@canopy-iiif/app 1.9.21 → 1.10.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.
@@ -953,8 +953,8 @@ function formatTemplate(template, replacements = {}) {
953
953
  });
954
954
  }
955
955
  function useLocaleMessages() {
956
- const PageContext2 = getSafePageContext();
957
- const context = PageContext2 ? React11.useContext(PageContext2) : null;
956
+ const PageContext3 = getSafePageContext();
957
+ const context = PageContext3 ? React11.useContext(PageContext3) : null;
958
958
  const siteMessages = context && context.site && context.site.localeMessages && typeof context.site.localeMessages === "object" ? context.site.localeMessages : null;
959
959
  return siteMessages || readRuntimeMessages();
960
960
  }
@@ -1130,8 +1130,8 @@ function Hero({
1130
1130
  const { getString } = useLocale();
1131
1131
  const normalizedVariant = normalizeVariant(variant);
1132
1132
  const isBreadcrumbVariant = normalizedVariant === "breadcrumb";
1133
- const PageContext2 = navigationHelpers && typeof navigationHelpers.getPageContext === "function" ? navigationHelpers.getPageContext() : null;
1134
- const pageContext = PageContext2 ? React12.useContext(PageContext2) : null;
1133
+ const PageContext3 = navigationHelpers && typeof navigationHelpers.getPageContext === "function" ? navigationHelpers.getPageContext() : null;
1134
+ const pageContext = PageContext3 ? React12.useContext(PageContext3) : null;
1135
1135
  let orderedSlides = [];
1136
1136
  if (!isBreadcrumbVariant) {
1137
1137
  const resolved = resolveFeaturedItem({ item, index, random });
@@ -1528,8 +1528,8 @@ function SubNavigation({
1528
1528
  heading,
1529
1529
  ariaLabel
1530
1530
  }) {
1531
- const PageContext2 = navigationHelpers2 && navigationHelpers2.getPageContext ? navigationHelpers2.getPageContext() : null;
1532
- const context = PageContext2 ? React14.useContext(PageContext2) : null;
1531
+ const PageContext3 = navigationHelpers2 && navigationHelpers2.getPageContext ? navigationHelpers2.getPageContext() : null;
1532
+ const context = PageContext3 ? React14.useContext(PageContext3) : null;
1533
1533
  const contextNavigation = context && context.navigation ? context.navigation : null;
1534
1534
  const contextPage = context && context.page ? context.page : null;
1535
1535
  const effectiveNavigation = navigationProp || contextNavigation;
@@ -1580,12 +1580,39 @@ function SubNavigation({
1580
1580
  );
1581
1581
  }
1582
1582
 
1583
- // ui/src/layout/Layout.jsx
1584
- import React16 from "react";
1585
- import navigationHelpers3 from "@canopy-iiif/app/lib/components/navigation.js";
1586
-
1587
1583
  // ui/src/layout/ContentNavigation.jsx
1588
1584
  import React15 from "react";
1585
+
1586
+ // ui/src/layout/headingUtils.js
1587
+ function buildHeadingTree(headings) {
1588
+ if (!Array.isArray(headings) || !headings.length) return [];
1589
+ const root = [];
1590
+ const stack = [];
1591
+ headings.forEach((heading) => {
1592
+ if (!heading || typeof heading !== "object") return;
1593
+ const depth = typeof heading.depth === "number" ? heading.depth : heading.level;
1594
+ if (typeof depth !== "number" || depth < 2) return;
1595
+ const entry = {
1596
+ id: heading.id || heading.slug || heading.title,
1597
+ title: heading.title || heading.text || heading.id,
1598
+ depth,
1599
+ children: []
1600
+ };
1601
+ while (stack.length && stack[stack.length - 1].depth >= entry.depth) {
1602
+ stack.pop();
1603
+ }
1604
+ if (!stack.length) {
1605
+ root.push(entry);
1606
+ } else {
1607
+ stack[stack.length - 1].children.push(entry);
1608
+ }
1609
+ stack.push(entry);
1610
+ });
1611
+ return root;
1612
+ }
1613
+
1614
+ // ui/src/layout/ContentNavigation.jsx
1615
+ var PageContext = typeof getSafePageContext === "function" ? getSafePageContext() : null;
1589
1616
  var SCROLL_OFFSET_REM = 1.618;
1590
1617
  var MAX_HEADING_DEPTH = 3;
1591
1618
  function resolveDepth(value, fallback = 1) {
@@ -1597,28 +1624,56 @@ function buildNodeKey(id, parentKey, index) {
1597
1624
  return `${parentKey || "section"}-${sanitized || index}`;
1598
1625
  }
1599
1626
  function ContentNavigation({
1600
- items = [],
1627
+ items: itemsProp = [],
1601
1628
  className = "",
1602
1629
  style = {},
1603
1630
  heading,
1604
1631
  headingId,
1605
1632
  pageTitle,
1606
- ariaLabel
1633
+ ariaLabel,
1634
+ collapsible = false
1607
1635
  }) {
1608
1636
  const { getString, formatString } = useLocale();
1637
+ const context = PageContext ? React15.useContext(PageContext) : null;
1638
+ const contextHeadings = React15.useMemo(() => {
1639
+ const headings = context && context.page ? context.page.headings : null;
1640
+ return Array.isArray(headings) ? headings : [];
1641
+ }, [context]);
1642
+ const resolvedItems = React15.useMemo(() => {
1643
+ if (itemsProp && itemsProp.length) return itemsProp;
1644
+ return buildHeadingTree(contextHeadings);
1645
+ }, [itemsProp, contextHeadings]);
1646
+ const topHeading = React15.useMemo(() => {
1647
+ return contextHeadings.find((entry) => {
1648
+ const depth = entry && (entry.depth || entry.level);
1649
+ return depth === 1;
1650
+ }) || null;
1651
+ }, [contextHeadings]);
1652
+ const resolvedHeadingId = headingId || topHeading && topHeading.id || null;
1653
+ const resolvedPageTitle = pageTitle || (context && context.page ? context.page.title : null) || null;
1654
+ const inferredHeading = topHeading && (topHeading.title || topHeading.text) || null;
1609
1655
  const isBrowser = typeof window !== "undefined" && typeof document !== "undefined";
1610
1656
  const savedDepthsRef = React15.useRef(null);
1611
- const [isExpanded, setIsExpanded] = React15.useState(false);
1657
+ const [internalExpanded, setInternalExpanded] = React15.useState(
1658
+ collapsible ? false : true
1659
+ );
1660
+ React15.useEffect(() => {
1661
+ setInternalExpanded(collapsible ? false : true);
1662
+ }, [collapsible]);
1612
1663
  const handleToggle = React15.useCallback(() => {
1613
- setIsExpanded((prev) => !prev);
1614
- }, []);
1615
- if ((!items || !items.length) && !headingId) return null;
1664
+ if (!collapsible) return;
1665
+ setInternalExpanded((prev) => !prev);
1666
+ }, [collapsible]);
1667
+ const isExpanded = collapsible ? internalExpanded : true;
1668
+ if ((!resolvedItems || !resolvedItems.length) && !resolvedHeadingId)
1669
+ return null;
1616
1670
  const combinedClassName = [
1617
1671
  "canopy-sub-navigation canopy-content-navigation",
1618
1672
  isExpanded ? "canopy-content-navigation--expanded" : "canopy-content-navigation--collapsed",
1673
+ !collapsible ? "canopy-content-navigation--static" : null,
1619
1674
  className
1620
1675
  ].filter(Boolean).join(" ");
1621
- const effectiveHeading = heading || pageTitle || null;
1676
+ const effectiveHeading = heading || inferredHeading || resolvedPageTitle || null;
1622
1677
  const fallbackNavLabel = getString(
1623
1678
  "common.nouns.section_navigation",
1624
1679
  "Section navigation"
@@ -1666,8 +1721,8 @@ function ContentNavigation({
1666
1721
  const headingEntries = React15.useMemo(() => {
1667
1722
  const entries = [];
1668
1723
  const seen = /* @__PURE__ */ new Set();
1669
- if (headingId) {
1670
- const topId = String(headingId);
1724
+ if (resolvedHeadingId) {
1725
+ const topId = String(resolvedHeadingId);
1671
1726
  entries.push({ id: topId, depth: 1 });
1672
1727
  seen.add(topId);
1673
1728
  }
@@ -1687,10 +1742,10 @@ function ContentNavigation({
1687
1742
  if (node.children && node.children.length) pushNodes(node.children);
1688
1743
  });
1689
1744
  };
1690
- pushNodes(items);
1745
+ pushNodes(resolvedItems);
1691
1746
  return entries;
1692
- }, [headingId, items, getSavedDepth]);
1693
- const fallbackId = headingEntries.length ? headingEntries[0].id : headingId || null;
1747
+ }, [resolvedHeadingId, resolvedItems, getSavedDepth]);
1748
+ const fallbackId = headingEntries.length ? headingEntries[0].id : resolvedHeadingId || null;
1694
1749
  const [activeId, setActiveId] = React15.useState(fallbackId);
1695
1750
  const activeIdRef = React15.useRef(activeId);
1696
1751
  React15.useEffect(() => {
@@ -1802,7 +1857,7 @@ function ContentNavigation({
1802
1857
  }
1803
1858
  }
1804
1859
  if (!Number.isFinite(top) || top < 0 || options.scrollToTop) top = 0;
1805
- const nextId = targetId && targetId !== "top" ? targetId : ((_a = headingEntries[0]) == null ? void 0 : _a.id) || headingId || null;
1860
+ const nextId = targetId && targetId !== "top" ? targetId : ((_a = headingEntries[0]) == null ? void 0 : _a.id) || resolvedHeadingId || null;
1806
1861
  if (nextId) {
1807
1862
  activeIdRef.current = nextId;
1808
1863
  setActiveId(nextId);
@@ -1813,7 +1868,7 @@ function ContentNavigation({
1813
1868
  window.scrollTo(0, top);
1814
1869
  }
1815
1870
  },
1816
- [computeOffsetPx, headingEntries, headingId, isBrowser]
1871
+ [computeOffsetPx, headingEntries, resolvedHeadingId, isBrowser]
1817
1872
  );
1818
1873
  const navTreeRoot = React15.useMemo(() => {
1819
1874
  function mapNodes(nodes2, parentKey = "section") {
@@ -1847,13 +1902,19 @@ function ContentNavigation({
1847
1902
  };
1848
1903
  }).filter(Boolean);
1849
1904
  }
1850
- const nodes = mapNodes(items, "section");
1905
+ const nodes = mapNodes(resolvedItems, "section");
1851
1906
  return {
1852
1907
  slug: "content-nav-root",
1853
- title: effectiveHeading || pageTitle || onThisPageLabel,
1908
+ title: effectiveHeading || resolvedPageTitle || onThisPageLabel,
1854
1909
  children: nodes
1855
1910
  };
1856
- }, [items, effectiveHeading, pageTitle, activeId, getSavedDepth]);
1911
+ }, [
1912
+ resolvedItems,
1913
+ effectiveHeading,
1914
+ resolvedPageTitle,
1915
+ activeId,
1916
+ getSavedDepth
1917
+ ]);
1857
1918
  return /* @__PURE__ */ React15.createElement(
1858
1919
  "nav",
1859
1920
  {
@@ -1862,7 +1923,7 @@ function ContentNavigation({
1862
1923
  "aria-label": navLabel,
1863
1924
  "data-canopy-content-nav": "true"
1864
1925
  },
1865
- /* @__PURE__ */ React15.createElement(
1926
+ collapsible ? /* @__PURE__ */ React15.createElement(
1866
1927
  "button",
1867
1928
  {
1868
1929
  type: "button",
@@ -1951,7 +2012,7 @@ function ContentNavigation({
1951
2012
  /* @__PURE__ */ React15.createElement("span", { className: "sr-only" }, toggleSrLabel)
1952
2013
  ),
1953
2014
  /* @__PURE__ */ React15.createElement("span", { className: "sr-only", "data-canopy-content-nav-toggle-sr": "true" }, toggleSrLabel)
1954
- ),
2015
+ ) : null,
1955
2016
  /* @__PURE__ */ React15.createElement(
1956
2017
  NavigationTree,
1957
2018
  {
@@ -1964,42 +2025,8 @@ function ContentNavigation({
1964
2025
  );
1965
2026
  }
1966
2027
 
1967
- // ui/src/layout/Layout.jsx
1968
- function buildHeadingTree(headings) {
1969
- if (!Array.isArray(headings) || !headings.length) return [];
1970
- const root = [];
1971
- const stack = [];
1972
- headings.forEach((heading) => {
1973
- if (!heading || typeof heading !== "object") return;
1974
- const depth = typeof heading.depth === "number" ? heading.depth : heading.level;
1975
- if (typeof depth !== "number" || depth < 2) return;
1976
- const entry = {
1977
- id: heading.id || heading.slug || heading.title,
1978
- title: heading.title || heading.text || heading.id,
1979
- depth,
1980
- children: []
1981
- };
1982
- while (stack.length && stack[stack.length - 1].depth >= entry.depth) {
1983
- stack.pop();
1984
- }
1985
- if (!stack.length) {
1986
- root.push(entry);
1987
- } else {
1988
- stack[stack.length - 1].children.push(entry);
1989
- }
1990
- stack.push(entry);
1991
- });
1992
- return root;
1993
- }
1994
- function buildNavigationAside(sidebar, className) {
1995
- if (!sidebar) {
1996
- return /* @__PURE__ */ React16.createElement(SubNavigation, { className });
1997
- }
1998
- if (typeof sidebar === "function") {
1999
- return React16.createElement(sidebar);
2000
- }
2001
- return sidebar;
2002
- }
2028
+ // ui/src/layout/ContentNavigationScript.jsx
2029
+ import React16 from "react";
2003
2030
  function ContentNavigationScript() {
2004
2031
  const code = `
2005
2032
  (function () {
@@ -2085,16 +2112,32 @@ function ContentNavigationScript() {
2085
2112
  function setupFloatingState(root) {
2086
2113
  if (!root || typeof IntersectionObserver !== 'function') return;
2087
2114
  if (root.__canopyContentNavFloating) return;
2115
+ var nav = root.querySelector('[data-canopy-content-nav]');
2116
+ if (!nav) return;
2088
2117
  var sentinel = root.querySelector('[data-canopy-content-nav-sentinel]');
2118
+ if (!sentinel) {
2119
+ sentinel = document.createElement('div');
2120
+ sentinel.setAttribute('aria-hidden', 'true');
2121
+ sentinel.setAttribute('data-canopy-content-nav-sentinel', 'true');
2122
+ root.insertBefore(sentinel, nav);
2123
+ }
2089
2124
  var placeholder = root.querySelector('[data-canopy-content-nav-placeholder]');
2090
- var nav = root.querySelector('[data-canopy-content-nav]');
2091
- if (!sentinel || !nav) return;
2125
+ if (!placeholder) {
2126
+ placeholder = document.createElement('div');
2127
+ placeholder.setAttribute('aria-hidden', 'true');
2128
+ placeholder.setAttribute('data-canopy-content-nav-placeholder', 'true');
2129
+ if (nav.nextSibling) {
2130
+ root.insertBefore(placeholder, nav.nextSibling);
2131
+ } else {
2132
+ root.appendChild(placeholder);
2133
+ }
2134
+ }
2092
2135
  root.__canopyContentNavFloating = true;
2093
2136
 
2094
2137
  function syncPosition() {
2095
2138
  try {
2096
2139
  var rect = root.getBoundingClientRect();
2097
- nav.style.setProperty('--canopy-content-nav-fixed-right', '1.618rem');
2140
+ nav.style.setProperty('--canopy-content-nav-fixed-left', rect.left + 'px');
2098
2141
  nav.style.setProperty('--canopy-content-nav-fixed-width', rect.width + 'px');
2099
2142
  if (placeholder) placeholder.style.width = rect.width + 'px';
2100
2143
  } catch (_) {}
@@ -2266,10 +2309,44 @@ function ContentNavigationScript() {
2266
2309
  }
2267
2310
 
2268
2311
  ready(function () {
2269
- var roots = Array.prototype.slice.call(
2270
- document.querySelectorAll('[data-canopy-content-nav-root]')
2312
+ var rootSet = new Set();
2313
+ var navNodes = Array.prototype.slice.call(
2314
+ document.querySelectorAll('[data-canopy-content-nav]')
2271
2315
  );
2316
+ navNodes.forEach(function (nav) {
2317
+ if (!nav || !nav.closest) return;
2318
+ var root = nav.closest('[data-canopy-content-nav-root]');
2319
+ if (!root) {
2320
+ root = nav.parentElement || nav;
2321
+ if (root && !root.hasAttribute('data-canopy-content-nav-root')) {
2322
+ root.setAttribute('data-canopy-content-nav-root', 'true');
2323
+ }
2324
+ }
2325
+ if (root) rootSet.add(root);
2326
+ });
2327
+
2328
+ var roots = Array.from(rootSet);
2272
2329
  if (!roots.length) return;
2330
+
2331
+ var collapsibleRoots = [];
2332
+ roots.forEach(function (root) {
2333
+ var nav = root.querySelector('[data-canopy-content-nav]');
2334
+ if (!nav) return;
2335
+ var isStatic = nav.classList.contains('canopy-content-navigation--static');
2336
+ if (isStatic) {
2337
+ root.classList.remove('is-collapsed');
2338
+ nav.classList.add('canopy-content-navigation--expanded');
2339
+ nav.classList.remove('canopy-content-navigation--collapsed');
2340
+ nav.setAttribute('data-expanded', 'true');
2341
+ } else {
2342
+ collapsibleRoots.push(root);
2343
+ }
2344
+ setupFloatingState(root);
2345
+ setupActiveHeadingWatcher(root);
2346
+ });
2347
+
2348
+ if (!collapsibleRoots.length) return;
2349
+
2273
2350
  var stored = getStored();
2274
2351
  var collapsed = true;
2275
2352
  var isDesktop = false;
@@ -2289,7 +2366,7 @@ function ContentNavigationScript() {
2289
2366
 
2290
2367
  function sync(next) {
2291
2368
  collapsed = !!next;
2292
- roots.forEach(function (root) {
2369
+ collapsibleRoots.forEach(function (root) {
2293
2370
  applyState(root, collapsed);
2294
2371
  });
2295
2372
  setStored(collapsed ? '1' : '0');
@@ -2297,7 +2374,7 @@ function ContentNavigationScript() {
2297
2374
 
2298
2375
  sync(collapsed);
2299
2376
 
2300
- roots.forEach(function (root) {
2377
+ collapsibleRoots.forEach(function (root) {
2301
2378
  var toggle = root.querySelector('[data-canopy-content-nav-toggle]');
2302
2379
  if (!toggle) return;
2303
2380
  toggle.addEventListener('click', function (event) {
@@ -2305,16 +2382,23 @@ function ContentNavigationScript() {
2305
2382
  sync(!collapsed);
2306
2383
  });
2307
2384
  });
2308
-
2309
- roots.forEach(function (root) {
2310
- setupFloatingState(root);
2311
- setupActiveHeadingWatcher(root);
2312
- });
2313
2385
  });
2314
2386
  })();
2315
2387
  `;
2316
2388
  return /* @__PURE__ */ React16.createElement("script", { dangerouslySetInnerHTML: { __html: code } });
2317
2389
  }
2390
+
2391
+ // ui/src/layout/Layout.jsx
2392
+ import React17 from "react";
2393
+ function buildNavigationAside(sidebar, className) {
2394
+ if (!sidebar) {
2395
+ return /* @__PURE__ */ React17.createElement(SubNavigation, { className });
2396
+ }
2397
+ if (typeof sidebar === "function") {
2398
+ return React17.createElement(sidebar);
2399
+ }
2400
+ return sidebar;
2401
+ }
2318
2402
  function Layout({
2319
2403
  children,
2320
2404
  sidebar,
@@ -2327,27 +2411,27 @@ function Layout({
2327
2411
  contentNavigationClassName = "",
2328
2412
  ...rest
2329
2413
  }) {
2330
- const PageContext2 = navigationHelpers3 && typeof navigationHelpers3.getPageContext === "function" ? navigationHelpers3.getPageContext() : null;
2331
- const context = PageContext2 ? React16.useContext(PageContext2) : null;
2332
- const pageHeadings = React16.useMemo(() => {
2414
+ const PageContext3 = typeof getSafePageContext === "function" ? getSafePageContext() : null;
2415
+ const context = PageContext3 ? React17.useContext(PageContext3) : null;
2416
+ const pageHeadings = React17.useMemo(() => {
2333
2417
  const headings = context && context.page ? context.page.headings : null;
2334
2418
  return Array.isArray(headings) ? headings : [];
2335
2419
  }, [context]);
2336
- const contentHeading = React16.useMemo(() => {
2420
+ const contentHeading = React17.useMemo(() => {
2337
2421
  const first = pageHeadings.find((heading) => {
2338
2422
  const depth = heading && (heading.depth || heading.level);
2339
2423
  return depth === 1;
2340
2424
  });
2341
2425
  return first && first.title ? first.title : null;
2342
2426
  }, [pageHeadings]);
2343
- const headingAnchorId = React16.useMemo(() => {
2427
+ const headingAnchorId = React17.useMemo(() => {
2344
2428
  const first = pageHeadings.find((heading) => {
2345
2429
  const depth = heading && (heading.depth || heading.level);
2346
2430
  return depth === 1;
2347
2431
  });
2348
2432
  return first && first.id ? first.id : null;
2349
2433
  }, [pageHeadings]);
2350
- const headingTree = React16.useMemo(
2434
+ const headingTree = React17.useMemo(
2351
2435
  () => buildHeadingTree(pageHeadings),
2352
2436
  [pageHeadings]
2353
2437
  );
@@ -2372,50 +2456,37 @@ function Layout({
2372
2456
  contentNavigationClassName
2373
2457
  ].filter(Boolean).join(" ");
2374
2458
  const sidebarNode = showLeftColumn ? buildNavigationAside(sidebar, sidebarClassName) : null;
2375
- return /* @__PURE__ */ React16.createElement("div", { className: containerClassName, ...rest }, showLeftColumn ? /* @__PURE__ */ React16.createElement("aside", { className: leftAsideClassName }, sidebarNode) : null, /* @__PURE__ */ React16.createElement("div", { className: contentClassNames }, children), hasContentNavigation ? /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(
2459
+ return /* @__PURE__ */ React17.createElement("div", { className: containerClassName, ...rest }, showLeftColumn ? /* @__PURE__ */ React17.createElement("aside", { className: leftAsideClassName }, sidebarNode) : null, /* @__PURE__ */ React17.createElement("div", { className: contentClassNames }, children), hasContentNavigation ? /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement(
2376
2460
  "aside",
2377
2461
  {
2378
2462
  className: contentNavigationAsideClassName,
2379
2463
  "data-canopy-content-nav-root": "true"
2380
2464
  },
2381
- /* @__PURE__ */ React16.createElement(
2382
- "div",
2383
- {
2384
- "data-canopy-content-nav-sentinel": "true",
2385
- "aria-hidden": "true"
2386
- }
2387
- ),
2388
- /* @__PURE__ */ React16.createElement(
2465
+ /* @__PURE__ */ React17.createElement(
2389
2466
  ContentNavigation,
2390
2467
  {
2391
2468
  items: headingTree,
2392
2469
  heading: contentHeading || void 0,
2393
2470
  headingId: headingAnchorId || void 0,
2394
- pageTitle: context && context.page ? context.page.title : void 0
2395
- }
2396
- ),
2397
- /* @__PURE__ */ React16.createElement(
2398
- "div",
2399
- {
2400
- "data-canopy-content-nav-placeholder": "true",
2401
- "aria-hidden": "true"
2471
+ pageTitle: context && context.page ? context.page.title : void 0,
2472
+ collapsible: true
2402
2473
  }
2403
2474
  )
2404
- ), /* @__PURE__ */ React16.createElement(ContentNavigationScript, null)) : null);
2475
+ ), /* @__PURE__ */ React17.createElement(ContentNavigationScript, null)) : null);
2405
2476
  }
2406
2477
 
2407
2478
  // ui/src/layout/CanopyHeader.jsx
2408
- import React25 from "react";
2479
+ import React26 from "react";
2409
2480
 
2410
2481
  // ui/src/search/SearchPanel.jsx
2411
- import React20 from "react";
2482
+ import React21 from "react";
2412
2483
 
2413
2484
  // ui/src/Icons.jsx
2414
- import React17 from "react";
2415
- var MagnifyingGlassIcon = (props) => /* @__PURE__ */ React17.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512", "aria-hidden": "true", focusable: "false", ...props }, /* @__PURE__ */ React17.createElement("path", { d: "M456.69 421.39L362.6 327.3a173.81 173.81 0 0034.84-104.58C397.44 126.38 319.06 48 222.72 48S48 126.38 48 222.72s78.38 174.72 174.72 174.72A173.81 173.81 0 00327.3 362.6l94.09 94.09a25 25 0 0035.3-35.3zM97.92 222.72a124.8 124.8 0 11124.8 124.8 124.95 124.95 0 01-124.8-124.8z" }));
2485
+ import React18 from "react";
2486
+ var MagnifyingGlassIcon = (props) => /* @__PURE__ */ React18.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512", "aria-hidden": "true", focusable: "false", ...props }, /* @__PURE__ */ React18.createElement("path", { d: "M456.69 421.39L362.6 327.3a173.81 173.81 0 0034.84-104.58C397.44 126.38 319.06 48 222.72 48S48 126.38 48 222.72s78.38 174.72 174.72 174.72A173.81 173.81 0 00327.3 362.6l94.09 94.09a25 25 0 0035.3-35.3zM97.92 222.72a124.8 124.8 0 11124.8 124.8 124.95 124.95 0 01-124.8-124.8z" }));
2416
2487
 
2417
2488
  // ui/src/search/SearchPanelForm.jsx
2418
- import React18 from "react";
2489
+ import React19 from "react";
2419
2490
  function readBasePath2() {
2420
2491
  const normalize = (val) => {
2421
2492
  const raw = typeof val === "string" ? val.trim() : "";
@@ -2487,18 +2558,18 @@ function SearchPanelForm(props = {}) {
2487
2558
  { content: searchLabel }
2488
2559
  );
2489
2560
  const text = typeof label === "string" && label.trim() ? label.trim() : buttonText;
2490
- const action = React18.useMemo(
2561
+ const action = React19.useMemo(
2491
2562
  () => resolveSearchPath(searchPath),
2492
2563
  [searchPath]
2493
2564
  );
2494
- const autoId = typeof React18.useId === "function" ? React18.useId() : void 0;
2495
- const [fallbackId] = React18.useState(
2565
+ const autoId = typeof React19.useId === "function" ? React19.useId() : void 0;
2566
+ const [fallbackId] = React19.useState(
2496
2567
  () => `canopy-search-form-${Math.random().toString(36).slice(2, 10)}`
2497
2568
  );
2498
2569
  const inputId = inputIdProp || autoId || fallbackId;
2499
- const inputRef = React18.useRef(null);
2500
- const [hasValue, setHasValue] = React18.useState(false);
2501
- const focusInput = React18.useCallback(() => {
2570
+ const inputRef = React19.useRef(null);
2571
+ const [hasValue, setHasValue] = React19.useState(false);
2572
+ const focusInput = React19.useCallback(() => {
2502
2573
  const el = inputRef.current;
2503
2574
  if (!el) return;
2504
2575
  if (document.activeElement === el) return;
@@ -2511,7 +2582,7 @@ function SearchPanelForm(props = {}) {
2511
2582
  }
2512
2583
  }
2513
2584
  }, []);
2514
- const handlePointerDown = React18.useCallback(
2585
+ const handlePointerDown = React19.useCallback(
2515
2586
  (event) => {
2516
2587
  const target = event.target;
2517
2588
  if (target && typeof target.closest === "function") {
@@ -2523,23 +2594,23 @@ function SearchPanelForm(props = {}) {
2523
2594
  },
2524
2595
  [focusInput]
2525
2596
  );
2526
- React18.useEffect(() => {
2597
+ React19.useEffect(() => {
2527
2598
  const el = inputRef.current;
2528
2599
  if (!el) return;
2529
2600
  if (el.value && el.value.trim()) {
2530
2601
  setHasValue(true);
2531
2602
  }
2532
2603
  }, []);
2533
- const handleInputChange = React18.useCallback((event) => {
2604
+ const handleInputChange = React19.useCallback((event) => {
2534
2605
  var _a;
2535
2606
  const nextHasValue = Boolean(
2536
2607
  ((_a = event == null ? void 0 : event.target) == null ? void 0 : _a.value) && event.target.value.trim()
2537
2608
  );
2538
2609
  setHasValue(nextHasValue);
2539
2610
  }, []);
2540
- const handleClear = React18.useCallback((event) => {
2611
+ const handleClear = React19.useCallback((event) => {
2541
2612
  }, []);
2542
- const handleClearKey = React18.useCallback(
2613
+ const handleClearKey = React19.useCallback(
2543
2614
  (event) => {
2544
2615
  if (event.key === "Enter" || event.key === " ") {
2545
2616
  event.preventDefault();
@@ -2548,7 +2619,7 @@ function SearchPanelForm(props = {}) {
2548
2619
  },
2549
2620
  [handleClear]
2550
2621
  );
2551
- return /* @__PURE__ */ React18.createElement(
2622
+ return /* @__PURE__ */ React19.createElement(
2552
2623
  "form",
2553
2624
  {
2554
2625
  action,
@@ -2560,7 +2631,7 @@ function SearchPanelForm(props = {}) {
2560
2631
  onPointerDown: handlePointerDown,
2561
2632
  "data-has-value": hasValue ? "1" : "0"
2562
2633
  },
2563
- /* @__PURE__ */ React18.createElement("label", { htmlFor: inputId, className: "canopy-search-form__label" }, /* @__PURE__ */ React18.createElement(MagnifyingGlassIcon, { className: "canopy-search-form__icon" }), /* @__PURE__ */ React18.createElement("span", { className: "sr-only" }, searchLabel), /* @__PURE__ */ React18.createElement(
2634
+ /* @__PURE__ */ React19.createElement("label", { htmlFor: inputId, className: "canopy-search-form__label" }, /* @__PURE__ */ React19.createElement(MagnifyingGlassIcon, { className: "canopy-search-form__icon" }), /* @__PURE__ */ React19.createElement("span", { className: "sr-only" }, searchLabel), /* @__PURE__ */ React19.createElement(
2564
2635
  "input",
2565
2636
  {
2566
2637
  id: inputId,
@@ -2575,7 +2646,7 @@ function SearchPanelForm(props = {}) {
2575
2646
  onInput: handleInputChange
2576
2647
  }
2577
2648
  )),
2578
- hasValue ? /* @__PURE__ */ React18.createElement(
2649
+ hasValue ? /* @__PURE__ */ React19.createElement(
2579
2650
  "button",
2580
2651
  {
2581
2652
  type: "button",
@@ -2588,7 +2659,7 @@ function SearchPanelForm(props = {}) {
2588
2659
  },
2589
2660
  "\xD7"
2590
2661
  ) : null,
2591
- /* @__PURE__ */ React18.createElement(
2662
+ /* @__PURE__ */ React19.createElement(
2592
2663
  "button",
2593
2664
  {
2594
2665
  type: "submit",
@@ -2601,11 +2672,11 @@ function SearchPanelForm(props = {}) {
2601
2672
  }
2602
2673
 
2603
2674
  // ui/src/search/SearchPanelTeaserResults.jsx
2604
- import React19 from "react";
2675
+ import React20 from "react";
2605
2676
  function SearchPanelTeaserResults(props = {}) {
2606
2677
  const { style, className } = props || {};
2607
2678
  const classes = ["canopy-search-teaser", "is-empty", className].filter(Boolean).join(" ");
2608
- return /* @__PURE__ */ React19.createElement(
2679
+ return /* @__PURE__ */ React20.createElement(
2609
2680
  "div",
2610
2681
  {
2611
2682
  "data-canopy-search-form-panel": true,
@@ -2613,7 +2684,7 @@ function SearchPanelTeaserResults(props = {}) {
2613
2684
  className: classes || void 0,
2614
2685
  style
2615
2686
  },
2616
- /* @__PURE__ */ React19.createElement("div", { id: "cplist", className: "canopy-search-teaser__list" })
2687
+ /* @__PURE__ */ React20.createElement("div", { id: "cplist", className: "canopy-search-teaser__list" })
2617
2688
  );
2618
2689
  }
2619
2690
 
@@ -2637,25 +2708,25 @@ function SearchPanel(props = {}) {
2637
2708
  const text = typeof label === "string" && label.trim() ? label.trim() : resolvedButtonLabel;
2638
2709
  const resolvedSearchPath = resolveSearchPath(searchPath);
2639
2710
  const data = { placeholder, hotkey, maxResults, groupOrder, label: text, searchPath: resolvedSearchPath };
2640
- return /* @__PURE__ */ React20.createElement("div", { "data-canopy-search-form": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React20.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React20.createElement(SearchPanelForm, { placeholder, buttonLabel: resolvedButtonLabel, label, searchPath: resolvedSearchPath }), /* @__PURE__ */ React20.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React20.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
2711
+ return /* @__PURE__ */ React21.createElement("div", { "data-canopy-search-form": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React21.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React21.createElement(SearchPanelForm, { placeholder, buttonLabel: resolvedButtonLabel, label, searchPath: resolvedSearchPath }), /* @__PURE__ */ React21.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React21.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
2641
2712
  }
2642
2713
 
2643
2714
  // ui/src/layout/CanopyBrand.jsx
2644
- import React21 from "react";
2645
- var PageContext = getSafePageContext();
2715
+ import React22 from "react";
2716
+ var PageContext2 = getSafePageContext();
2646
2717
  function CanopyBrand(props = {}) {
2647
2718
  const { labelId, label: labelProp, href = "/", className, Logo } = props || {};
2648
- const context = React21.useContext(PageContext);
2719
+ const context = React22.useContext(PageContext2);
2649
2720
  const contextSiteTitle = context && context.site && typeof context.site.title === "string" ? context.site.title.trim() : "";
2650
2721
  const normalizedLabel = typeof labelProp === "string" && labelProp.trim() ? labelProp : "";
2651
2722
  const resolvedLabel = normalizedLabel || contextSiteTitle || "Site title";
2652
2723
  const spanProps = labelId ? { id: labelId } : {};
2653
2724
  const classes = ["canopy-logo", className].filter(Boolean).join(" ");
2654
- return /* @__PURE__ */ React21.createElement("a", { href, className: classes }, typeof Logo === "function" ? /* @__PURE__ */ React21.createElement(Logo, null) : null, /* @__PURE__ */ React21.createElement("span", { ...spanProps }, resolvedLabel));
2725
+ return /* @__PURE__ */ React22.createElement("a", { href, className: classes }, typeof Logo === "function" ? /* @__PURE__ */ React22.createElement(Logo, null) : null, /* @__PURE__ */ React22.createElement("span", { ...spanProps }, resolvedLabel));
2655
2726
  }
2656
2727
 
2657
2728
  // ui/src/layout/CanopyModal.jsx
2658
- import React22 from "react";
2729
+ import React23 from "react";
2659
2730
  function CanopyModal(props = {}) {
2660
2731
  const {
2661
2732
  id,
@@ -2708,7 +2779,7 @@ function CanopyModal(props = {}) {
2708
2779
  if (padded) bodyClasses.push("canopy-modal__body--padded");
2709
2780
  if (bodyClassName) bodyClasses.push(bodyClassName);
2710
2781
  const bodyClassNameValue = bodyClasses.join(" ");
2711
- return /* @__PURE__ */ React22.createElement("div", { ...modalProps }, /* @__PURE__ */ React22.createElement("div", { className: "canopy-modal__panel" }, /* @__PURE__ */ React22.createElement("button", { ...closeButtonProps }, /* @__PURE__ */ React22.createElement(
2782
+ return /* @__PURE__ */ React23.createElement("div", { ...modalProps }, /* @__PURE__ */ React23.createElement("div", { className: "canopy-modal__panel" }, /* @__PURE__ */ React23.createElement("button", { ...closeButtonProps }, /* @__PURE__ */ React23.createElement(
2712
2783
  "svg",
2713
2784
  {
2714
2785
  xmlns: "http://www.w3.org/2000/svg",
@@ -2718,8 +2789,8 @@ function CanopyModal(props = {}) {
2718
2789
  strokeWidth: "1.5",
2719
2790
  className: "canopy-modal__close-icon"
2720
2791
  },
2721
- /* @__PURE__ */ React22.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 6l12 12M6 18L18 6" })
2722
- ), /* @__PURE__ */ React22.createElement("span", { className: "sr-only" }, resolvedCloseLabel)), /* @__PURE__ */ React22.createElement("div", { className: bodyClassNameValue }, label ? /* @__PURE__ */ React22.createElement("div", { className: "canopy-modal__brand" }, /* @__PURE__ */ React22.createElement(
2792
+ /* @__PURE__ */ React23.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 6l12 12M6 18L18 6" })
2793
+ ), /* @__PURE__ */ React23.createElement("span", { className: "sr-only" }, resolvedCloseLabel)), /* @__PURE__ */ React23.createElement("div", { className: bodyClassNameValue }, label ? /* @__PURE__ */ React23.createElement("div", { className: "canopy-modal__brand" }, /* @__PURE__ */ React23.createElement(
2723
2794
  CanopyBrand,
2724
2795
  {
2725
2796
  labelId: resolvedLabelId,
@@ -2732,10 +2803,10 @@ function CanopyModal(props = {}) {
2732
2803
  }
2733
2804
 
2734
2805
  // ui/src/layout/LanguageToggle.jsx
2735
- import React24 from "react";
2806
+ import React25 from "react";
2736
2807
 
2737
2808
  // ui/src/layout/languageToggleShared.jsx
2738
- import React23 from "react";
2809
+ import React24 from "react";
2739
2810
  function readBasePath3() {
2740
2811
  const normalize = (value) => {
2741
2812
  if (!value) return "";
@@ -2894,13 +2965,13 @@ function LanguageToggleControl({
2894
2965
  ].filter(Boolean).join(" ").trim();
2895
2966
  const ariaLabel = config.label || "Language";
2896
2967
  const resolvedControl = control === "list" ? "list" : "select";
2897
- const selectId = typeof React23.useId === "function" && resolvedControl === "select" ? React23.useId() : void 0;
2968
+ const selectId = typeof React24.useId === "function" && resolvedControl === "select" ? React24.useId() : void 0;
2898
2969
  const links = Array.isArray(config.links) ? config.links : [];
2899
2970
  if (!links.length) return null;
2900
2971
  const activeLink = links.find((link) => link.isActive);
2901
2972
  const fallbackHref = links[0].href;
2902
2973
  const selectedHref = activeLink ? activeLink.href : fallbackHref;
2903
- const navigate = React23.useCallback((href) => {
2974
+ const navigate = React24.useCallback((href) => {
2904
2975
  if (!href) return;
2905
2976
  try {
2906
2977
  if (typeof window !== "undefined" && window.location) {
@@ -2920,7 +2991,7 @@ function LanguageToggleControl({
2920
2991
  } catch (_) {
2921
2992
  }
2922
2993
  }, []);
2923
- const handleSelectChange = React23.useCallback(
2994
+ const handleSelectChange = React24.useCallback(
2924
2995
  (event) => {
2925
2996
  if (!event || !event.target) return;
2926
2997
  const nextHref = event.target.value;
@@ -2929,15 +3000,15 @@ function LanguageToggleControl({
2929
3000
  },
2930
3001
  [navigate, selectedHref]
2931
3002
  );
2932
- const labelElement = showLabel && config.label ? resolvedControl === "select" ? /* @__PURE__ */ React23.createElement(
3003
+ const labelElement = showLabel && config.label ? resolvedControl === "select" ? /* @__PURE__ */ React24.createElement(
2933
3004
  "label",
2934
3005
  {
2935
3006
  className: "canopy-language-toggle__label",
2936
3007
  htmlFor: selectId
2937
3008
  },
2938
3009
  config.label
2939
- ) : /* @__PURE__ */ React23.createElement("span", { className: "canopy-language-toggle__label" }, config.label) : null;
2940
- return /* @__PURE__ */ React23.createElement("div", { className: classes || void 0 }, labelElement, resolvedControl === "select" ? /* @__PURE__ */ React23.createElement("div", { className: "canopy-language-toggle__select" }, /* @__PURE__ */ React23.createElement(
3010
+ ) : /* @__PURE__ */ React24.createElement("span", { className: "canopy-language-toggle__label" }, config.label) : null;
3011
+ return /* @__PURE__ */ React24.createElement("div", { className: classes || void 0 }, labelElement, resolvedControl === "select" ? /* @__PURE__ */ React24.createElement("div", { className: "canopy-language-toggle__select" }, /* @__PURE__ */ React24.createElement(
2941
3012
  "select",
2942
3013
  {
2943
3014
  id: selectId,
@@ -2947,7 +3018,7 @@ function LanguageToggleControl({
2947
3018
  "aria-label": ariaLabel,
2948
3019
  "data-canopy-language-select": "true"
2949
3020
  },
2950
- links.map((link) => /* @__PURE__ */ React23.createElement(
3021
+ links.map((link) => /* @__PURE__ */ React24.createElement(
2951
3022
  "option",
2952
3023
  {
2953
3024
  key: link.lang,
@@ -2957,7 +3028,7 @@ function LanguageToggleControl({
2957
3028
  },
2958
3029
  link.label
2959
3030
  ))
2960
- )) : /* @__PURE__ */ React23.createElement("nav", { className: "canopy-language-toggle__nav", "aria-label": ariaLabel }, /* @__PURE__ */ React23.createElement("ul", { className: "canopy-language-toggle__list", role: "list" }, links.map((link) => /* @__PURE__ */ React23.createElement("li", { key: link.lang }, /* @__PURE__ */ React23.createElement(
3031
+ )) : /* @__PURE__ */ React24.createElement("nav", { className: "canopy-language-toggle__nav", "aria-label": ariaLabel }, /* @__PURE__ */ React24.createElement("ul", { className: "canopy-language-toggle__list", role: "list" }, links.map((link) => /* @__PURE__ */ React24.createElement("li", { key: link.lang }, /* @__PURE__ */ React24.createElement(
2961
3032
  "button",
2962
3033
  {
2963
3034
  type: "button",
@@ -2969,7 +3040,7 @@ function LanguageToggleControl({
2969
3040
  onClick: () => navigate(link.href)
2970
3041
  },
2971
3042
  link.label
2972
- ))))), /* @__PURE__ */ React23.createElement(LanguageToggleRuntime, null));
3043
+ ))))), /* @__PURE__ */ React24.createElement(LanguageToggleRuntime, null));
2973
3044
  }
2974
3045
  function LanguageToggleRuntime() {
2975
3046
  const code = `
@@ -3029,7 +3100,7 @@ function LanguageToggleRuntime() {
3029
3100
  }
3030
3101
  })();
3031
3102
  `;
3032
- return /* @__PURE__ */ React23.createElement("script", { dangerouslySetInnerHTML: { __html: code } });
3103
+ return /* @__PURE__ */ React24.createElement("script", { dangerouslySetInnerHTML: { __html: code } });
3033
3104
  }
3034
3105
 
3035
3106
  // ui/src/layout/LanguageToggle.jsx
@@ -3043,8 +3114,8 @@ function LanguageToggle({
3043
3114
  label,
3044
3115
  ariaLabel
3045
3116
  }) {
3046
- const PageContext2 = getSafePageContext();
3047
- const context = React24.useContext(PageContext2);
3117
+ const PageContext3 = getSafePageContext();
3118
+ const context = React25.useContext(PageContext3);
3048
3119
  const siteLanguageToggle = context && context.site && context.site.languageToggle || null;
3049
3120
  const pageData = page || (context && context.page ? context.page : null);
3050
3121
  const resolvedToggle = languageToggle === false ? null : languageToggle === true || typeof languageToggle === "undefined" ? siteLanguageToggle : languageToggle;
@@ -3053,7 +3124,7 @@ function LanguageToggle({
3053
3124
  resolvedToggle && typeof resolvedToggle.control === "string" ? resolvedToggle.control : null
3054
3125
  );
3055
3126
  const resolvedControl = normalizeControl(typeof control === "string" ? control : null) || toggleControl || "select";
3056
- const config = React24.useMemo(() => {
3127
+ const config = React25.useMemo(() => {
3057
3128
  if (!resolvedToggle) return null;
3058
3129
  const base = buildLanguageToggleConfig(resolvedToggle, pageData);
3059
3130
  if (!base) return null;
@@ -3064,7 +3135,7 @@ function LanguageToggle({
3064
3135
  };
3065
3136
  }, [resolvedToggle, pageData, label, ariaLabel]);
3066
3137
  if (!config) return null;
3067
- return /* @__PURE__ */ React24.createElement(
3138
+ return /* @__PURE__ */ React25.createElement(
3068
3139
  LanguageToggleControl,
3069
3140
  {
3070
3141
  config,
@@ -3366,7 +3437,7 @@ function HeaderScript() {
3366
3437
  });
3367
3438
  })();
3368
3439
  `;
3369
- return /* @__PURE__ */ React25.createElement(
3440
+ return /* @__PURE__ */ React26.createElement(
3370
3441
  "script",
3371
3442
  {
3372
3443
  dangerouslySetInnerHTML: {
@@ -3442,8 +3513,8 @@ function CanopyHeader(props = {}) {
3442
3513
  logo: SiteLogo,
3443
3514
  languageToggle: languageToggleProp
3444
3515
  } = props;
3445
- const PageContext2 = getSafePageContext();
3446
- const context = React25.useContext(PageContext2);
3516
+ const PageContext3 = getSafePageContext();
3517
+ const context = React26.useContext(PageContext3);
3447
3518
  const { getString, formatString } = useLocale();
3448
3519
  const contextPrimaryNav = context && Array.isArray(context.primaryNavigation) ? context.primaryNavigation : [];
3449
3520
  const navLinks = navLinksProp && navLinksProp.length ? ensureArray(navLinksProp) : ensureArray(contextPrimaryNav);
@@ -3519,14 +3590,14 @@ function CanopyHeader(props = {}) {
3519
3590
  return !!(rootNode && Array.isArray(rootNode.children) && rootNode.children.length);
3520
3591
  };
3521
3592
  const hasIntegratedSectionNav = navLinks.some(shouldAttachSectionNav);
3522
- return /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement(
3593
+ return /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(
3523
3594
  "header",
3524
3595
  {
3525
3596
  className: "canopy-header",
3526
3597
  "data-mobile-nav": "closed",
3527
3598
  "data-mobile-search": "closed"
3528
3599
  },
3529
- /* @__PURE__ */ React25.createElement("div", { className: "canopy-header__brand" }, /* @__PURE__ */ React25.createElement(
3600
+ /* @__PURE__ */ React26.createElement("div", { className: "canopy-header__brand" }, /* @__PURE__ */ React26.createElement(
3530
3601
  CanopyBrand,
3531
3602
  {
3532
3603
  label: resolvedTitle,
@@ -3535,7 +3606,7 @@ function CanopyHeader(props = {}) {
3535
3606
  Logo: SiteLogo
3536
3607
  }
3537
3608
  )),
3538
- /* @__PURE__ */ React25.createElement("div", { className: "canopy-header__desktop-search" }, /* @__PURE__ */ React25.createElement(
3609
+ /* @__PURE__ */ React26.createElement("div", { className: "canopy-header__desktop-search" }, /* @__PURE__ */ React26.createElement(
3539
3610
  SearchPanel,
3540
3611
  {
3541
3612
  label: resolvedSearchLabel,
@@ -3544,13 +3615,13 @@ function CanopyHeader(props = {}) {
3544
3615
  searchPath: normalizedSearchRoute
3545
3616
  }
3546
3617
  )),
3547
- /* @__PURE__ */ React25.createElement(
3618
+ /* @__PURE__ */ React26.createElement(
3548
3619
  "nav",
3549
3620
  {
3550
3621
  className: "canopy-nav-links canopy-header__desktop-nav",
3551
3622
  "aria-label": primaryNavigationLabel
3552
3623
  },
3553
- navLinks.map((link) => /* @__PURE__ */ React25.createElement(
3624
+ navLinks.map((link) => /* @__PURE__ */ React26.createElement(
3554
3625
  "a",
3555
3626
  {
3556
3627
  key: link.href,
@@ -3560,7 +3631,7 @@ function CanopyHeader(props = {}) {
3560
3631
  link.label || link.href
3561
3632
  ))
3562
3633
  ),
3563
- /* @__PURE__ */ React25.createElement("div", { className: "canopy-header__actions" }, resolvedLanguageToggle ? /* @__PURE__ */ React25.createElement(
3634
+ /* @__PURE__ */ React26.createElement("div", { className: "canopy-header__actions" }, resolvedLanguageToggle ? /* @__PURE__ */ React26.createElement(
3564
3635
  LanguageToggle,
3565
3636
  {
3566
3637
  languageToggle: resolvedLanguageToggle,
@@ -3568,7 +3639,7 @@ function CanopyHeader(props = {}) {
3568
3639
  variant: "desktop",
3569
3640
  className: "canopy-header__language-toggle canopy-header__language-toggle--desktop"
3570
3641
  }
3571
- ) : null, /* @__PURE__ */ React25.createElement(
3642
+ ) : null, /* @__PURE__ */ React26.createElement(
3572
3643
  "button",
3573
3644
  {
3574
3645
  type: "button",
@@ -3578,7 +3649,7 @@ function CanopyHeader(props = {}) {
3578
3649
  "aria-expanded": "false",
3579
3650
  "data-canopy-header-toggle": "search"
3580
3651
  },
3581
- /* @__PURE__ */ React25.createElement(
3652
+ /* @__PURE__ */ React26.createElement(
3582
3653
  "svg",
3583
3654
  {
3584
3655
  xmlns: "http://www.w3.org/2000/svg",
@@ -3588,7 +3659,7 @@ function CanopyHeader(props = {}) {
3588
3659
  strokeWidth: "1.5",
3589
3660
  className: "canopy-header__search-icon"
3590
3661
  },
3591
- /* @__PURE__ */ React25.createElement(
3662
+ /* @__PURE__ */ React26.createElement(
3592
3663
  "path",
3593
3664
  {
3594
3665
  strokeLinecap: "round",
@@ -3597,7 +3668,7 @@ function CanopyHeader(props = {}) {
3597
3668
  }
3598
3669
  )
3599
3670
  )
3600
- ), /* @__PURE__ */ React25.createElement(
3671
+ ), /* @__PURE__ */ React26.createElement(
3601
3672
  "button",
3602
3673
  {
3603
3674
  type: "button",
@@ -3607,7 +3678,7 @@ function CanopyHeader(props = {}) {
3607
3678
  "aria-expanded": "false",
3608
3679
  "data-canopy-header-toggle": "nav"
3609
3680
  },
3610
- /* @__PURE__ */ React25.createElement(
3681
+ /* @__PURE__ */ React26.createElement(
3611
3682
  "svg",
3612
3683
  {
3613
3684
  xmlns: "http://www.w3.org/2000/svg",
@@ -3617,7 +3688,7 @@ function CanopyHeader(props = {}) {
3617
3688
  stroke: "currentColor",
3618
3689
  className: "canopy-header__menu-icon"
3619
3690
  },
3620
- /* @__PURE__ */ React25.createElement(
3691
+ /* @__PURE__ */ React26.createElement(
3621
3692
  "path",
3622
3693
  {
3623
3694
  strokeLinecap: "round",
@@ -3627,7 +3698,7 @@ function CanopyHeader(props = {}) {
3627
3698
  )
3628
3699
  )
3629
3700
  ))
3630
- ), /* @__PURE__ */ React25.createElement(
3701
+ ), /* @__PURE__ */ React26.createElement(
3631
3702
  CanopyModal,
3632
3703
  {
3633
3704
  id: "canopy-modal-nav",
@@ -3639,7 +3710,7 @@ function CanopyHeader(props = {}) {
3639
3710
  closeLabel: closeNavLabel,
3640
3711
  closeDataAttr: "nav"
3641
3712
  },
3642
- resolvedLanguageToggle ? /* @__PURE__ */ React25.createElement(
3713
+ resolvedLanguageToggle ? /* @__PURE__ */ React26.createElement(
3643
3714
  LanguageToggle,
3644
3715
  {
3645
3716
  languageToggle: resolvedLanguageToggle,
@@ -3648,13 +3719,13 @@ function CanopyHeader(props = {}) {
3648
3719
  className: "canopy-header__language-toggle canopy-header__language-toggle--mobile"
3649
3720
  }
3650
3721
  ) : null,
3651
- /* @__PURE__ */ React25.createElement(
3722
+ /* @__PURE__ */ React26.createElement(
3652
3723
  "nav",
3653
3724
  {
3654
3725
  className: "canopy-nav-links canopy-modal__nav",
3655
3726
  "aria-label": primaryNavigationLabel
3656
3727
  },
3657
- /* @__PURE__ */ React25.createElement("ul", { className: "canopy-modal__nav-list", role: "list" }, navLinks.map((link, index) => {
3728
+ /* @__PURE__ */ React26.createElement("ul", { className: "canopy-modal__nav-list", role: "list" }, navLinks.map((link, index) => {
3658
3729
  const navData = getLinkNavigationData(
3659
3730
  link,
3660
3731
  navigationRoots,
@@ -3674,7 +3745,7 @@ function CanopyHeader(props = {}) {
3674
3745
  { content: toggleLabelTarget }
3675
3746
  );
3676
3747
  const defaultExpanded = hasChildren && !!navRoot.isExpanded;
3677
- return /* @__PURE__ */ React25.createElement(
3748
+ return /* @__PURE__ */ React26.createElement(
3678
3749
  "li",
3679
3750
  {
3680
3751
  className: "canopy-modal__nav-item",
@@ -3683,7 +3754,7 @@ function CanopyHeader(props = {}) {
3683
3754
  "data-expanded": defaultExpanded ? "true" : "false",
3684
3755
  "data-default-expanded": defaultExpanded ? "true" : void 0
3685
3756
  },
3686
- /* @__PURE__ */ React25.createElement("div", { className: "canopy-modal__nav-row" }, /* @__PURE__ */ React25.createElement("a", { href: link.href }, link.label || link.href), hasChildren ? /* @__PURE__ */ React25.createElement(
3757
+ /* @__PURE__ */ React26.createElement("div", { className: "canopy-modal__nav-row" }, /* @__PURE__ */ React26.createElement("a", { href: link.href }, link.label || link.href), hasChildren ? /* @__PURE__ */ React26.createElement(
3687
3758
  "button",
3688
3759
  {
3689
3760
  type: "button",
@@ -3693,7 +3764,7 @@ function CanopyHeader(props = {}) {
3693
3764
  "aria-label": toggleLabel,
3694
3765
  "data-canopy-nav-item-toggle": nestedId || void 0
3695
3766
  },
3696
- /* @__PURE__ */ React25.createElement(
3767
+ /* @__PURE__ */ React26.createElement(
3697
3768
  "svg",
3698
3769
  {
3699
3770
  xmlns: "http://www.w3.org/2000/svg",
@@ -3703,7 +3774,7 @@ function CanopyHeader(props = {}) {
3703
3774
  strokeWidth: "1.5",
3704
3775
  className: "canopy-modal__nav-toggle-icon"
3705
3776
  },
3706
- /* @__PURE__ */ React25.createElement(
3777
+ /* @__PURE__ */ React26.createElement(
3707
3778
  "path",
3708
3779
  {
3709
3780
  strokeLinecap: "round",
@@ -3712,9 +3783,9 @@ function CanopyHeader(props = {}) {
3712
3783
  }
3713
3784
  )
3714
3785
  ),
3715
- /* @__PURE__ */ React25.createElement("span", { className: "sr-only" }, toggleLabel)
3786
+ /* @__PURE__ */ React26.createElement("span", { className: "sr-only" }, toggleLabel)
3716
3787
  ) : null),
3717
- hasChildren ? /* @__PURE__ */ React25.createElement(
3788
+ hasChildren ? /* @__PURE__ */ React26.createElement(
3718
3789
  NavigationTree,
3719
3790
  {
3720
3791
  root: navRoot,
@@ -3734,7 +3805,7 @@ function CanopyHeader(props = {}) {
3734
3805
  );
3735
3806
  }))
3736
3807
  ),
3737
- hasSectionNav && !hasIntegratedSectionNav ? /* @__PURE__ */ React25.createElement(
3808
+ hasSectionNav && !hasIntegratedSectionNav ? /* @__PURE__ */ React26.createElement(
3738
3809
  NavigationTree,
3739
3810
  {
3740
3811
  root: sectionNavigation.root,
@@ -3744,7 +3815,7 @@ function CanopyHeader(props = {}) {
3744
3815
  parentKey: "fallback-nav"
3745
3816
  }
3746
3817
  ) : null
3747
- ), /* @__PURE__ */ React25.createElement(
3818
+ ), /* @__PURE__ */ React26.createElement(
3748
3819
  CanopyModal,
3749
3820
  {
3750
3821
  id: "canopy-modal-search",
@@ -3757,7 +3828,7 @@ function CanopyHeader(props = {}) {
3757
3828
  closeDataAttr: "search",
3758
3829
  bodyClassName: "canopy-modal__body--search"
3759
3830
  },
3760
- /* @__PURE__ */ React25.createElement(
3831
+ /* @__PURE__ */ React26.createElement(
3761
3832
  SearchPanel,
3762
3833
  {
3763
3834
  label: resolvedSearchLabel,
@@ -3766,18 +3837,18 @@ function CanopyHeader(props = {}) {
3766
3837
  searchPath: normalizedSearchRoute
3767
3838
  }
3768
3839
  )
3769
- ), /* @__PURE__ */ React25.createElement(HeaderScript, null));
3840
+ ), /* @__PURE__ */ React26.createElement(HeaderScript, null));
3770
3841
  }
3771
3842
 
3772
3843
  // ui/src/layout/CanopyFooter.jsx
3773
- import React26 from "react";
3844
+ import React27 from "react";
3774
3845
  function CanopyFooter({ className = "", children }) {
3775
3846
  const footerClassName = ["canopy-footer", className].filter(Boolean).join(" ");
3776
- return /* @__PURE__ */ React26.createElement("footer", { className: footerClassName }, /* @__PURE__ */ React26.createElement("div", { className: "canopy-footer__inner" }, children));
3847
+ return /* @__PURE__ */ React27.createElement("footer", { className: footerClassName }, /* @__PURE__ */ React27.createElement("div", { className: "canopy-footer__inner" }, children));
3777
3848
  }
3778
3849
 
3779
3850
  // ui/src/layout/TeaserCard.jsx
3780
- import React27 from "react";
3851
+ import React28 from "react";
3781
3852
  function TeaserCard({
3782
3853
  href = "",
3783
3854
  title = "",
@@ -3798,7 +3869,7 @@ function TeaserCard({
3798
3869
  ].filter(Boolean).join(" ");
3799
3870
  const showThumb = type === "work" && thumbnail;
3800
3871
  const metaLine = (Array.isArray(metadata) && metadata.length ? metadata.filter(Boolean) : summary ? [summary] : []).filter(Boolean).slice(0, 2).join(" \u2022 ");
3801
- return /* @__PURE__ */ React27.createElement(
3872
+ return /* @__PURE__ */ React28.createElement(
3802
3873
  Tag,
3803
3874
  {
3804
3875
  className: classes,
@@ -3806,7 +3877,7 @@ function TeaserCard({
3806
3877
  "data-canopy-item": href ? "" : void 0,
3807
3878
  ...rest
3808
3879
  },
3809
- showThumb ? /* @__PURE__ */ React27.createElement("div", { className: "canopy-search-teaser__thumb" }, /* @__PURE__ */ React27.createElement(
3880
+ showThumb ? /* @__PURE__ */ React28.createElement("div", { className: "canopy-search-teaser__thumb" }, /* @__PURE__ */ React28.createElement(
3810
3881
  "img",
3811
3882
  {
3812
3883
  src: thumbnail,
@@ -3816,12 +3887,12 @@ function TeaserCard({
3816
3887
  className: "canopy-search-teaser__thumb-img"
3817
3888
  }
3818
3889
  )) : null,
3819
- /* @__PURE__ */ React27.createElement("div", { className: "canopy-search-teaser__text" }, /* @__PURE__ */ React27.createElement("span", { className: "canopy-search-teaser__title" }, title || href || "Untitled"), metaLine ? /* @__PURE__ */ React27.createElement("span", { className: "canopy-search-teaser__meta" }, metaLine) : null)
3890
+ /* @__PURE__ */ React28.createElement("div", { className: "canopy-search-teaser__text" }, /* @__PURE__ */ React28.createElement("span", { className: "canopy-search-teaser__title" }, title || href || "Untitled"), metaLine ? /* @__PURE__ */ React28.createElement("span", { className: "canopy-search-teaser__meta" }, metaLine) : null)
3820
3891
  );
3821
3892
  }
3822
3893
 
3823
3894
  // ui/src/layout/GoogleAnalytics.jsx
3824
- import React28 from "react";
3895
+ import React29 from "react";
3825
3896
  var GA_HOST = "https://www.googletagmanager.com/gtag/js";
3826
3897
  function GoogleAnalytics({ id }) {
3827
3898
  if (!id) return null;
@@ -3831,11 +3902,11 @@ function GoogleAnalytics({ id }) {
3831
3902
  gtag('js', new Date());
3832
3903
  gtag('config', '${id}');
3833
3904
  `;
3834
- return /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement("script", { async: true, src: `${GA_HOST}?id=${encodeURIComponent(id)}` }), /* @__PURE__ */ React28.createElement("script", { dangerouslySetInnerHTML: { __html: inlineConfig } }));
3905
+ return /* @__PURE__ */ React29.createElement(React29.Fragment, null, /* @__PURE__ */ React29.createElement("script", { async: true, src: `${GA_HOST}?id=${encodeURIComponent(id)}` }), /* @__PURE__ */ React29.createElement("script", { dangerouslySetInnerHTML: { __html: inlineConfig } }));
3835
3906
  }
3836
3907
 
3837
3908
  // ui/src/layout/Container.jsx
3838
- import React29 from "react";
3909
+ import React30 from "react";
3839
3910
  function Container({
3840
3911
  className = "",
3841
3912
  variant = "content",
@@ -3844,7 +3915,7 @@ function Container({
3844
3915
  }) {
3845
3916
  const variantClass = variant === "wide" ? "max-w-wide" : "max-w-content";
3846
3917
  const classes = ["mx-auto", variantClass, "w-full", className].filter(Boolean).join(" ");
3847
- return /* @__PURE__ */ React29.createElement(
3918
+ return /* @__PURE__ */ React30.createElement(
3848
3919
  "div",
3849
3920
  {
3850
3921
  className: classes,
@@ -3856,7 +3927,7 @@ function Container({
3856
3927
  }
3857
3928
 
3858
3929
  // ui/src/layout/Card.jsx
3859
- import React30, { useEffect as useEffect6, useRef as useRef2, useState as useState5 } from "react";
3930
+ import React31, { useEffect as useEffect6, useRef as useRef2, useState as useState5 } from "react";
3860
3931
  var DEFAULT_CARD_ASPECT_RATIO = 4 / 3;
3861
3932
  function Card({
3862
3933
  href,
@@ -3920,8 +3991,8 @@ function Card({
3920
3991
  const hasDimensions = Number.isFinite(w) && w > 0 && Number.isFinite(h) && h > 0;
3921
3992
  const ratio = hasAspectRatio ? Number(aspectRatio) : hasDimensions ? w / h : src ? DEFAULT_CARD_ASPECT_RATIO : void 0;
3922
3993
  const paddingPercent = ratio ? 100 / ratio : 100;
3923
- const caption = /* @__PURE__ */ React30.createElement("figcaption", null, title && /* @__PURE__ */ React30.createElement("span", null, title), subtitle && /* @__PURE__ */ React30.createElement("span", null, subtitle), children);
3924
- return /* @__PURE__ */ React30.createElement(
3994
+ const caption = /* @__PURE__ */ React31.createElement("figcaption", null, title && /* @__PURE__ */ React31.createElement("span", null, title), subtitle && /* @__PURE__ */ React31.createElement("span", null, subtitle), children);
3995
+ return /* @__PURE__ */ React31.createElement(
3925
3996
  "a",
3926
3997
  {
3927
3998
  href,
@@ -3933,13 +4004,13 @@ function Card({
3933
4004
  "data-image-loaded": imageLoaded ? "true" : "false",
3934
4005
  ...rest
3935
4006
  },
3936
- /* @__PURE__ */ React30.createElement("figure", null, src ? ratio ? /* @__PURE__ */ React30.createElement(
4007
+ /* @__PURE__ */ React31.createElement("figure", null, src ? ratio ? /* @__PURE__ */ React31.createElement(
3937
4008
  "div",
3938
4009
  {
3939
4010
  className: "canopy-card-media",
3940
4011
  style: { "--canopy-card-padding": `${paddingPercent}%` }
3941
4012
  },
3942
- inView ? /* @__PURE__ */ React30.createElement(
4013
+ inView ? /* @__PURE__ */ React31.createElement(
3943
4014
  "img",
3944
4015
  {
3945
4016
  src,
@@ -3950,7 +4021,7 @@ function Card({
3950
4021
  onError: () => setImageLoaded(true)
3951
4022
  }
3952
4023
  ) : null
3953
- ) : /* @__PURE__ */ React30.createElement(
4024
+ ) : /* @__PURE__ */ React31.createElement(
3954
4025
  "img",
3955
4026
  {
3956
4027
  src,
@@ -3966,13 +4037,13 @@ function Card({
3966
4037
  }
3967
4038
 
3968
4039
  // ui/src/content/ReferencedItems.jsx
3969
- import React31 from "react";
3970
- import navigationHelpers4 from "@canopy-iiif/app/lib/components/navigation.js";
4040
+ import React32 from "react";
4041
+ import navigationHelpers3 from "@canopy-iiif/app/lib/components/navigation.js";
3971
4042
  function useReferencedItems(itemsProp) {
3972
4043
  if (Array.isArray(itemsProp)) return itemsProp;
3973
- const PageContext2 = navigationHelpers4 && typeof navigationHelpers4.getPageContext === "function" ? navigationHelpers4.getPageContext() : null;
3974
- if (!PageContext2) return [];
3975
- const context = React31.useContext(PageContext2);
4044
+ const PageContext3 = navigationHelpers3 && typeof navigationHelpers3.getPageContext === "function" ? navigationHelpers3.getPageContext() : null;
4045
+ if (!PageContext3) return [];
4046
+ const context = React32.useContext(PageContext3);
3976
4047
  const items = context && context.page ? context.page.referencedItems : null;
3977
4048
  return Array.isArray(items) ? items : [];
3978
4049
  }
@@ -3992,13 +4063,13 @@ function ReferencedItems({
3992
4063
  "referenced-items--empty",
3993
4064
  className
3994
4065
  ].filter(Boolean).join(" ");
3995
- return /* @__PURE__ */ React31.createElement("div", { className: emptyClass, ...rest }, typeof emptyLabel === "function" ? emptyLabel() : emptyLabel);
4066
+ return /* @__PURE__ */ React32.createElement("div", { className: emptyClass, ...rest }, typeof emptyLabel === "function" ? emptyLabel() : emptyLabel);
3996
4067
  }
3997
4068
  const containerClassName = ["referenced-items", className].filter(Boolean).join(" ");
3998
- return /* @__PURE__ */ React31.createElement("section", { className: containerClassName, ...rest }, children, /* @__PURE__ */ React31.createElement("div", { className: "referenced-items__grid", role: "list" }, items.map((item) => {
4069
+ return /* @__PURE__ */ React32.createElement("section", { className: containerClassName, ...rest }, children, /* @__PURE__ */ React32.createElement("div", { className: "referenced-items__grid", role: "list" }, items.map((item) => {
3999
4070
  if (!item) return null;
4000
4071
  const key = item.href || item.slug || item.id;
4001
- return /* @__PURE__ */ React31.createElement("div", { className: "referenced-items__item", role: "listitem", key }, /* @__PURE__ */ React31.createElement(
4072
+ return /* @__PURE__ */ React32.createElement("div", { className: "referenced-items__item", role: "listitem", key }, /* @__PURE__ */ React32.createElement(
4002
4073
  Card,
4003
4074
  {
4004
4075
  href: item.href,
@@ -4015,15 +4086,15 @@ function ReferencedItems({
4015
4086
  }
4016
4087
 
4017
4088
  // ui/src/content/References.jsx
4018
- import React32 from "react";
4019
- import navigationHelpers5 from "@canopy-iiif/app/lib/components/navigation.js";
4089
+ import React33 from "react";
4090
+ import navigationHelpers4 from "@canopy-iiif/app/lib/components/navigation.js";
4020
4091
  import referenced from "@canopy-iiif/app/lib/components/referenced.js";
4021
4092
  function getPageContext() {
4022
- if (!navigationHelpers5 || typeof navigationHelpers5.getPageContext !== "function") {
4093
+ if (!navigationHelpers4 || typeof navigationHelpers4.getPageContext !== "function") {
4023
4094
  return null;
4024
4095
  }
4025
4096
  try {
4026
- return navigationHelpers5.getPageContext();
4097
+ return navigationHelpers4.getPageContext();
4027
4098
  } catch (_) {
4028
4099
  return null;
4029
4100
  }
@@ -4047,8 +4118,8 @@ function References({
4047
4118
  }) {
4048
4119
  const { getString } = useLocale();
4049
4120
  const resolvedTitle = title != null ? title : getString("common.misc.referenced_by", "Referenced by");
4050
- const PageContext2 = getPageContext();
4051
- const context = PageContext2 ? React32.useContext(PageContext2) : null;
4121
+ const PageContext3 = getPageContext();
4122
+ const context = PageContext3 ? React33.useContext(PageContext3) : null;
4052
4123
  const contextPage = context && context.page ? context.page : null;
4053
4124
  const manifestId = id || contextPage && contextPage.manifestId || "";
4054
4125
  const contextReferences = !id && contextPage && Array.isArray(contextPage.referencedBy) ? contextPage.referencedBy : null;
@@ -4057,12 +4128,12 @@ function References({
4057
4128
  const entries = references && references.length ? references : null;
4058
4129
  if (!entries || !entries.length) return null;
4059
4130
  const containerClass = ["references", className].filter(Boolean).join(" ");
4060
- return /* @__PURE__ */ React32.createElement("dl", { className: containerClass, ...rest }, /* @__PURE__ */ React32.createElement("div", { className: "references__group" }, /* @__PURE__ */ React32.createElement("dt", null, resolvedTitle), entries.map((entry) => /* @__PURE__ */ React32.createElement("dd", { key: entry.href, className: "references__item" }, /* @__PURE__ */ React32.createElement("a", { href: entry.href }, entry.title || entry.href)))));
4131
+ return /* @__PURE__ */ React33.createElement("dl", { className: containerClass, ...rest }, /* @__PURE__ */ React33.createElement("div", { className: "references__group" }, /* @__PURE__ */ React33.createElement("dt", null, resolvedTitle), entries.map((entry) => /* @__PURE__ */ React33.createElement("dd", { key: entry.href, className: "references__item" }, /* @__PURE__ */ React33.createElement("a", { href: entry.href }, entry.title || entry.href)))));
4061
4132
  }
4062
4133
 
4063
4134
  // ui/src/content/Index.jsx
4064
4135
  var import_slugify = __toESM(require_slugify());
4065
- import React33 from "react";
4136
+ import React34 from "react";
4066
4137
  import metadataIndexHelpers from "@canopy-iiif/app/lib/components/metadata-index.js";
4067
4138
  var metadataModule = metadataIndexHelpers && typeof metadataIndexHelpers === "object" ? metadataIndexHelpers : null;
4068
4139
  var SLUG_OPTIONS = { lower: true, strict: true, trim: true };
@@ -4225,7 +4296,7 @@ function Index({
4225
4296
  const entries = filterByLabel(data, label);
4226
4297
  if (!entries.length) return null;
4227
4298
  const containerClass = ["canopy-index", className].filter(Boolean).join(" ");
4228
- return /* @__PURE__ */ React33.createElement("div", { className: containerClass, ...rest }, entries.map((entry) => /* @__PURE__ */ React33.createElement(
4299
+ return /* @__PURE__ */ React34.createElement("div", { className: containerClass, ...rest }, entries.map((entry) => /* @__PURE__ */ React34.createElement(
4229
4300
  IndexGroup,
4230
4301
  {
4231
4302
  key: entry.slug || entry.label,
@@ -4236,7 +4307,7 @@ function Index({
4236
4307
  expandLabel,
4237
4308
  collapseLabel
4238
4309
  }
4239
- )), /* @__PURE__ */ React33.createElement(
4310
+ )), /* @__PURE__ */ React34.createElement(
4240
4311
  "script",
4241
4312
  {
4242
4313
  "data-canopy-index-script": "",
@@ -4253,10 +4324,10 @@ function IndexGroup({ label, labelSlug, values, limit, expandLabel, collapseLabe
4253
4324
  const hiddenValues = hasOverflow ? values.slice(maxVisible) : [];
4254
4325
  const labelCollapsed = typeof expandLabel === "string" && expandLabel.trim() ? expandLabel.trim() : "Show more";
4255
4326
  const labelExpanded = typeof collapseLabel === "string" && collapseLabel.trim() ? collapseLabel.trim() : "Show less";
4256
- return /* @__PURE__ */ React33.createElement("dl", { className: "canopy-index__group", "data-canopy-index-group": "", "data-expanded": "0" }, /* @__PURE__ */ React33.createElement("dt", null, label), /* @__PURE__ */ React33.createElement("div", { className: "canopy-index__values" }, visibleValues.map((value) => {
4327
+ return /* @__PURE__ */ React34.createElement("dl", { className: "canopy-index__group", "data-canopy-index-group": "", "data-expanded": "0" }, /* @__PURE__ */ React34.createElement("dt", null, label), /* @__PURE__ */ React34.createElement("div", { className: "canopy-index__values" }, visibleValues.map((value) => {
4257
4328
  const href = buildSearchHref(labelSlug, value.slug);
4258
4329
  const key = `${labelSlug || label}-${value.slug || value.value}`;
4259
- return /* @__PURE__ */ React33.createElement("dd", { key }, href ? /* @__PURE__ */ React33.createElement(
4330
+ return /* @__PURE__ */ React34.createElement("dd", { key }, href ? /* @__PURE__ */ React34.createElement(
4260
4331
  "a",
4261
4332
  {
4262
4333
  href,
@@ -4269,7 +4340,7 @@ function IndexGroup({ label, labelSlug, values, limit, expandLabel, collapseLabe
4269
4340
  }), hiddenValues.map((value) => {
4270
4341
  const href = buildSearchHref(labelSlug, value.slug);
4271
4342
  const key = `${labelSlug || label}-hidden-${value.slug || value.value}`;
4272
- return /* @__PURE__ */ React33.createElement("dd", { key, "data-canopy-index-hidden": "", hidden: true }, href ? /* @__PURE__ */ React33.createElement(
4343
+ return /* @__PURE__ */ React34.createElement("dd", { key, "data-canopy-index-hidden": "", hidden: true }, href ? /* @__PURE__ */ React34.createElement(
4273
4344
  "a",
4274
4345
  {
4275
4346
  href,
@@ -4279,7 +4350,7 @@ function IndexGroup({ label, labelSlug, values, limit, expandLabel, collapseLabe
4279
4350
  },
4280
4351
  value.value
4281
4352
  ) : value.value);
4282
- })), hasOverflow && /* @__PURE__ */ React33.createElement("div", { className: "canopy-index__more-wrapper" }, /* @__PURE__ */ React33.createElement(
4353
+ })), hasOverflow && /* @__PURE__ */ React34.createElement("div", { className: "canopy-index__more-wrapper" }, /* @__PURE__ */ React34.createElement(
4283
4354
  "button",
4284
4355
  {
4285
4356
  type: "button",
@@ -4293,7 +4364,7 @@ function IndexGroup({ label, labelSlug, values, limit, expandLabel, collapseLabe
4293
4364
  }
4294
4365
 
4295
4366
  // ui/src/content/Bibliography.jsx
4296
- import React34 from "react";
4367
+ import React35 from "react";
4297
4368
  import bibliography from "@canopy-iiif/app/lib/components/bibliography.js";
4298
4369
  function resolveHeadingTag(tag, fallback) {
4299
4370
  if (typeof tag === "string" && tag.trim()) return tag;
@@ -4303,7 +4374,7 @@ function resolveHeadingTag(tag, fallback) {
4303
4374
  function NoteBody({ note }) {
4304
4375
  if (!note) return null;
4305
4376
  if (note.html) {
4306
- return /* @__PURE__ */ React34.createElement(
4377
+ return /* @__PURE__ */ React35.createElement(
4307
4378
  "div",
4308
4379
  {
4309
4380
  className: "bibliography__note-body",
@@ -4312,7 +4383,7 @@ function NoteBody({ note }) {
4312
4383
  );
4313
4384
  }
4314
4385
  if (note.text) {
4315
- return /* @__PURE__ */ React34.createElement("div", { className: "bibliography__note-body" }, note.text);
4386
+ return /* @__PURE__ */ React35.createElement("div", { className: "bibliography__note-body" }, note.text);
4316
4387
  }
4317
4388
  return null;
4318
4389
  }
@@ -4330,22 +4401,22 @@ function Bibliography({
4330
4401
  if (!entries.length) return null;
4331
4402
  const PageHeadingTag = resolveHeadingTag(pageHeadingTag, "h3");
4332
4403
  const rootClass = ["bibliography", className].filter(Boolean).join(" ");
4333
- return /* @__PURE__ */ React34.createElement("section", { className: rootClass }, /* @__PURE__ */ React34.createElement("div", { className: "bibliography__pages" }, entries.map((entry) => {
4404
+ return /* @__PURE__ */ React35.createElement("section", { className: rootClass }, /* @__PURE__ */ React35.createElement("div", { className: "bibliography__pages" }, entries.map((entry) => {
4334
4405
  const key = entry.href || entry.relativePath || entry.title;
4335
4406
  const pageTitle = entry.title || entry.href;
4336
- return /* @__PURE__ */ React34.createElement("article", { key, className: "bibliography__page" }, /* @__PURE__ */ React34.createElement("header", { className: "bibliography__page-header" }, pageTitle ? /* @__PURE__ */ React34.createElement(PageHeadingTag, { className: "bibliography__page-title" }, pageTitle) : null, entry.href ? /* @__PURE__ */ React34.createElement("a", { className: "bibliography__page-link", href: entry.href }, entry.href) : null), /* @__PURE__ */ React34.createElement("ol", { className: "bibliography__notes" }, (entry.footnotes || []).map((note, idx) => {
4407
+ return /* @__PURE__ */ React35.createElement("article", { key, className: "bibliography__page" }, /* @__PURE__ */ React35.createElement("header", { className: "bibliography__page-header" }, pageTitle ? /* @__PURE__ */ React35.createElement(PageHeadingTag, { className: "bibliography__page-title" }, pageTitle) : null, entry.href ? /* @__PURE__ */ React35.createElement("a", { className: "bibliography__page-link", href: entry.href }, entry.href) : null), /* @__PURE__ */ React35.createElement("ol", { className: "bibliography__notes" }, (entry.footnotes || []).map((note, idx) => {
4337
4408
  const noteKey = `${key || "entry"}-${note.identifier || idx}`;
4338
- return /* @__PURE__ */ React34.createElement("li", { key: noteKey, className: "bibliography__note" }, note.identifier ? /* @__PURE__ */ React34.createElement("span", { className: "bibliography__note-label" }, note.identifier) : null, /* @__PURE__ */ React34.createElement(NoteBody, { note }));
4409
+ return /* @__PURE__ */ React35.createElement("li", { key: noteKey, className: "bibliography__note" }, note.identifier ? /* @__PURE__ */ React35.createElement("span", { className: "bibliography__note-label" }, note.identifier) : null, /* @__PURE__ */ React35.createElement(NoteBody, { note }));
4339
4410
  })));
4340
4411
  })));
4341
4412
  }
4342
4413
 
4343
4414
  // ui/src/content/timeline/MdxTimeline.jsx
4344
- import React38 from "react";
4415
+ import React39 from "react";
4345
4416
  import ReactDOMServer from "react-dom/server";
4346
4417
 
4347
4418
  // ui/src/content/timeline/Timeline.jsx
4348
- import React36 from "react";
4419
+ import React37 from "react";
4349
4420
 
4350
4421
  // ui/src/content/timeline/date-utils.js
4351
4422
  var FALLBACK_LOCALE = (() => {
@@ -4506,7 +4577,7 @@ function clampProgress(value) {
4506
4577
  }
4507
4578
 
4508
4579
  // ui/src/layout/ReferencedManifestCard.jsx
4509
- import React35 from "react";
4580
+ import React36 from "react";
4510
4581
  function normalizeMetadata(metadata, summary) {
4511
4582
  if (Array.isArray(metadata) && metadata.length) {
4512
4583
  return metadata.filter(Boolean);
@@ -4540,7 +4611,7 @@ function ReferencedManifestCard({
4540
4611
  "canopy-referenced-manifest-card",
4541
4612
  className
4542
4613
  ].filter(Boolean).join(" ");
4543
- return /* @__PURE__ */ React35.createElement(
4614
+ return /* @__PURE__ */ React36.createElement(
4544
4615
  TeaserCard,
4545
4616
  {
4546
4617
  href: resolvedHref || void 0,
@@ -4722,14 +4793,14 @@ function TimelineConnector({ side, isActive, highlight }) {
4722
4793
  "canopy-timeline__connector-dot",
4723
4794
  highlight || isActive ? "is-active" : ""
4724
4795
  ].filter(Boolean).join(" ");
4725
- return /* @__PURE__ */ React36.createElement("span", { className: connectorClasses, "aria-hidden": "true" }, side === "left" ? /* @__PURE__ */ React36.createElement(React36.Fragment, null, /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__connector-line" }), /* @__PURE__ */ React36.createElement("span", { className: dotClasses })) : /* @__PURE__ */ React36.createElement(React36.Fragment, null, /* @__PURE__ */ React36.createElement("span", { className: dotClasses }), /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__connector-line" })));
4796
+ return /* @__PURE__ */ React37.createElement("span", { className: connectorClasses, "aria-hidden": "true" }, side === "left" ? /* @__PURE__ */ React37.createElement(React37.Fragment, null, /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__connector-line" }), /* @__PURE__ */ React37.createElement("span", { className: dotClasses })) : /* @__PURE__ */ React37.createElement(React37.Fragment, null, /* @__PURE__ */ React37.createElement("span", { className: dotClasses }), /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__connector-line" })));
4726
4797
  }
4727
4798
  function renderResourceSection(point) {
4728
4799
  if (!point) return null;
4729
4800
  const manifestCards = Array.isArray(point.manifests) ? point.manifests.filter(Boolean) : [];
4730
4801
  const legacyResources = Array.isArray(point.resources) ? point.resources.filter(Boolean) : [];
4731
4802
  if (!manifestCards.length && !legacyResources.length) return null;
4732
- return /* @__PURE__ */ React36.createElement("div", { className: "canopy-timeline__resources" }, /* @__PURE__ */ React36.createElement("div", { className: "canopy-timeline__resources-list" }, manifestCards.map((manifest) => /* @__PURE__ */ React36.createElement("div", { key: manifest.id || manifest.href }, /* @__PURE__ */ React36.createElement(ReferencedManifestCard, { manifest }))), legacyResources.map((resource, idx) => /* @__PURE__ */ React36.createElement("div", { key: resource.id || resource.href || `legacy-${idx}` }, /* @__PURE__ */ React36.createElement(
4803
+ return /* @__PURE__ */ React37.createElement("div", { className: "canopy-timeline__resources" }, /* @__PURE__ */ React37.createElement("div", { className: "canopy-timeline__resources-list" }, manifestCards.map((manifest) => /* @__PURE__ */ React37.createElement("div", { key: manifest.id || manifest.href }, /* @__PURE__ */ React37.createElement(ReferencedManifestCard, { manifest }))), legacyResources.map((resource, idx) => /* @__PURE__ */ React37.createElement("div", { key: resource.id || resource.href || `legacy-${idx}` }, /* @__PURE__ */ React37.createElement(
4733
4804
  TeaserCard,
4734
4805
  {
4735
4806
  href: resource.href,
@@ -4754,26 +4825,26 @@ function Timeline({
4754
4825
  ...rest
4755
4826
  }) {
4756
4827
  const payloadPoints = payload && Array.isArray(payload.points) ? payload.points : null;
4757
- const rawPoints = React36.useMemo(() => {
4828
+ const rawPoints = React37.useMemo(() => {
4758
4829
  if (Array.isArray(pointsProp) && pointsProp.length) return pointsProp;
4759
4830
  if (payloadPoints && payloadPoints.length) return payloadPoints;
4760
4831
  return [];
4761
4832
  }, [pointsProp, payloadPoints]);
4762
- const sanitizedPoints = React36.useMemo(
4833
+ const sanitizedPoints = React37.useMemo(
4763
4834
  () => sanitizePoints(rawPoints),
4764
4835
  [rawPoints]
4765
4836
  );
4766
4837
  const localeValue = payload && payload.locale ? payload.locale : localeProp;
4767
- const baseLocale = React36.useMemo(
4838
+ const baseLocale = React37.useMemo(
4768
4839
  () => createLocale(localeValue),
4769
4840
  [localeValue]
4770
4841
  );
4771
4842
  const rangeInput = payload && payload.range ? payload.range : rangeProp || {};
4772
- const rangeOverrides = React36.useMemo(
4843
+ const rangeOverrides = React37.useMemo(
4773
4844
  () => deriveRangeOverrides(sanitizedPoints, rangeInput),
4774
4845
  [sanitizedPoints, rangeInput]
4775
4846
  );
4776
- const effectiveRange = React36.useMemo(
4847
+ const effectiveRange = React37.useMemo(
4777
4848
  () => normalizeRange({
4778
4849
  ...rangeOverrides,
4779
4850
  locale: baseLocale
@@ -4782,7 +4853,7 @@ function Timeline({
4782
4853
  );
4783
4854
  const spanStart = effectiveRange.startDate.getTime();
4784
4855
  const span = effectiveRange.span;
4785
- const pointsWithPosition = React36.useMemo(() => {
4856
+ const pointsWithPosition = React37.useMemo(() => {
4786
4857
  if (!sanitizedPoints.length) return [];
4787
4858
  return sanitizedPoints.map((point, index) => {
4788
4859
  const timestamp = point.meta.timestamp;
@@ -4796,29 +4867,29 @@ function Timeline({
4796
4867
  };
4797
4868
  });
4798
4869
  }, [sanitizedPoints, spanStart, span]);
4799
- const [activeId, setActiveId] = React36.useState(
4870
+ const [activeId, setActiveId] = React37.useState(
4800
4871
  () => getActivePointId(pointsWithPosition)
4801
4872
  );
4802
- React36.useEffect(() => {
4873
+ React37.useEffect(() => {
4803
4874
  setActiveId(getActivePointId(pointsWithPosition));
4804
4875
  }, [pointsWithPosition]);
4805
4876
  const thresholdValue = typeof thresholdProp === "number" ? thresholdProp : payload && payload.threshold != null ? payload.threshold : null;
4806
4877
  const stepsValue = typeof steps === "number" ? Number(steps) : payload && typeof payload.steps === "number" ? Number(payload.steps) : null;
4807
- const thresholdMs = React36.useMemo(
4878
+ const thresholdMs = React37.useMemo(
4808
4879
  () => getThresholdMs(thresholdValue, effectiveRange.granularity),
4809
4880
  [thresholdValue, effectiveRange.granularity]
4810
4881
  );
4811
- const groupedEntries = React36.useMemo(
4882
+ const groupedEntries = React37.useMemo(
4812
4883
  () => buildGroupedEntries(pointsWithPosition, thresholdMs, {
4813
4884
  granularity: effectiveRange.granularity,
4814
4885
  locale: baseLocale
4815
4886
  }),
4816
4887
  [pointsWithPosition, thresholdMs, effectiveRange.granularity, baseLocale]
4817
4888
  );
4818
- const [expandedGroupIds, setExpandedGroupIds] = React36.useState(
4889
+ const [expandedGroupIds, setExpandedGroupIds] = React37.useState(
4819
4890
  () => /* @__PURE__ */ new Set()
4820
4891
  );
4821
- React36.useEffect(() => {
4892
+ React37.useEffect(() => {
4822
4893
  setExpandedGroupIds((prev) => {
4823
4894
  if (!prev || prev.size === 0) return prev;
4824
4895
  const validIds = new Set(
@@ -4833,7 +4904,7 @@ function Timeline({
4833
4904
  return changed ? next : prev;
4834
4905
  });
4835
4906
  }, [groupedEntries]);
4836
- const toggleGroup = React36.useCallback((groupId) => {
4907
+ const toggleGroup = React37.useCallback((groupId) => {
4837
4908
  setExpandedGroupIds((prev) => {
4838
4909
  const next = new Set(prev || []);
4839
4910
  if (next.has(groupId)) next.delete(groupId);
@@ -4856,7 +4927,7 @@ function Timeline({
4856
4927
  point.id === activeId ? "is-active" : "",
4857
4928
  point.highlight ? "is-highlighted" : ""
4858
4929
  ].filter(Boolean).join(" ");
4859
- const connector = /* @__PURE__ */ React36.createElement(
4930
+ const connector = /* @__PURE__ */ React37.createElement(
4860
4931
  TimelineConnector,
4861
4932
  {
4862
4933
  side: point.side,
@@ -4864,9 +4935,9 @@ function Timeline({
4864
4935
  highlight: point.highlight
4865
4936
  }
4866
4937
  );
4867
- const body = /* @__PURE__ */ React36.createElement("div", { className: "canopy-timeline__point-body" }, /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label), /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__point-title" }, point.title), point.summary ? /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__point-summary" }, point.summary) : null);
4938
+ const body = /* @__PURE__ */ React37.createElement("div", { className: "canopy-timeline__point-body" }, /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label), /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__point-title" }, point.title), point.summary ? /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__point-summary" }, point.summary) : null);
4868
4939
  const resourceSection = renderResourceSection(point);
4869
- return /* @__PURE__ */ React36.createElement(
4940
+ return /* @__PURE__ */ React37.createElement(
4870
4941
  "div",
4871
4942
  {
4872
4943
  key: point.id,
@@ -4874,7 +4945,7 @@ function Timeline({
4874
4945
  style: wrapperStyle,
4875
4946
  role: "listitem"
4876
4947
  },
4877
- point.side === "left" ? /* @__PURE__ */ React36.createElement(React36.Fragment, null, /* @__PURE__ */ React36.createElement("div", { className: cardClasses }, body, resourceSection), connector) : /* @__PURE__ */ React36.createElement(React36.Fragment, null, connector, /* @__PURE__ */ React36.createElement("div", { className: cardClasses }, body, resourceSection))
4948
+ point.side === "left" ? /* @__PURE__ */ React37.createElement(React37.Fragment, null, /* @__PURE__ */ React37.createElement("div", { className: cardClasses }, body, resourceSection), connector) : /* @__PURE__ */ React37.createElement(React37.Fragment, null, connector, /* @__PURE__ */ React37.createElement("div", { className: cardClasses }, body, resourceSection))
4878
4949
  );
4879
4950
  }
4880
4951
  function renderGroupEntry(entry) {
@@ -4885,7 +4956,7 @@ function Timeline({
4885
4956
  const wrapperStyle = { top: `${entry.progress * 100}%` };
4886
4957
  const isExpanded = expandedGroupIds.has(entry.id);
4887
4958
  const hasActivePoint = entry.points.some((point) => point.id === activeId);
4888
- const connector = /* @__PURE__ */ React36.createElement(
4959
+ const connector = /* @__PURE__ */ React37.createElement(
4889
4960
  TimelineConnector,
4890
4961
  {
4891
4962
  side: entry.side,
@@ -4899,7 +4970,7 @@ function Timeline({
4899
4970
  hasActivePoint ? "is-active" : ""
4900
4971
  ].filter(Boolean).join(" ");
4901
4972
  const countLabel = `${entry.count} event${entry.count > 1 ? "s" : ""}`;
4902
- const header = /* @__PURE__ */ React36.createElement("div", { className: "canopy-timeline__group-header" }, /* @__PURE__ */ React36.createElement("div", { className: "canopy-timeline__group-summary" }, /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__point-date" }, entry.label), /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__group-count" }, countLabel)), /* @__PURE__ */ React36.createElement(
4973
+ const header = /* @__PURE__ */ React37.createElement("div", { className: "canopy-timeline__group-header" }, /* @__PURE__ */ React37.createElement("div", { className: "canopy-timeline__group-summary" }, /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__point-date" }, entry.label), /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__group-count" }, countLabel)), /* @__PURE__ */ React37.createElement(
4903
4974
  "button",
4904
4975
  {
4905
4976
  type: "button",
@@ -4909,7 +4980,7 @@ function Timeline({
4909
4980
  },
4910
4981
  isExpanded ? "Hide details" : "Show details"
4911
4982
  ));
4912
- const groupPoints = isExpanded ? /* @__PURE__ */ React36.createElement("div", { className: "canopy-timeline__group-points" }, entry.points.map((point) => /* @__PURE__ */ React36.createElement(
4983
+ const groupPoints = isExpanded ? /* @__PURE__ */ React37.createElement("div", { className: "canopy-timeline__group-points" }, entry.points.map((point) => /* @__PURE__ */ React37.createElement(
4913
4984
  "button",
4914
4985
  {
4915
4986
  key: point.id,
@@ -4920,11 +4991,11 @@ function Timeline({
4920
4991
  ].filter(Boolean).join(" "),
4921
4992
  onClick: () => setActiveId(point.id)
4922
4993
  },
4923
- /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label),
4924
- /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__group-point-title" }, point.title)
4994
+ /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label),
4995
+ /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__group-point-title" }, point.title)
4925
4996
  ))) : null;
4926
- const groupCard = /* @__PURE__ */ React36.createElement("div", { className: groupClasses }, header, groupPoints);
4927
- return /* @__PURE__ */ React36.createElement(
4997
+ const groupCard = /* @__PURE__ */ React37.createElement("div", { className: groupClasses }, header, groupPoints);
4998
+ return /* @__PURE__ */ React37.createElement(
4928
4999
  "div",
4929
5000
  {
4930
5001
  key: entry.id,
@@ -4932,17 +5003,17 @@ function Timeline({
4932
5003
  style: wrapperStyle,
4933
5004
  role: "listitem"
4934
5005
  },
4935
- entry.side === "left" ? /* @__PURE__ */ React36.createElement(React36.Fragment, null, groupCard, connector) : /* @__PURE__ */ React36.createElement(React36.Fragment, null, connector, groupCard)
5006
+ entry.side === "left" ? /* @__PURE__ */ React37.createElement(React37.Fragment, null, groupCard, connector) : /* @__PURE__ */ React37.createElement(React37.Fragment, null, connector, groupCard)
4936
5007
  );
4937
5008
  }
4938
- return /* @__PURE__ */ React36.createElement("section", { className: containerClasses, ...rest }, title ? /* @__PURE__ */ React36.createElement("h2", { className: "canopy-timeline__title" }, title) : null, description ? /* @__PURE__ */ React36.createElement("p", { className: "canopy-timeline__description" }, description) : null, rangeLabel ? /* @__PURE__ */ React36.createElement("p", { className: "canopy-timeline__range", "aria-live": "polite" }, rangeLabel) : null, /* @__PURE__ */ React36.createElement("div", { className: "canopy-timeline__body" }, /* @__PURE__ */ React36.createElement(
5009
+ return /* @__PURE__ */ React37.createElement("section", { className: containerClasses, ...rest }, title ? /* @__PURE__ */ React37.createElement("h2", { className: "canopy-timeline__title" }, title) : null, description ? /* @__PURE__ */ React37.createElement("p", { className: "canopy-timeline__description" }, description) : null, rangeLabel ? /* @__PURE__ */ React37.createElement("p", { className: "canopy-timeline__range", "aria-live": "polite" }, rangeLabel) : null, /* @__PURE__ */ React37.createElement("div", { className: "canopy-timeline__body" }, /* @__PURE__ */ React37.createElement(
4939
5010
  "div",
4940
5011
  {
4941
5012
  className: "canopy-timeline__list",
4942
5013
  role: "list",
4943
5014
  style: { minHeight: trackHeight }
4944
5015
  },
4945
- /* @__PURE__ */ React36.createElement("div", { className: "canopy-timeline__spine", "aria-hidden": "true" }),
5016
+ /* @__PURE__ */ React37.createElement("div", { className: "canopy-timeline__spine", "aria-hidden": "true" }),
4946
5017
  renderSteps(stepsValue, effectiveRange),
4947
5018
  groupedEntries.map((entry) => {
4948
5019
  if (entry.type === "group") return renderGroupEntry(entry);
@@ -4957,7 +5028,7 @@ function renderSteps(stepSize, range) {
4957
5028
  const markers = [];
4958
5029
  if (startYear < endYear) {
4959
5030
  markers.push(
4960
- /* @__PURE__ */ React36.createElement(
5031
+ /* @__PURE__ */ React37.createElement(
4961
5032
  "span",
4962
5033
  {
4963
5034
  key: "timeline-step-start",
@@ -4965,12 +5036,12 @@ function renderSteps(stepSize, range) {
4965
5036
  style: { top: "0%" },
4966
5037
  "aria-hidden": "true"
4967
5038
  },
4968
- /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__step-line" }),
4969
- /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__step-label" }, startYear)
5039
+ /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__step-line" }),
5040
+ /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__step-label" }, startYear)
4970
5041
  )
4971
5042
  );
4972
5043
  markers.push(
4973
- /* @__PURE__ */ React36.createElement(
5044
+ /* @__PURE__ */ React37.createElement(
4974
5045
  "span",
4975
5046
  {
4976
5047
  key: "timeline-step-end",
@@ -4978,8 +5049,8 @@ function renderSteps(stepSize, range) {
4978
5049
  style: { top: "100%" },
4979
5050
  "aria-hidden": "true"
4980
5051
  },
4981
- /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__step-line" }),
4982
- /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__step-label" }, endYear)
5052
+ /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__step-line" }),
5053
+ /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__step-label" }, endYear)
4983
5054
  )
4984
5055
  );
4985
5056
  }
@@ -4989,7 +5060,7 @@ function renderSteps(stepSize, range) {
4989
5060
  const progress = (timestamp - range.startDate.getTime()) / range.span;
4990
5061
  if (progress <= 0 || progress >= 1) continue;
4991
5062
  markers.push(
4992
- /* @__PURE__ */ React36.createElement(
5063
+ /* @__PURE__ */ React37.createElement(
4993
5064
  "span",
4994
5065
  {
4995
5066
  key: `timeline-step-${year}`,
@@ -4997,8 +5068,8 @@ function renderSteps(stepSize, range) {
4997
5068
  style: { top: `calc(${progress * 100}% - 0.5px)` },
4998
5069
  "aria-hidden": "true"
4999
5070
  },
5000
- /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__step-line" }),
5001
- /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__step-label" }, year)
5071
+ /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__step-line" }),
5072
+ /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__step-label" }, year)
5002
5073
  )
5003
5074
  );
5004
5075
  }
@@ -5012,7 +5083,7 @@ function TimelinePoint() {
5012
5083
  TimelinePoint.displayName = "TimelinePoint";
5013
5084
 
5014
5085
  // ui/src/utils/manifestReferences.js
5015
- import React37 from "react";
5086
+ import React38 from "react";
5016
5087
  var CONTEXT_KEY2 = typeof Symbol === "function" ? Symbol.for("__CANOPY_PAGE_CONTEXT__") : "__CANOPY_PAGE_CONTEXT__";
5017
5088
  function getGlobalRoot() {
5018
5089
  if (typeof globalThis !== "undefined") return globalThis;
@@ -5023,7 +5094,7 @@ function getGlobalRoot() {
5023
5094
  function getPageContext2() {
5024
5095
  const root = getGlobalRoot();
5025
5096
  if (root && root[CONTEXT_KEY2]) return root[CONTEXT_KEY2];
5026
- const ctx = React37.createContext({
5097
+ const ctx = React38.createContext({
5027
5098
  navigation: null,
5028
5099
  page: null,
5029
5100
  site: null,
@@ -5047,7 +5118,7 @@ function normalizeManifestId(raw) {
5047
5118
  return String(raw || "").trim();
5048
5119
  }
5049
5120
  }
5050
- var PageContextFallback = React37.createContext(null);
5121
+ var PageContextFallback = React38.createContext(null);
5051
5122
  var referencedModule = null;
5052
5123
  var REFERENCED_SPEC = "@canopy-iiif/app/lib/components/referenced.js";
5053
5124
  function getReferencedModule() {
@@ -5072,10 +5143,10 @@ function getReferencedModule() {
5072
5143
  return referencedModule;
5073
5144
  }
5074
5145
  function useReferencedManifestMap() {
5075
- const PageContext2 = getPageContext2() || PageContextFallback;
5076
- const pageContext = React37.useContext(PageContext2);
5146
+ const PageContext3 = getPageContext2() || PageContextFallback;
5147
+ const pageContext = React38.useContext(PageContext3);
5077
5148
  const referencedItems = pageContext && pageContext.page && Array.isArray(pageContext.page.referencedItems) ? pageContext.page.referencedItems : [];
5078
- return React37.useMemo(() => {
5149
+ return React38.useMemo(() => {
5079
5150
  const map = /* @__PURE__ */ new Map();
5080
5151
  referencedItems.forEach((item) => {
5081
5152
  if (!item) return;
@@ -5186,7 +5257,7 @@ function normalizeResource(resource, index) {
5186
5257
  }
5187
5258
  function normalizePoint(child, index, options) {
5188
5259
  var _a, _b, _c, _d, _e, _f;
5189
- if (!React38.isValidElement(child)) return null;
5260
+ if (!React39.isValidElement(child)) return null;
5190
5261
  if (child.type !== TimelinePoint && ((_a = child.type) == null ? void 0 : _a.displayName) !== "TimelinePoint")
5191
5262
  return null;
5192
5263
  const props = child.props || {};
@@ -5202,7 +5273,7 @@ function normalizePoint(child, index, options) {
5202
5273
  try {
5203
5274
  if (props.children) {
5204
5275
  detailsHtml = ReactDOMServer.renderToStaticMarkup(
5205
- React38.createElement(React38.Fragment, null, props.children)
5276
+ React39.createElement(React39.Fragment, null, props.children)
5206
5277
  );
5207
5278
  }
5208
5279
  } catch (_) {
@@ -5251,7 +5322,7 @@ function MdxTimeline({ children, ...rest }) {
5251
5322
  const localeObj = createLocale(localeValue);
5252
5323
  const localeBase = typeof localeObj === "string" ? localeObj : localeObj.baseName || "en-US";
5253
5324
  const manifestMap = useReferencedManifestMap();
5254
- const childArray = React38.Children.toArray(children);
5325
+ const childArray = React39.Children.toArray(children);
5255
5326
  const points = childArray.map(
5256
5327
  (child, index) => normalizePoint(child, index, {
5257
5328
  range: rest.range || {},
@@ -5267,7 +5338,7 @@ function MdxTimeline({ children, ...rest }) {
5267
5338
  steps: rest.steps != null ? rest.steps : null
5268
5339
  };
5269
5340
  const json = serializeForScript(serializeProps(rest, payload, localeBase));
5270
- return /* @__PURE__ */ React38.createElement("div", { "data-canopy-timeline": "1" }, /* @__PURE__ */ React38.createElement(Timeline, { ...rest, __canopyTimeline: payload }), /* @__PURE__ */ React38.createElement(
5341
+ return /* @__PURE__ */ React39.createElement("div", { "data-canopy-timeline": "1" }, /* @__PURE__ */ React39.createElement(Timeline, { ...rest, __canopyTimeline: payload }), /* @__PURE__ */ React39.createElement(
5271
5342
  "script",
5272
5343
  {
5273
5344
  type: "application/json",
@@ -5277,7 +5348,7 @@ function MdxTimeline({ children, ...rest }) {
5277
5348
  }
5278
5349
 
5279
5350
  // ui/src/content/map/MdxMap.jsx
5280
- import React39 from "react";
5351
+ import React40 from "react";
5281
5352
  import ReactDOMServer2 from "react-dom/server";
5282
5353
 
5283
5354
  // ui/src/content/map/MapPoint.jsx
@@ -5312,7 +5383,7 @@ function renderDetailsHtml(children) {
5312
5383
  if (!children) return "";
5313
5384
  try {
5314
5385
  return ReactDOMServer2.renderToStaticMarkup(
5315
- React39.createElement(React39.Fragment, null, children)
5386
+ React40.createElement(React40.Fragment, null, children)
5316
5387
  );
5317
5388
  } catch (_) {
5318
5389
  return "";
@@ -5345,7 +5416,7 @@ function pickManifestSummary(manifest) {
5345
5416
  }
5346
5417
  function normalizeCustomPoint(child, index, manifestMap) {
5347
5418
  var _a;
5348
- if (!React39.isValidElement(child)) return null;
5419
+ if (!React40.isValidElement(child)) return null;
5349
5420
  if (child.type !== MapPoint && ((_a = child.type) == null ? void 0 : _a.displayName) !== "MapPoint") return null;
5350
5421
  const coords = normalizeCoordinates(child.props || {});
5351
5422
  if (!coords) return null;
@@ -5408,7 +5479,7 @@ function normalizeCustomPoint(child, index, manifestMap) {
5408
5479
  };
5409
5480
  }
5410
5481
  function normalizeCustomPoints(children, manifestMap) {
5411
- return React39.Children.toArray(children).map((child, index) => normalizeCustomPoint(child, index, manifestMap)).filter(Boolean);
5482
+ return React40.Children.toArray(children).map((child, index) => normalizeCustomPoint(child, index, manifestMap)).filter(Boolean);
5412
5483
  }
5413
5484
  function normalizeHeight(value) {
5414
5485
  if (value == null) return "600px";
@@ -5585,11 +5656,11 @@ function MdxMap({ children, ...rest }) {
5585
5656
  if (placeholderClass) placeholderProps.className = placeholderClass;
5586
5657
  if (rest.id) placeholderProps.id = rest.id;
5587
5658
  if (rest.style) placeholderProps.style = rest.style;
5588
- return /* @__PURE__ */ React39.createElement("div", { "data-canopy-map": "1" }, /* @__PURE__ */ React39.createElement("div", { ...placeholderProps, "aria-live": "polite" }, /* @__PURE__ */ React39.createElement("div", { className: "canopy-map__status" }, "Loading map\u2026")), /* @__PURE__ */ React39.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
5659
+ return /* @__PURE__ */ React40.createElement("div", { "data-canopy-map": "1" }, /* @__PURE__ */ React40.createElement("div", { ...placeholderProps, "aria-live": "polite" }, /* @__PURE__ */ React40.createElement("div", { className: "canopy-map__status" }, "Loading map\u2026")), /* @__PURE__ */ React40.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
5589
5660
  }
5590
5661
 
5591
5662
  // ui/src/content/gallery/Gallery.jsx
5592
- import React40 from "react";
5663
+ import React41 from "react";
5593
5664
  var INLINE_SCRIPT2 = `(() => {
5594
5665
  if (typeof window === 'undefined') return;
5595
5666
  if (window.__canopyGalleryBound) return;
@@ -6100,7 +6171,7 @@ function shuffleItems(list) {
6100
6171
  function renderMetaList(meta, className) {
6101
6172
  const entries = ensureArray2(meta).filter((entry) => entry || entry === 0);
6102
6173
  if (!entries.length) return null;
6103
- return /* @__PURE__ */ React40.createElement("ul", { className, role: "list" }, entries.map((entry, index) => /* @__PURE__ */ React40.createElement("li", { key: `meta-${index}` }, entry)));
6174
+ return /* @__PURE__ */ React41.createElement("ul", { className, role: "list" }, entries.map((entry, index) => /* @__PURE__ */ React41.createElement("li", { key: `meta-${index}` }, entry)));
6104
6175
  }
6105
6176
  function renderPreview(props = {}) {
6106
6177
  const source = typeof props.media === "string" && props.media || props.thumbnail || props.src || props.image && props.image.src || props.image;
@@ -6108,7 +6179,7 @@ function renderPreview(props = {}) {
6108
6179
  const alt = props.thumbnailAlt || props.imageAlt || props.alt || props.title || "";
6109
6180
  const width = props.thumbnailWidth || props.imageWidth || props.width;
6110
6181
  const height = props.thumbnailHeight || props.imageHeight || props.height;
6111
- return /* @__PURE__ */ React40.createElement(
6182
+ return /* @__PURE__ */ React41.createElement(
6112
6183
  "img",
6113
6184
  {
6114
6185
  src: source,
@@ -6119,7 +6190,7 @@ function renderPreview(props = {}) {
6119
6190
  }
6120
6191
  );
6121
6192
  }
6122
- return /* @__PURE__ */ React40.createElement("div", { className: "canopy-gallery__placeholder", "aria-hidden": "true" });
6193
+ return /* @__PURE__ */ React41.createElement("div", { className: "canopy-gallery__placeholder", "aria-hidden": "true" });
6123
6194
  }
6124
6195
  function renderFlexibleContent(content, options = {}) {
6125
6196
  var _a, _b;
@@ -6132,25 +6203,25 @@ function renderFlexibleContent(content, options = {}) {
6132
6203
  if (content == null || content === false) return null;
6133
6204
  const isPrimitive = typeof content === "string" || typeof content === "number" || typeof content === "bigint";
6134
6205
  if (isPrimitive) {
6135
- return /* @__PURE__ */ React40.createElement(InlineTag, { className, id }, content);
6206
+ return /* @__PURE__ */ React41.createElement(InlineTag, { className, id }, content);
6136
6207
  }
6137
- if (React40.isValidElement(content)) {
6138
- if (content.type === React40.Fragment) {
6139
- return /* @__PURE__ */ React40.createElement(BlockTag, { className, id }, content);
6208
+ if (React41.isValidElement(content)) {
6209
+ if (content.type === React41.Fragment) {
6210
+ return /* @__PURE__ */ React41.createElement(BlockTag, { className, id }, content);
6140
6211
  }
6141
6212
  const mergedClassName = [(_a = content.props) == null ? void 0 : _a.className, className].filter(Boolean).join(" ");
6142
- return React40.cloneElement(content, {
6213
+ return React41.cloneElement(content, {
6143
6214
  ...content.props,
6144
6215
  className: mergedClassName || void 0,
6145
6216
  id: ((_b = content.props) == null ? void 0 : _b.id) || id
6146
6217
  });
6147
6218
  }
6148
6219
  const FallbackTag = BlockTag;
6149
- return /* @__PURE__ */ React40.createElement(FallbackTag, { className, id }, content);
6220
+ return /* @__PURE__ */ React41.createElement(FallbackTag, { className, id }, content);
6150
6221
  }
6151
6222
  function normalizeItem(child, index, galleryId, manifestMap) {
6152
6223
  var _a;
6153
- if (!React40.isValidElement(child)) return null;
6224
+ if (!React41.isValidElement(child)) return null;
6154
6225
  if (child.type !== GalleryItem && ((_a = child.type) == null ? void 0 : _a.displayName) !== "GalleryItem")
6155
6226
  return null;
6156
6227
  const props = child.props || {};
@@ -6225,7 +6296,7 @@ function buildCaptionContent(itemProps) {
6225
6296
  if (itemProps.caption) return itemProps.caption;
6226
6297
  const kicker = itemProps.kicker || itemProps.label || itemProps.eyebrow;
6227
6298
  const summary = itemProps.summary || itemProps.description;
6228
- return /* @__PURE__ */ React40.createElement(React40.Fragment, null, kicker ? /* @__PURE__ */ React40.createElement("span", { className: "canopy-gallery__kicker" }, kicker) : null, itemProps.title ? /* @__PURE__ */ React40.createElement("span", { className: "canopy-gallery__title-text" }, itemProps.title) : null, renderFlexibleContent(summary, {
6299
+ return /* @__PURE__ */ React41.createElement(React41.Fragment, null, kicker ? /* @__PURE__ */ React41.createElement("span", { className: "canopy-gallery__kicker" }, kicker) : null, itemProps.title ? /* @__PURE__ */ React41.createElement("span", { className: "canopy-gallery__title-text" }, itemProps.title) : null, renderFlexibleContent(summary, {
6229
6300
  inlineTag: "span",
6230
6301
  blockTag: "div",
6231
6302
  className: "canopy-gallery__summary"
@@ -6247,7 +6318,7 @@ function GalleryModal({ item, closeTargetId, navItems, navGroupName }) {
6247
6318
  const kicker = props.kicker || props.label || props.eyebrow;
6248
6319
  const summary = props.popupDescription || props.modalDescription || props.description || props.summary || null;
6249
6320
  const modalTitle = props.popupTitle || props.modalTitle || props.title || `Item ${index + 1}`;
6250
- return /* @__PURE__ */ React40.createElement(
6321
+ return /* @__PURE__ */ React41.createElement(
6251
6322
  "div",
6252
6323
  {
6253
6324
  id: modalId,
@@ -6260,14 +6331,14 @@ function GalleryModal({ item, closeTargetId, navItems, navGroupName }) {
6260
6331
  "data-canopy-gallery-modal": "true",
6261
6332
  "data-canopy-gallery-close": closeTargetId
6262
6333
  },
6263
- /* @__PURE__ */ React40.createElement("div", { className: "canopy-gallery__modal-scrim" }, /* @__PURE__ */ React40.createElement("div", { className: "canopy-gallery__modal-actions" }, /* @__PURE__ */ React40.createElement(
6334
+ /* @__PURE__ */ React41.createElement("div", { className: "canopy-gallery__modal-scrim" }, /* @__PURE__ */ React41.createElement("div", { className: "canopy-gallery__modal-actions" }, /* @__PURE__ */ React41.createElement(
6264
6335
  GalleryThumbnailNav,
6265
6336
  {
6266
6337
  items: navItems,
6267
6338
  activeModalId: modalId,
6268
6339
  groupName: `${navGroupName || "canopy-gallery"}-${modalId}`
6269
6340
  }
6270
- ), /* @__PURE__ */ React40.createElement(
6341
+ ), /* @__PURE__ */ React41.createElement(
6271
6342
  "a",
6272
6343
  {
6273
6344
  className: "canopy-gallery__modal-close",
@@ -6275,7 +6346,7 @@ function GalleryModal({ item, closeTargetId, navItems, navGroupName }) {
6275
6346
  "aria-label": `Close popup for ${modalTitle}`
6276
6347
  },
6277
6348
  "X"
6278
- )), /* @__PURE__ */ React40.createElement("div", { className: "canopy-gallery__modal-panel" }, /* @__PURE__ */ React40.createElement(
6349
+ )), /* @__PURE__ */ React41.createElement("div", { className: "canopy-gallery__modal-panel" }, /* @__PURE__ */ React41.createElement(
6279
6350
  "button",
6280
6351
  {
6281
6352
  type: "button",
@@ -6283,7 +6354,7 @@ function GalleryModal({ item, closeTargetId, navItems, navGroupName }) {
6283
6354
  "aria-label": "Scroll left through gallery thumbnails",
6284
6355
  "data-canopy-gallery-nav-prev": "true"
6285
6356
  },
6286
- /* @__PURE__ */ React40.createElement(
6357
+ /* @__PURE__ */ React41.createElement(
6287
6358
  "span",
6288
6359
  {
6289
6360
  className: "canopy-gallery__nav-button-icon",
@@ -6292,8 +6363,8 @@ function GalleryModal({ item, closeTargetId, navItems, navGroupName }) {
6292
6363
  },
6293
6364
  "<"
6294
6365
  ),
6295
- /* @__PURE__ */ React40.createElement("span", { className: "canopy-gallery__visually-hidden" }, "Previous item")
6296
- ), /* @__PURE__ */ React40.createElement(
6366
+ /* @__PURE__ */ React41.createElement("span", { className: "canopy-gallery__visually-hidden" }, "Previous item")
6367
+ ), /* @__PURE__ */ React41.createElement(
6297
6368
  "button",
6298
6369
  {
6299
6370
  type: "button",
@@ -6301,7 +6372,7 @@ function GalleryModal({ item, closeTargetId, navItems, navGroupName }) {
6301
6372
  "aria-label": "Scroll right through gallery thumbnails",
6302
6373
  "data-canopy-gallery-nav-next": "true"
6303
6374
  },
6304
- /* @__PURE__ */ React40.createElement(
6375
+ /* @__PURE__ */ React41.createElement(
6305
6376
  "span",
6306
6377
  {
6307
6378
  className: "canopy-gallery__nav-button-icon",
@@ -6310,8 +6381,8 @@ function GalleryModal({ item, closeTargetId, navItems, navGroupName }) {
6310
6381
  },
6311
6382
  ">"
6312
6383
  ),
6313
- /* @__PURE__ */ React40.createElement("span", { className: "canopy-gallery__visually-hidden" }, "Next item")
6314
- ), /* @__PURE__ */ React40.createElement("header", { className: "canopy-gallery__modal-header" }, /* @__PURE__ */ React40.createElement("div", { className: "canopy-gallery__modal-text" }, kicker ? /* @__PURE__ */ React40.createElement("p", { className: "canopy-gallery__modal-kicker" }, kicker) : null, /* @__PURE__ */ React40.createElement("h3", { id: modalTitleId, className: "canopy-gallery__modal-title" }, modalTitle), renderFlexibleContent(summary, {
6384
+ /* @__PURE__ */ React41.createElement("span", { className: "canopy-gallery__visually-hidden" }, "Next item")
6385
+ ), /* @__PURE__ */ React41.createElement("header", { className: "canopy-gallery__modal-header" }, /* @__PURE__ */ React41.createElement("div", { className: "canopy-gallery__modal-text" }, kicker ? /* @__PURE__ */ React41.createElement("p", { className: "canopy-gallery__modal-kicker" }, kicker) : null, /* @__PURE__ */ React41.createElement("h3", { id: modalTitleId, className: "canopy-gallery__modal-title" }, modalTitle), renderFlexibleContent(summary, {
6315
6386
  inlineTag: "p",
6316
6387
  blockTag: "div",
6317
6388
  className: "canopy-gallery__modal-summary",
@@ -6319,20 +6390,20 @@ function GalleryModal({ item, closeTargetId, navItems, navGroupName }) {
6319
6390
  }), renderMetaList(
6320
6391
  props.meta,
6321
6392
  "canopy-gallery__meta canopy-gallery__meta--modal"
6322
- ), manifests && manifests.length ? manifests.map((manifest) => /* @__PURE__ */ React40.createElement("a", { key: manifest.id || manifest.href, href: manifest.href }, manifest.title || manifest.href)) : null)), /* @__PURE__ */ React40.createElement("div", { className: "canopy-gallery__modal-body" }, props.children)))
6393
+ ), manifests && manifests.length ? manifests.map((manifest) => /* @__PURE__ */ React41.createElement("a", { key: manifest.id || manifest.href, href: manifest.href }, manifest.title || manifest.href)) : null)), /* @__PURE__ */ React41.createElement("div", { className: "canopy-gallery__modal-body" }, props.children)))
6323
6394
  );
6324
6395
  }
6325
6396
  function GalleryFigure({ item }) {
6326
6397
  const { props, modalId, triggerLabel } = item;
6327
- return /* @__PURE__ */ React40.createElement(
6398
+ return /* @__PURE__ */ React41.createElement(
6328
6399
  "figure",
6329
6400
  {
6330
6401
  className: "canopy-gallery__item",
6331
6402
  "data-gallery-item-index": item.index
6332
6403
  },
6333
- /* @__PURE__ */ React40.createElement("div", { className: "canopy-gallery__media" }, renderPreview(props)),
6334
- /* @__PURE__ */ React40.createElement("figcaption", { className: "canopy-gallery__caption" }, buildCaptionContent(props)),
6335
- /* @__PURE__ */ React40.createElement(
6404
+ /* @__PURE__ */ React41.createElement("div", { className: "canopy-gallery__media" }, renderPreview(props)),
6405
+ /* @__PURE__ */ React41.createElement("figcaption", { className: "canopy-gallery__caption" }, buildCaptionContent(props)),
6406
+ /* @__PURE__ */ React41.createElement(
6336
6407
  "a",
6337
6408
  {
6338
6409
  className: "canopy-gallery__trigger",
@@ -6342,27 +6413,27 @@ function GalleryFigure({ item }) {
6342
6413
  "aria-label": triggerLabel,
6343
6414
  "data-canopy-gallery-trigger": modalId
6344
6415
  },
6345
- /* @__PURE__ */ React40.createElement("span", { className: "canopy-gallery__trigger-label" }, triggerLabel)
6416
+ /* @__PURE__ */ React41.createElement("span", { className: "canopy-gallery__trigger-label" }, triggerLabel)
6346
6417
  )
6347
6418
  );
6348
6419
  }
6349
6420
  function GalleryThumbnailNav({ items, activeModalId, groupName }) {
6350
6421
  if (!items || items.length < 2) return null;
6351
6422
  const radioGroup = groupName || "canopy-gallery-nav";
6352
- return /* @__PURE__ */ React40.createElement(
6423
+ return /* @__PURE__ */ React41.createElement(
6353
6424
  "nav",
6354
6425
  {
6355
6426
  className: "canopy-gallery__nav",
6356
6427
  "aria-label": "Gallery navigation",
6357
6428
  "data-canopy-gallery-nav": "true"
6358
6429
  },
6359
- /* @__PURE__ */ React40.createElement(
6430
+ /* @__PURE__ */ React41.createElement(
6360
6431
  "div",
6361
6432
  {
6362
6433
  className: "canopy-gallery__nav-viewport",
6363
6434
  "data-canopy-gallery-nav-viewport": "true"
6364
6435
  },
6365
- /* @__PURE__ */ React40.createElement(
6436
+ /* @__PURE__ */ React41.createElement(
6366
6437
  "ul",
6367
6438
  {
6368
6439
  className: "canopy-gallery__nav-list",
@@ -6372,7 +6443,7 @@ function GalleryThumbnailNav({ items, activeModalId, groupName }) {
6372
6443
  items.map((item, index) => {
6373
6444
  const optionId = `${radioGroup}-${item.modalId || index}`;
6374
6445
  const isActive = item.modalId === activeModalId;
6375
- return /* @__PURE__ */ React40.createElement(
6446
+ return /* @__PURE__ */ React41.createElement(
6376
6447
  "li",
6377
6448
  {
6378
6449
  key: `${item.key}-nav`,
@@ -6380,7 +6451,7 @@ function GalleryThumbnailNav({ items, activeModalId, groupName }) {
6380
6451
  "data-canopy-gallery-nav-item": "true",
6381
6452
  "data-canopy-gallery-nav-selected": isActive ? "1" : void 0
6382
6453
  },
6383
- /* @__PURE__ */ React40.createElement(
6454
+ /* @__PURE__ */ React41.createElement(
6384
6455
  "input",
6385
6456
  {
6386
6457
  type: "radio",
@@ -6396,15 +6467,15 @@ function GalleryThumbnailNav({ items, activeModalId, groupName }) {
6396
6467
  "data-canopy-gallery-nav-selected": isActive ? "1" : void 0
6397
6468
  }
6398
6469
  ),
6399
- /* @__PURE__ */ React40.createElement(
6470
+ /* @__PURE__ */ React41.createElement(
6400
6471
  "label",
6401
6472
  {
6402
6473
  className: "canopy-gallery__nav-link",
6403
6474
  htmlFor: optionId,
6404
6475
  "data-canopy-gallery-nav-active": isActive ? "1" : void 0
6405
6476
  },
6406
- /* @__PURE__ */ React40.createElement("span", { className: "canopy-gallery__nav-thumb" }, renderPreview(item.props)),
6407
- /* @__PURE__ */ React40.createElement("span", { className: "canopy-gallery__nav-label" }, item.props.title || `Item ${item.index + 1}`)
6477
+ /* @__PURE__ */ React41.createElement("span", { className: "canopy-gallery__nav-thumb" }, renderPreview(item.props)),
6478
+ /* @__PURE__ */ React41.createElement("span", { className: "canopy-gallery__nav-label" }, item.props.title || `Item ${item.index + 1}`)
6408
6479
  )
6409
6480
  );
6410
6481
  })
@@ -6417,7 +6488,7 @@ function GalleryContent({ children, flex = false }) {
6417
6488
  "canopy-gallery-item__content",
6418
6489
  flex ? "canopy-gallery-item__content_flex" : null
6419
6490
  ].filter(Boolean).join(" ");
6420
- return /* @__PURE__ */ React40.createElement("div", { className: contentClassName }, children);
6491
+ return /* @__PURE__ */ React41.createElement("div", { className: contentClassName }, children);
6421
6492
  }
6422
6493
  function GalleryItem() {
6423
6494
  return null;
@@ -6441,7 +6512,7 @@ function Gallery({
6441
6512
  const galleryId = id ? String(id) : nextGalleryInstanceId();
6442
6513
  const HeadingTag = "h3";
6443
6514
  const closeTargetId = `${galleryId}-close`;
6444
- const childArray = React40.Children.toArray(children);
6515
+ const childArray = React41.Children.toArray(children);
6445
6516
  const items = childArray.map((child, index) => normalizeItem(child, index, galleryId, manifestMap)).filter(Boolean);
6446
6517
  if (!items.length) return null;
6447
6518
  const popupMode = normalizePopupSize(popupSize);
@@ -6453,7 +6524,7 @@ function Gallery({
6453
6524
  className
6454
6525
  ].filter(Boolean).join(" ");
6455
6526
  const navGroupName = `${galleryId}-nav`;
6456
- return /* @__PURE__ */ React40.createElement("section", { className: rootClassName, style, "data-canopy-gallery": "true" }, /* @__PURE__ */ React40.createElement(
6527
+ return /* @__PURE__ */ React41.createElement("section", { className: rootClassName, style, "data-canopy-gallery": "true" }, /* @__PURE__ */ React41.createElement(
6457
6528
  "div",
6458
6529
  {
6459
6530
  id: closeTargetId,
@@ -6461,7 +6532,7 @@ function Gallery({
6461
6532
  "aria-hidden": "true",
6462
6533
  tabIndex: -1
6463
6534
  }
6464
- ), (title || description) && /* @__PURE__ */ React40.createElement("div", { className: "canopy-gallery__header" }, title ? /* @__PURE__ */ React40.createElement(HeadingTag, { className: "canopy-gallery__heading" }, title) : null, description ? /* @__PURE__ */ React40.createElement("p", { className: "canopy-gallery__description" }, description) : null), /* @__PURE__ */ React40.createElement("div", { className: "canopy-gallery__grid" }, orderedItems.map((item) => /* @__PURE__ */ React40.createElement(GalleryFigure, { key: item.key, item }))), /* @__PURE__ */ React40.createElement("div", { className: "canopy-gallery__modals" }, orderedItems.map((item) => /* @__PURE__ */ React40.createElement(
6535
+ ), (title || description) && /* @__PURE__ */ React41.createElement("div", { className: "canopy-gallery__header" }, title ? /* @__PURE__ */ React41.createElement(HeadingTag, { className: "canopy-gallery__heading" }, title) : null, description ? /* @__PURE__ */ React41.createElement("p", { className: "canopy-gallery__description" }, description) : null), /* @__PURE__ */ React41.createElement("div", { className: "canopy-gallery__grid" }, orderedItems.map((item) => /* @__PURE__ */ React41.createElement(GalleryFigure, { key: item.key, item }))), /* @__PURE__ */ React41.createElement("div", { className: "canopy-gallery__modals" }, orderedItems.map((item) => /* @__PURE__ */ React41.createElement(
6465
6536
  GalleryModal,
6466
6537
  {
6467
6538
  key: `${item.modalId}-modal`,
@@ -6470,7 +6541,7 @@ function Gallery({
6470
6541
  navItems: orderedItems,
6471
6542
  navGroupName
6472
6543
  }
6473
- ))), /* @__PURE__ */ React40.createElement(
6544
+ ))), /* @__PURE__ */ React41.createElement(
6474
6545
  "script",
6475
6546
  {
6476
6547
  "data-canopy-gallery-script": "true",
@@ -6482,7 +6553,7 @@ Gallery.Item = GalleryItem;
6482
6553
  Gallery.Content = GalleryContent;
6483
6554
 
6484
6555
  // ui/src/search/MdxSearchResults.jsx
6485
- import React41 from "react";
6556
+ import React42 from "react";
6486
6557
  function MdxSearchResults(props) {
6487
6558
  let json = "{}";
6488
6559
  try {
@@ -6490,11 +6561,11 @@ function MdxSearchResults(props) {
6490
6561
  } catch (_) {
6491
6562
  json = "{}";
6492
6563
  }
6493
- return /* @__PURE__ */ React41.createElement("div", { "data-canopy-search-results": "1" }, /* @__PURE__ */ React41.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
6564
+ return /* @__PURE__ */ React42.createElement("div", { "data-canopy-search-results": "1" }, /* @__PURE__ */ React42.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
6494
6565
  }
6495
6566
 
6496
6567
  // ui/src/search/SearchSummary.jsx
6497
- import React42 from "react";
6568
+ import React43 from "react";
6498
6569
  function SearchSummary(props) {
6499
6570
  let json = "{}";
6500
6571
  try {
@@ -6502,11 +6573,11 @@ function SearchSummary(props) {
6502
6573
  } catch (_) {
6503
6574
  json = "{}";
6504
6575
  }
6505
- return /* @__PURE__ */ React42.createElement("div", { "data-canopy-search-summary": "1" }, /* @__PURE__ */ React42.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
6576
+ return /* @__PURE__ */ React43.createElement("div", { "data-canopy-search-summary": "1" }, /* @__PURE__ */ React43.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
6506
6577
  }
6507
6578
 
6508
6579
  // ui/src/search/MdxSearchTabs.jsx
6509
- import React43 from "react";
6580
+ import React44 from "react";
6510
6581
  function MdxSearchTabs(props) {
6511
6582
  let json = "{}";
6512
6583
  try {
@@ -6514,11 +6585,11 @@ function MdxSearchTabs(props) {
6514
6585
  } catch (_) {
6515
6586
  json = "{}";
6516
6587
  }
6517
- return /* @__PURE__ */ React43.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React43.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
6588
+ return /* @__PURE__ */ React44.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React44.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
6518
6589
  }
6519
6590
 
6520
6591
  // ui/src/search/MdxSearch.jsx
6521
- import React44 from "react";
6592
+ import React45 from "react";
6522
6593
  function MdxSearch(props = {}) {
6523
6594
  const {
6524
6595
  layout,
@@ -6536,11 +6607,11 @@ function MdxSearch(props = {}) {
6536
6607
  resultsPayload.layout = layout;
6537
6608
  }
6538
6609
  const classes = ["canopy-search", className].filter(Boolean).join(" ");
6539
- return /* @__PURE__ */ React44.createElement("section", { className: classes, "data-canopy-search": "1" }, showTabs ? /* @__PURE__ */ React44.createElement(MdxSearchTabs, { ...tabsProps }) : null, showSummary ? /* @__PURE__ */ React44.createElement(SearchSummary, { ...summaryProps }) : null, showResults ? /* @__PURE__ */ React44.createElement(MdxSearchResults, { ...resultsPayload }) : null, children || null);
6610
+ return /* @__PURE__ */ React45.createElement("section", { className: classes, "data-canopy-search": "1" }, showTabs ? /* @__PURE__ */ React45.createElement(MdxSearchTabs, { ...tabsProps }) : null, showSummary ? /* @__PURE__ */ React45.createElement(SearchSummary, { ...summaryProps }) : null, showResults ? /* @__PURE__ */ React45.createElement(MdxSearchResults, { ...resultsPayload }) : null, children || null);
6540
6611
  }
6541
6612
 
6542
6613
  // ui/src/search-form/MdxSearchFormModal.jsx
6543
- import React45 from "react";
6614
+ import React46 from "react";
6544
6615
  function MdxSearchFormModal(props = {}) {
6545
6616
  const {
6546
6617
  placeholder: placeholderProp,
@@ -6559,12 +6630,12 @@ function MdxSearchFormModal(props = {}) {
6559
6630
  const text = typeof label === "string" && label.trim() ? label.trim() : resolvedButtonLabel;
6560
6631
  const resolvedSearchPath = resolveSearchPath(searchPath);
6561
6632
  const data = { placeholder, hotkey, maxResults, groupOrder, label: text, searchPath: resolvedSearchPath };
6562
- return /* @__PURE__ */ React45.createElement("div", { "data-canopy-search-form": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React45.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React45.createElement(SearchPanelForm, { placeholder, buttonLabel: resolvedButtonLabel, label, searchPath: resolvedSearchPath }), /* @__PURE__ */ React45.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React45.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
6633
+ return /* @__PURE__ */ React46.createElement("div", { "data-canopy-search-form": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React46.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React46.createElement(SearchPanelForm, { placeholder, buttonLabel: resolvedButtonLabel, label, searchPath: resolvedSearchPath }), /* @__PURE__ */ React46.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React46.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
6563
6634
  }
6564
6635
 
6565
6636
  // ui/src/iiif/ManifestPrimitives.jsx
6566
6637
  var import_slugify2 = __toESM(require_slugify());
6567
- import React46 from "react";
6638
+ import React47 from "react";
6568
6639
  import {
6569
6640
  Label as CloverLabel,
6570
6641
  Metadata as CloverMetadata,
@@ -6705,7 +6776,7 @@ function MetadataFacetLink(props) {
6705
6776
  const valueSlug = facetSlug ? toValueSlug(text) : "";
6706
6777
  const href = facetSlug && valueSlug ? buildFacetSearchHref(facetSlug, valueSlug) : "";
6707
6778
  if (!href) return text;
6708
- return /* @__PURE__ */ React46.createElement(
6779
+ return /* @__PURE__ */ React47.createElement(
6709
6780
  "a",
6710
6781
  {
6711
6782
  href,
@@ -6731,7 +6802,7 @@ function buildFacetCustomValueContent(items, manifest) {
6731
6802
  seen.add(normalized);
6732
6803
  custom.push({
6733
6804
  matchingLabel: item.label,
6734
- Content: /* @__PURE__ */ React46.createElement(MetadataFacetLink, { facetSlug: facet.slug })
6805
+ Content: /* @__PURE__ */ React47.createElement(MetadataFacetLink, { facetSlug: facet.slug })
6735
6806
  });
6736
6807
  }
6737
6808
  return custom;
@@ -6763,12 +6834,12 @@ function mergeCustomValueContent(userContent, autoContent) {
6763
6834
  function Label({ manifest, label, ...rest }) {
6764
6835
  const intl = label || manifest && manifest.label;
6765
6836
  if (!hasInternationalValue(intl)) return null;
6766
- return /* @__PURE__ */ React46.createElement(CloverLabel, { label: intl, ...rest });
6837
+ return /* @__PURE__ */ React47.createElement(CloverLabel, { label: intl, ...rest });
6767
6838
  }
6768
6839
  function Summary({ manifest, summary, ...rest }) {
6769
6840
  const intl = summary || manifest && manifest.summary;
6770
6841
  if (!hasInternationalValue(intl)) return null;
6771
- return /* @__PURE__ */ React46.createElement(CloverSummary, { summary: intl, ...rest });
6842
+ return /* @__PURE__ */ React47.createElement(CloverSummary, { summary: intl, ...rest });
6772
6843
  }
6773
6844
  function Metadata({ manifest, metadata, customValueContent, ...rest }) {
6774
6845
  const items = ensureMetadata(metadata || manifest && manifest.metadata);
@@ -6778,7 +6849,7 @@ function Metadata({ manifest, metadata, customValueContent, ...rest }) {
6778
6849
  customValueContent,
6779
6850
  autoCustomContent
6780
6851
  );
6781
- return /* @__PURE__ */ React46.createElement(
6852
+ return /* @__PURE__ */ React47.createElement(
6782
6853
  CloverMetadata,
6783
6854
  {
6784
6855
  metadata: items,
@@ -6792,17 +6863,17 @@ function RequiredStatement({ manifest, requiredStatement, ...rest }) {
6792
6863
  if (!stmt || !hasInternationalValue(stmt.label) || !hasInternationalValue(stmt.value)) {
6793
6864
  return null;
6794
6865
  }
6795
- return /* @__PURE__ */ React46.createElement(CloverRequiredStatement, { requiredStatement: stmt, ...rest });
6866
+ return /* @__PURE__ */ React47.createElement(CloverRequiredStatement, { requiredStatement: stmt, ...rest });
6796
6867
  }
6797
6868
 
6798
6869
  // ui/src/iiif/Properties/Id.jsx
6799
- import React47 from "react";
6870
+ import React48 from "react";
6800
6871
  function Id({ title = "IIIF Manifest", id, ...props }) {
6801
- return /* @__PURE__ */ React47.createElement("dl", null, /* @__PURE__ */ React47.createElement("dt", null, title), /* @__PURE__ */ React47.createElement("dd", null, /* @__PURE__ */ React47.createElement("a", { href: id }, id)));
6872
+ return /* @__PURE__ */ React48.createElement("dl", null, /* @__PURE__ */ React48.createElement("dt", null, title), /* @__PURE__ */ React48.createElement("dd", null, /* @__PURE__ */ React48.createElement("a", { href: id }, id)));
6802
6873
  }
6803
6874
 
6804
6875
  // ui/src/docs/CodeBlock.jsx
6805
- import React48 from "react";
6876
+ import React49 from "react";
6806
6877
  function parseHighlightAttr(attr) {
6807
6878
  if (!attr) return /* @__PURE__ */ new Set();
6808
6879
  const cleaned = String(attr || "").trim();
@@ -6848,10 +6919,10 @@ var highlightBaseStyle = {
6848
6919
  };
6849
6920
  function DocsCodeBlock(props = {}) {
6850
6921
  const { children, ...rest } = props;
6851
- const childArray = React48.Children.toArray(children);
6852
- const codeElement = childArray.find((el) => React48.isValidElement(el));
6922
+ const childArray = React49.Children.toArray(children);
6923
+ const codeElement = childArray.find((el) => React49.isValidElement(el));
6853
6924
  if (!codeElement || !codeElement.props) {
6854
- return React48.createElement("pre", props);
6925
+ return React49.createElement("pre", props);
6855
6926
  }
6856
6927
  const {
6857
6928
  className = "",
@@ -6866,9 +6937,9 @@ function DocsCodeBlock(props = {}) {
6866
6937
  const highlightSet = parseHighlightAttr(highlightAttr);
6867
6938
  const copyAttr = codeProps["data-copy"];
6868
6939
  const enableCopy = copyAttr !== void 0 ? copyAttr === true || copyAttr === "true" || copyAttr === "" : false;
6869
- const [copied, setCopied] = React48.useState(false);
6870
- const buttonRef = React48.useRef(null);
6871
- const handleCopy = React48.useCallback(async () => {
6940
+ const [copied, setCopied] = React49.useState(false);
6941
+ const buttonRef = React49.useRef(null);
6942
+ const handleCopy = React49.useCallback(async () => {
6872
6943
  const text = trimmedCode;
6873
6944
  try {
6874
6945
  if (typeof navigator !== "undefined" && navigator.clipboard && navigator.clipboard.writeText) {
@@ -6890,12 +6961,12 @@ function DocsCodeBlock(props = {}) {
6890
6961
  setCopied(false);
6891
6962
  }
6892
6963
  }, [trimmedCode]);
6893
- React48.useEffect(() => {
6964
+ React49.useEffect(() => {
6894
6965
  if (buttonRef.current) {
6895
6966
  buttonRef.current.setAttribute("data-docs-copy-hydrated", "true");
6896
6967
  }
6897
6968
  }, []);
6898
- React48.useEffect(() => {
6969
+ React49.useEffect(() => {
6899
6970
  if (!buttonRef.current) return;
6900
6971
  if (copied) buttonRef.current.setAttribute("data-docs-copy-active", "true");
6901
6972
  else buttonRef.current.removeAttribute("data-docs-copy-active");
@@ -6958,27 +7029,27 @@ function DocsCodeBlock(props = {}) {
6958
7029
  const highlight = highlightSet.has(lineNumber);
6959
7030
  const style = highlight ? { ...baseLineStyle, ...highlightBaseStyle } : baseLineStyle;
6960
7031
  const displayLine = line === "" ? " " : line;
6961
- return React48.createElement(
7032
+ return React49.createElement(
6962
7033
  "span",
6963
7034
  {
6964
7035
  key: lineNumber,
6965
7036
  style,
6966
7037
  "data-docs-code-line": line
6967
7038
  },
6968
- React48.createElement("span", { style: lineContentStyle }, displayLine)
7039
+ React49.createElement("span", { style: lineContentStyle }, displayLine)
6969
7040
  );
6970
7041
  });
6971
- return React48.createElement(
7042
+ return React49.createElement(
6972
7043
  "div",
6973
7044
  {
6974
7045
  style: containerStyle,
6975
7046
  "data-docs-code-block": "true"
6976
7047
  },
6977
- showHeader ? React48.createElement(
7048
+ showHeader ? React49.createElement(
6978
7049
  "div",
6979
7050
  { style: headerStyle },
6980
- React48.createElement("span", null, showFilename ? filename : null),
6981
- enableCopy ? React48.createElement(
7051
+ React49.createElement("span", null, showFilename ? filename : null),
7052
+ enableCopy ? React49.createElement(
6982
7053
  "button",
6983
7054
  {
6984
7055
  ref: buttonRef,
@@ -6989,8 +7060,8 @@ function DocsCodeBlock(props = {}) {
6989
7060
  "data-docs-copy-button": "true",
6990
7061
  style: buttonStyle
6991
7062
  },
6992
- React48.createElement("span", null, "Copy"),
6993
- React48.createElement(
7063
+ React49.createElement("span", null, "Copy"),
7064
+ React49.createElement(
6994
7065
  "span",
6995
7066
  {
6996
7067
  "aria-hidden": "true",
@@ -7000,7 +7071,7 @@ function DocsCodeBlock(props = {}) {
7000
7071
  )
7001
7072
  ) : null
7002
7073
  ) : null,
7003
- enableCopy ? React48.createElement("textarea", {
7074
+ enableCopy ? React49.createElement("textarea", {
7004
7075
  "data-docs-copy-source": "true",
7005
7076
  tabIndex: -1,
7006
7077
  readOnly: true,
@@ -7015,29 +7086,29 @@ function DocsCodeBlock(props = {}) {
7015
7086
  pointerEvents: "none"
7016
7087
  }
7017
7088
  }) : null,
7018
- React48.createElement(
7089
+ React49.createElement(
7019
7090
  "pre",
7020
7091
  { ...preRest, className: preClassName, style: mergedPreStyle },
7021
- React48.createElement("code", { style: codeStyle }, lineElements)
7092
+ React49.createElement("code", { style: codeStyle }, lineElements)
7022
7093
  )
7023
7094
  );
7024
7095
  }
7025
7096
 
7026
7097
  // ui/src/docs/MarkdownTable.jsx
7027
- import React49 from "react";
7098
+ import React50 from "react";
7028
7099
  function MarkdownTable({ className = "", ...rest }) {
7029
7100
  const merged = ["markdown-table", className].filter(Boolean).join(" ");
7030
- return /* @__PURE__ */ React49.createElement("div", { className: "markdown-table__frame" }, /* @__PURE__ */ React49.createElement("table", { className: merged, ...rest }));
7101
+ return /* @__PURE__ */ React50.createElement("div", { className: "markdown-table__frame" }, /* @__PURE__ */ React50.createElement("table", { className: merged, ...rest }));
7031
7102
  }
7032
7103
 
7033
7104
  // ui/src/docs/Diagram.jsx
7034
- import React50 from "react";
7105
+ import React51 from "react";
7035
7106
  function CanopyDiagram() {
7036
- return /* @__PURE__ */ React50.createElement("div", { className: "canopy-diagram" }, /* @__PURE__ */ React50.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--collections" }, /* @__PURE__ */ React50.createElement("h3", null, "IIIF Providers"), /* @__PURE__ */ React50.createElement("span", { className: "canopy-diagram__section-summary" }, "Source collections contribute 45 manifests while 5 manifests are directly retrieved as-is via IIIF endpoints."), /* @__PURE__ */ React50.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React50.createElement("article", null, /* @__PURE__ */ React50.createElement("h4", null, "Collection A"), /* @__PURE__ */ React50.createElement("ul", null, /* @__PURE__ */ React50.createElement("li", null, "30 Manifests"), /* @__PURE__ */ React50.createElement("li", null, /* @__PURE__ */ React50.createElement("em", null, "Manuscripts")))), /* @__PURE__ */ React50.createElement("article", null, /* @__PURE__ */ React50.createElement("h4", null, "Collection B"), /* @__PURE__ */ React50.createElement("ul", null, /* @__PURE__ */ React50.createElement("li", null, "15 Manifests"), /* @__PURE__ */ React50.createElement("li", null, /* @__PURE__ */ React50.createElement("em", null, "Portraits")))), /* @__PURE__ */ React50.createElement("article", null, /* @__PURE__ */ React50.createElement("h4", null, "Manifests (direct)"), /* @__PURE__ */ React50.createElement("ul", null, /* @__PURE__ */ React50.createElement("li", null, "5 Manifests"), /* @__PURE__ */ React50.createElement("li", null, /* @__PURE__ */ React50.createElement("em", null, "Scrapbooks")))))), /* @__PURE__ */ React50.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React50.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React50.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React50.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--build" }, /* @__PURE__ */ React50.createElement("h3", null, "Canopy Build Process"), /* @__PURE__ */ React50.createElement("span", { className: "canopy-diagram__section-summary" }, "Canopy retrieves collections and syncs all manifests, page content, and annotations before bundling the site."), /* @__PURE__ */ React50.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React50.createElement("article", null, /* @__PURE__ */ React50.createElement("h4", null, "Automated content"), /* @__PURE__ */ React50.createElement("ul", null, /* @__PURE__ */ React50.createElement("li", null, "50 manifests \u2192 50 work pages"), /* @__PURE__ */ React50.createElement("li", null, "One page per manifest"), /* @__PURE__ */ React50.createElement("li", null, "Customize page layout"))), /* @__PURE__ */ React50.createElement("article", null, /* @__PURE__ */ React50.createElement("h4", null, "Contextual content"), /* @__PURE__ */ React50.createElement("ul", null, /* @__PURE__ */ React50.createElement("li", null, "Markdown & MDX pages"), /* @__PURE__ */ React50.createElement("li", null, "Author narratives"), /* @__PURE__ */ React50.createElement("li", null, "Reference manifests inline"))), /* @__PURE__ */ React50.createElement("article", null, /* @__PURE__ */ React50.createElement("h4", null, "Search index"), /* @__PURE__ */ React50.createElement("ul", null, /* @__PURE__ */ React50.createElement("li", null, "Combines works + pages"), /* @__PURE__ */ React50.createElement("li", null, "Customize result layout"), /* @__PURE__ */ React50.createElement("li", null, "Optional annotations"))))), /* @__PURE__ */ React50.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React50.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React50.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React50.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--output" }, /* @__PURE__ */ React50.createElement("h3", null, "Static Digital Project"), /* @__PURE__ */ React50.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__ */ React50.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React50.createElement("article", null, /* @__PURE__ */ React50.createElement("h4", null, "Work pages"), /* @__PURE__ */ React50.createElement("ul", null, /* @__PURE__ */ React50.createElement("li", null, "50 generated HTML pages"), /* @__PURE__ */ React50.createElement("li", null, "Each links back to source manifests"), /* @__PURE__ */ React50.createElement("li", null, "Styled with Canopy components"))), /* @__PURE__ */ React50.createElement("article", null, /* @__PURE__ */ React50.createElement("h4", null, "Custom pages"), /* @__PURE__ */ React50.createElement("ul", null, /* @__PURE__ */ React50.createElement("li", null, "Markdown & MDX-authored content"), /* @__PURE__ */ React50.createElement("li", null, "Reusable layouts for narratives"), /* @__PURE__ */ React50.createElement("li", null, "Embed IIIF media & interstitials"))), /* @__PURE__ */ React50.createElement("article", null, /* @__PURE__ */ React50.createElement("h4", null, "Search bundle"), /* @__PURE__ */ React50.createElement("ul", null, /* @__PURE__ */ React50.createElement("li", null, "Static FlexSearch index"), /* @__PURE__ */ React50.createElement("li", null, "Works + pages share records"), /* @__PURE__ */ React50.createElement("li", null, "Optional annotation dataset"))))));
7107
+ return /* @__PURE__ */ React51.createElement("div", { className: "canopy-diagram" }, /* @__PURE__ */ React51.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--collections" }, /* @__PURE__ */ React51.createElement("h3", null, "IIIF Providers"), /* @__PURE__ */ React51.createElement("span", { className: "canopy-diagram__section-summary" }, "Source collections contribute 45 manifests while 5 manifests are directly retrieved as-is via IIIF endpoints."), /* @__PURE__ */ React51.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React51.createElement("article", null, /* @__PURE__ */ React51.createElement("h4", null, "Collection A"), /* @__PURE__ */ React51.createElement("ul", null, /* @__PURE__ */ React51.createElement("li", null, "30 Manifests"), /* @__PURE__ */ React51.createElement("li", null, /* @__PURE__ */ React51.createElement("em", null, "Manuscripts")))), /* @__PURE__ */ React51.createElement("article", null, /* @__PURE__ */ React51.createElement("h4", null, "Collection B"), /* @__PURE__ */ React51.createElement("ul", null, /* @__PURE__ */ React51.createElement("li", null, "15 Manifests"), /* @__PURE__ */ React51.createElement("li", null, /* @__PURE__ */ React51.createElement("em", null, "Portraits")))), /* @__PURE__ */ React51.createElement("article", null, /* @__PURE__ */ React51.createElement("h4", null, "Manifests (direct)"), /* @__PURE__ */ React51.createElement("ul", null, /* @__PURE__ */ React51.createElement("li", null, "5 Manifests"), /* @__PURE__ */ React51.createElement("li", null, /* @__PURE__ */ React51.createElement("em", null, "Scrapbooks")))))), /* @__PURE__ */ React51.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React51.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React51.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React51.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--build" }, /* @__PURE__ */ React51.createElement("h3", null, "Canopy Build Process"), /* @__PURE__ */ React51.createElement("span", { className: "canopy-diagram__section-summary" }, "Canopy retrieves collections and syncs all manifests, page content, and annotations before bundling the site."), /* @__PURE__ */ React51.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React51.createElement("article", null, /* @__PURE__ */ React51.createElement("h4", null, "Automated content"), /* @__PURE__ */ React51.createElement("ul", null, /* @__PURE__ */ React51.createElement("li", null, "50 manifests \u2192 50 work pages"), /* @__PURE__ */ React51.createElement("li", null, "One page per manifest"), /* @__PURE__ */ React51.createElement("li", null, "Customize page layout"))), /* @__PURE__ */ React51.createElement("article", null, /* @__PURE__ */ React51.createElement("h4", null, "Contextual content"), /* @__PURE__ */ React51.createElement("ul", null, /* @__PURE__ */ React51.createElement("li", null, "Markdown & MDX pages"), /* @__PURE__ */ React51.createElement("li", null, "Author narratives"), /* @__PURE__ */ React51.createElement("li", null, "Reference manifests inline"))), /* @__PURE__ */ React51.createElement("article", null, /* @__PURE__ */ React51.createElement("h4", null, "Search index"), /* @__PURE__ */ React51.createElement("ul", null, /* @__PURE__ */ React51.createElement("li", null, "Combines works + pages"), /* @__PURE__ */ React51.createElement("li", null, "Customize result layout"), /* @__PURE__ */ React51.createElement("li", null, "Optional annotations"))))), /* @__PURE__ */ React51.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React51.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React51.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React51.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--output" }, /* @__PURE__ */ React51.createElement("h3", null, "Static Digital Project"), /* @__PURE__ */ React51.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__ */ React51.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React51.createElement("article", null, /* @__PURE__ */ React51.createElement("h4", null, "Work pages"), /* @__PURE__ */ React51.createElement("ul", null, /* @__PURE__ */ React51.createElement("li", null, "50 generated HTML pages"), /* @__PURE__ */ React51.createElement("li", null, "Each links back to source manifests"), /* @__PURE__ */ React51.createElement("li", null, "Styled with Canopy components"))), /* @__PURE__ */ React51.createElement("article", null, /* @__PURE__ */ React51.createElement("h4", null, "Custom pages"), /* @__PURE__ */ React51.createElement("ul", null, /* @__PURE__ */ React51.createElement("li", null, "Markdown & MDX-authored content"), /* @__PURE__ */ React51.createElement("li", null, "Reusable layouts for narratives"), /* @__PURE__ */ React51.createElement("li", null, "Embed IIIF media & interstitials"))), /* @__PURE__ */ React51.createElement("article", null, /* @__PURE__ */ React51.createElement("h4", null, "Search bundle"), /* @__PURE__ */ React51.createElement("ul", null, /* @__PURE__ */ React51.createElement("li", null, "Static FlexSearch index"), /* @__PURE__ */ React51.createElement("li", null, "Works + pages share records"), /* @__PURE__ */ React51.createElement("li", null, "Optional annotation dataset"))))));
7037
7108
  }
7038
7109
 
7039
7110
  // ui/src/docs/ThemeShowcase.jsx
7040
- import React51 from "react";
7111
+ import React52 from "react";
7041
7112
 
7042
7113
  // ../../node_modules/@radix-ui/colors/index.mjs
7043
7114
  var colors_exports = {};
@@ -10889,21 +10960,21 @@ var STEP_MAP = {
10889
10960
  800: 11,
10890
10961
  900: 12
10891
10962
  };
10892
- var Section = ({ title, description, children }) => /* @__PURE__ */ React51.createElement("div", { className: "canopy-theme-showcase__section" }, /* @__PURE__ */ React51.createElement("h3", { className: "canopy-theme-showcase__section-title" }, title), description ? /* @__PURE__ */ React51.createElement("p", { className: "canopy-theme-showcase__section-description" }, description) : null, children);
10893
- var ColorScaleRow = ({ label, prefix }) => /* @__PURE__ */ React51.createElement("div", { className: "canopy-theme-showcase__scale-row" }, /* @__PURE__ */ React51.createElement("div", { className: "canopy-theme-showcase__scale-label" }, /* @__PURE__ */ React51.createElement("strong", null, label)), /* @__PURE__ */ React51.createElement("div", { className: "canopy-theme-showcase__scale-track" }, COLOR_STOPS.map((stop) => /* @__PURE__ */ React51.createElement(
10963
+ var Section = ({ title, description, children }) => /* @__PURE__ */ React52.createElement("div", { className: "canopy-theme-showcase__section" }, /* @__PURE__ */ React52.createElement("h3", { className: "canopy-theme-showcase__section-title" }, title), description ? /* @__PURE__ */ React52.createElement("p", { className: "canopy-theme-showcase__section-description" }, description) : null, children);
10964
+ var ColorScaleRow = ({ label, prefix }) => /* @__PURE__ */ React52.createElement("div", { className: "canopy-theme-showcase__scale-row" }, /* @__PURE__ */ React52.createElement("div", { className: "canopy-theme-showcase__scale-label" }, /* @__PURE__ */ React52.createElement("strong", null, label)), /* @__PURE__ */ React52.createElement("div", { className: "canopy-theme-showcase__scale-track" }, COLOR_STOPS.map((stop) => /* @__PURE__ */ React52.createElement(
10894
10965
  "div",
10895
10966
  {
10896
10967
  key: `${label}-${stop}`,
10897
10968
  className: "canopy-theme-showcase__scale-stop"
10898
10969
  },
10899
- /* @__PURE__ */ React51.createElement(
10970
+ /* @__PURE__ */ React52.createElement(
10900
10971
  "span",
10901
10972
  {
10902
10973
  className: "canopy-theme-showcase__scale-chip",
10903
10974
  style: { backgroundColor: `var(${prefix}-${stop})` }
10904
10975
  }
10905
10976
  ),
10906
- /* @__PURE__ */ React51.createElement("span", { className: "canopy-theme-showcase__scale-token" }, stop)
10977
+ /* @__PURE__ */ React52.createElement("span", { className: "canopy-theme-showcase__scale-token" }, stop)
10907
10978
  ))));
10908
10979
  var AVAILABLE = new Set(
10909
10980
  Object.keys(colors_exports).filter(
@@ -10968,9 +11039,9 @@ var PREVIEW_DATA = buildPreviewData();
10968
11039
  function encodeJson(value) {
10969
11040
  return JSON.stringify(value).replace(/</g, "\\u003c");
10970
11041
  }
10971
- var ColorsLabeled = ({ colors, type, getRadixSwatch }) => /* @__PURE__ */ React51.createElement("div", { className: "canopy-theme-showcase__swatch-grid" }, colors.map((name) => {
11042
+ var ColorsLabeled = ({ colors, type, getRadixSwatch }) => /* @__PURE__ */ React52.createElement("div", { className: "canopy-theme-showcase__swatch-grid" }, colors.map((name) => {
10972
11043
  const colorValue = getRadixSwatch(name);
10973
- return /* @__PURE__ */ React51.createElement(
11044
+ return /* @__PURE__ */ React52.createElement(
10974
11045
  "button",
10975
11046
  {
10976
11047
  key: `${type}-${name}`,
@@ -10981,14 +11052,14 @@ var ColorsLabeled = ({ colors, type, getRadixSwatch }) => /* @__PURE__ */ React5
10981
11052
  "data-theme-swatch-value": name,
10982
11053
  "aria-pressed": "false"
10983
11054
  },
10984
- /* @__PURE__ */ React51.createElement(
11055
+ /* @__PURE__ */ React52.createElement(
10985
11056
  "span",
10986
11057
  {
10987
11058
  className: "canopy-theme-showcase__swatch-chip",
10988
11059
  style: { background: colorValue || "var(--color-gray-200)" }
10989
11060
  }
10990
11061
  ),
10991
- /* @__PURE__ */ React51.createElement("span", { className: "canopy-theme-showcase__swatch-label" }, name)
11062
+ /* @__PURE__ */ React52.createElement("span", { className: "canopy-theme-showcase__swatch-label" }, name)
10992
11063
  );
10993
11064
  }));
10994
11065
  function ThemeShowcase() {
@@ -11148,7 +11219,7 @@ function ThemeShowcase() {
11148
11219
  .canopy-theme-showcase__swatch-controls { display: none; }
11149
11220
  .canopy-theme-showcase__clear-button { display: none; }
11150
11221
  `;
11151
- return /* @__PURE__ */ React51.createElement("div", { className: "canopy-theme-showcase", "data-theme-showcase": true }, /* @__PURE__ */ React51.createElement("style", { dangerouslySetInnerHTML: { __html: styles } }), /* @__PURE__ */ React51.createElement(
11222
+ return /* @__PURE__ */ React52.createElement("div", { className: "canopy-theme-showcase", "data-theme-showcase": true }, /* @__PURE__ */ React52.createElement("style", { dangerouslySetInnerHTML: { __html: styles } }), /* @__PURE__ */ React52.createElement(
11152
11223
  "div",
11153
11224
  {
11154
11225
  style: {
@@ -11159,18 +11230,18 @@ function ThemeShowcase() {
11159
11230
  marginBottom: "1rem"
11160
11231
  }
11161
11232
  },
11162
- /* @__PURE__ */ React51.createElement(
11233
+ /* @__PURE__ */ React52.createElement(
11163
11234
  Section,
11164
11235
  {
11165
11236
  title: "Appearance",
11166
11237
  description: "Pick the base light or dark mode for the theme preview."
11167
11238
  },
11168
- /* @__PURE__ */ React51.createElement("div", { className: "canopy-theme-showcase__appearance-buttons" }, ["light", "dark"].map((mode) => {
11239
+ /* @__PURE__ */ React52.createElement("div", { className: "canopy-theme-showcase__appearance-buttons" }, ["light", "dark"].map((mode) => {
11169
11240
  const label = `${mode.charAt(0).toUpperCase()}${mode.slice(1)}`;
11170
11241
  const baseClass = "canopy-theme-showcase__appearance-button";
11171
11242
  const isDefault = mode === DEFAULTS.appearance;
11172
11243
  const className = isDefault ? `${baseClass} is-active` : baseClass;
11173
- return /* @__PURE__ */ React51.createElement(
11244
+ return /* @__PURE__ */ React52.createElement(
11174
11245
  "button",
11175
11246
  {
11176
11247
  key: mode,
@@ -11182,7 +11253,7 @@ function ThemeShowcase() {
11182
11253
  );
11183
11254
  }))
11184
11255
  ),
11185
- /* @__PURE__ */ React51.createElement(
11256
+ /* @__PURE__ */ React52.createElement(
11186
11257
  "button",
11187
11258
  {
11188
11259
  type: "button",
@@ -11191,13 +11262,13 @@ function ThemeShowcase() {
11191
11262
  },
11192
11263
  "Reset"
11193
11264
  )
11194
- ), /* @__PURE__ */ React51.createElement(
11265
+ ), /* @__PURE__ */ React52.createElement(
11195
11266
  Section,
11196
11267
  {
11197
11268
  title: "Color scales",
11198
11269
  description: "Accent and gray ramps from the active theme."
11199
11270
  },
11200
- /* @__PURE__ */ React51.createElement("div", { style: { display: "flex", flexDirection: "column", gap: "1.5rem" } }, COLOR_SCALES.map((scale) => /* @__PURE__ */ React51.createElement(
11271
+ /* @__PURE__ */ React52.createElement("div", { style: { display: "flex", flexDirection: "column", gap: "1.5rem" } }, COLOR_SCALES.map((scale) => /* @__PURE__ */ React52.createElement(
11201
11272
  ColorScaleRow,
11202
11273
  {
11203
11274
  key: scale.label,
@@ -11205,13 +11276,13 @@ function ThemeShowcase() {
11205
11276
  prefix: scale.prefix
11206
11277
  }
11207
11278
  )))
11208
- ), /* @__PURE__ */ React51.createElement(
11279
+ ), /* @__PURE__ */ React52.createElement(
11209
11280
  Section,
11210
11281
  {
11211
11282
  title: "Accent color palette options",
11212
11283
  description: "Click a swatch to temporarily override the accent palette."
11213
11284
  },
11214
- /* @__PURE__ */ React51.createElement(
11285
+ /* @__PURE__ */ React52.createElement(
11215
11286
  ColorsLabeled,
11216
11287
  {
11217
11288
  colors: accentColors,
@@ -11219,13 +11290,13 @@ function ThemeShowcase() {
11219
11290
  getRadixSwatch
11220
11291
  }
11221
11292
  )
11222
- ), /* @__PURE__ */ React51.createElement(
11293
+ ), /* @__PURE__ */ React52.createElement(
11223
11294
  Section,
11224
11295
  {
11225
11296
  title: "Gray color palette options",
11226
11297
  description: "Click a swatch to preview the neutral ramp for surfaces and text."
11227
11298
  },
11228
- /* @__PURE__ */ React51.createElement(
11299
+ /* @__PURE__ */ React52.createElement(
11229
11300
  ColorsLabeled,
11230
11301
  {
11231
11302
  colors: grayColors,
@@ -11233,7 +11304,7 @@ function ThemeShowcase() {
11233
11304
  getRadixSwatch
11234
11305
  }
11235
11306
  )
11236
- ), /* @__PURE__ */ React51.createElement(
11307
+ ), /* @__PURE__ */ React52.createElement(
11237
11308
  "script",
11238
11309
  {
11239
11310
  type: "application/json",
@@ -11253,6 +11324,8 @@ export {
11253
11324
  CanopyModal,
11254
11325
  Card,
11255
11326
  Container,
11327
+ ContentNavigation,
11328
+ ContentNavigationScript,
11256
11329
  DocsCodeBlock,
11257
11330
  MarkdownTable as DocsMarkdownTable,
11258
11331
  Gallery,