@canopy-iiif/app 1.8.14 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/ui/dist/index.mjs CHANGED
@@ -43225,7 +43225,7 @@ function ButtonWrapper({
43225
43225
  }
43226
43226
 
43227
43227
  // ui/src/layout/CanopyHeader.jsx
43228
- import React15 from "react";
43228
+ import React18 from "react";
43229
43229
 
43230
43230
  // ui/src/search/SearchPanel.jsx
43231
43231
  import React11 from "react";
@@ -43676,6 +43676,368 @@ function NavigationTree({
43676
43676
  );
43677
43677
  }
43678
43678
 
43679
+ // ui/src/layout/pageContext.js
43680
+ import React15 from "react";
43681
+ var CONTEXT_KEY = typeof Symbol === "function" ? Symbol.for("__CANOPY_PAGE_CONTEXT__") : "__CANOPY_PAGE_CONTEXT__";
43682
+ function getSharedRoot() {
43683
+ if (typeof globalThis !== "undefined") return globalThis;
43684
+ if (typeof window !== "undefined") return window;
43685
+ if (typeof global !== "undefined") return global;
43686
+ return null;
43687
+ }
43688
+ function getSafePageContext() {
43689
+ const root2 = getSharedRoot();
43690
+ if (root2 && root2[CONTEXT_KEY]) return root2[CONTEXT_KEY];
43691
+ const ctx = React15.createContext({ navigation: null, page: null, site: null });
43692
+ if (root2) root2[CONTEXT_KEY] = ctx;
43693
+ return ctx;
43694
+ }
43695
+
43696
+ // ui/src/layout/LanguageToggle.jsx
43697
+ import React17 from "react";
43698
+
43699
+ // ui/src/layout/languageToggleShared.jsx
43700
+ import React16 from "react";
43701
+ function readBasePath2() {
43702
+ const normalize = (value) => {
43703
+ if (!value) return "";
43704
+ const raw = String(value).trim();
43705
+ if (!raw) return "";
43706
+ const prefixed = raw.startsWith("/") ? raw : `/${raw}`;
43707
+ const cleaned = prefixed.replace(/\/+$/, "");
43708
+ return cleaned === "/" ? "" : cleaned;
43709
+ };
43710
+ try {
43711
+ if (typeof window !== "undefined" && window.CANOPY_BASE_PATH != null) {
43712
+ const candidate = normalize(window.CANOPY_BASE_PATH);
43713
+ if (candidate || candidate === "") return candidate;
43714
+ }
43715
+ } catch (_) {
43716
+ }
43717
+ try {
43718
+ if (typeof globalThis !== "undefined" && globalThis.CANOPY_BASE_PATH != null) {
43719
+ const candidate = normalize(globalThis.CANOPY_BASE_PATH);
43720
+ if (candidate || candidate === "") return candidate;
43721
+ }
43722
+ } catch (_) {
43723
+ }
43724
+ try {
43725
+ if (typeof process !== "undefined" && process.env && process.env.CANOPY_BASE_PATH) {
43726
+ const candidate = normalize(process.env.CANOPY_BASE_PATH);
43727
+ if (candidate || candidate === "") return candidate;
43728
+ }
43729
+ } catch (_) {
43730
+ }
43731
+ return "";
43732
+ }
43733
+ function withBasePath(href) {
43734
+ try {
43735
+ const raw = typeof href === "string" ? href.trim() : "";
43736
+ if (!raw) return raw;
43737
+ if (/^(?:[a-z][a-z0-9+.-]*:|\/\/|#)/i.test(raw)) return raw;
43738
+ if (!raw.startsWith("/")) return raw;
43739
+ const base = readBasePath2();
43740
+ if (!base || base === "/") return raw;
43741
+ if (raw === base || raw.startsWith(`${base}/`)) return raw;
43742
+ return `${base}${raw}`;
43743
+ } catch (_) {
43744
+ return href;
43745
+ }
43746
+ }
43747
+ function normalizeLocales(locales) {
43748
+ if (!Array.isArray(locales)) return [];
43749
+ const normalized = locales.map((entry, index) => {
43750
+ if (!entry || typeof entry !== "object") return null;
43751
+ const lang = typeof entry.lang === "string" ? entry.lang.trim() : "";
43752
+ if (!lang) return null;
43753
+ const label = typeof entry.label === "string" && entry.label.trim() ? entry.label.trim() : lang.toUpperCase();
43754
+ return { lang, label, default: entry.default === true, index };
43755
+ }).filter(Boolean);
43756
+ if (!normalized.length) return [];
43757
+ const explicitDefault = normalized.find((item) => item.default);
43758
+ if (explicitDefault) {
43759
+ normalized.forEach((item) => {
43760
+ item.default = item.index === explicitDefault.index;
43761
+ });
43762
+ } else {
43763
+ normalized[0].default = true;
43764
+ }
43765
+ return normalized.map(({ index, ...rest }) => rest);
43766
+ }
43767
+ function splitHref(href = "/") {
43768
+ try {
43769
+ if (/^[a-z][a-z0-9+.-]*:/i.test(href)) {
43770
+ const url = new URL(href);
43771
+ return {
43772
+ pathname: url.pathname || "/",
43773
+ suffix: `${url.search || ""}${url.hash || ""}`
43774
+ };
43775
+ }
43776
+ } catch (_) {
43777
+ }
43778
+ const raw = typeof href === "string" ? href : String(href || "/");
43779
+ const match2 = raw.match(/^[^?#]+/);
43780
+ const pathname = match2 ? match2[0] : "/";
43781
+ const suffix = raw.slice(pathname.length);
43782
+ return {
43783
+ pathname: pathname || "/",
43784
+ suffix
43785
+ };
43786
+ }
43787
+ function normalizePathname(pathname = "/") {
43788
+ if (!pathname) return "/";
43789
+ const trimmed = pathname.trim();
43790
+ if (!trimmed) return "/";
43791
+ if (!trimmed.startsWith("/")) return `/${trimmed}`;
43792
+ return trimmed === "/" ? "/" : `/${trimmed.replace(/^\/+/, "")}`;
43793
+ }
43794
+ function stripLocaleFromPath(pathname, locales, defaultLocale) {
43795
+ const normalizedPath = normalizePathname(pathname);
43796
+ const segments = normalizedPath.replace(/^\/+/, "").split("/");
43797
+ const first = segments[0] || "";
43798
+ const match2 = locales.find((loc) => loc.lang === first);
43799
+ if (match2 && match2.lang !== defaultLocale.lang) {
43800
+ segments.shift();
43801
+ const remainder = segments.join("/");
43802
+ return {
43803
+ locale: match2,
43804
+ pathname: remainder ? `/${remainder}` : "/"
43805
+ };
43806
+ }
43807
+ return { locale: defaultLocale, pathname: normalizedPath };
43808
+ }
43809
+ function buildLocaleHref(locale, basePath, suffix, defaultLocale) {
43810
+ const normalizedBase = normalizePathname(basePath);
43811
+ const needsPrefix = locale.lang !== defaultLocale.lang;
43812
+ const prefixed = needsPrefix ? `/${locale.lang}${normalizedBase === "/" ? "" : normalizedBase}` : normalizedBase;
43813
+ const href = withBasePath(prefixed || "/");
43814
+ return `${href}${suffix || ""}`;
43815
+ }
43816
+ function buildLanguageToggleConfig(toggle, page) {
43817
+ if (!toggle || !Array.isArray(toggle.locales)) return null;
43818
+ const locales = normalizeLocales(toggle.locales);
43819
+ if (locales.length <= 1) return null;
43820
+ const defaultLocale = locales.find((loc) => loc.default) || locales[0];
43821
+ const pageHref = page && page.href ? page.href : "/";
43822
+ const { pathname } = splitHref(pageHref);
43823
+ const { locale: activeLocale } = stripLocaleFromPath(
43824
+ pathname,
43825
+ locales,
43826
+ defaultLocale
43827
+ );
43828
+ const homePathname = "/";
43829
+ const homeSuffix = "";
43830
+ const messageMap = toggle && toggle.messages ? toggle.messages : {};
43831
+ const defaultCopy = messageMap.__default || {};
43832
+ const localeCopy = messageMap[activeLocale.lang] || null;
43833
+ const fallbackLabel = defaultCopy.label || "Language";
43834
+ const label = localeCopy && localeCopy.label || fallbackLabel;
43835
+ const links = locales.map((locale) => ({
43836
+ lang: locale.lang,
43837
+ label: locale.label || locale.lang.toUpperCase(),
43838
+ href: buildLocaleHref(locale, homePathname, homeSuffix, defaultLocale),
43839
+ isActive: locale.lang === activeLocale.lang
43840
+ }));
43841
+ return { label, links };
43842
+ }
43843
+ function LanguageToggleControl({
43844
+ config,
43845
+ variant = "inline",
43846
+ className = "",
43847
+ showLabel = false,
43848
+ control = "select"
43849
+ }) {
43850
+ if (!config) return null;
43851
+ const classes = [
43852
+ "canopy-language-toggle",
43853
+ variant ? `canopy-language-toggle--${variant}` : null,
43854
+ control ? `canopy-language-toggle--${control}` : null,
43855
+ className
43856
+ ].filter(Boolean).join(" ").trim();
43857
+ const ariaLabel = config.label || "Language";
43858
+ const resolvedControl = control === "list" ? "list" : "select";
43859
+ const selectId = typeof React16.useId === "function" && resolvedControl === "select" ? React16.useId() : void 0;
43860
+ const links = Array.isArray(config.links) ? config.links : [];
43861
+ if (!links.length) return null;
43862
+ const activeLink = links.find((link) => link.isActive);
43863
+ const fallbackHref = links[0].href;
43864
+ const selectedHref = activeLink ? activeLink.href : fallbackHref;
43865
+ const navigate = React16.useCallback((href) => {
43866
+ if (!href) return;
43867
+ try {
43868
+ if (typeof window !== "undefined" && window.location) {
43869
+ if (typeof window.location.assign === "function") {
43870
+ window.location.assign(href);
43871
+ } else {
43872
+ window.location.href = href;
43873
+ }
43874
+ return;
43875
+ }
43876
+ } catch (_) {
43877
+ }
43878
+ try {
43879
+ if (typeof document !== "undefined" && document.location) {
43880
+ document.location.href = href;
43881
+ }
43882
+ } catch (_) {
43883
+ }
43884
+ }, []);
43885
+ const handleSelectChange = React16.useCallback(
43886
+ (event) => {
43887
+ if (!event || !event.target) return;
43888
+ const nextHref = event.target.value;
43889
+ if (!nextHref || nextHref === selectedHref) return;
43890
+ navigate(nextHref);
43891
+ },
43892
+ [navigate, selectedHref]
43893
+ );
43894
+ const labelElement = showLabel && config.label ? resolvedControl === "select" ? /* @__PURE__ */ React16.createElement(
43895
+ "label",
43896
+ {
43897
+ className: "canopy-language-toggle__label",
43898
+ htmlFor: selectId
43899
+ },
43900
+ config.label
43901
+ ) : /* @__PURE__ */ React16.createElement("span", { className: "canopy-language-toggle__label" }, config.label) : null;
43902
+ return /* @__PURE__ */ React16.createElement("div", { className: classes || void 0 }, labelElement, resolvedControl === "select" ? /* @__PURE__ */ React16.createElement("div", { className: "canopy-language-toggle__select" }, /* @__PURE__ */ React16.createElement(
43903
+ "select",
43904
+ {
43905
+ id: selectId,
43906
+ className: "canopy-language-toggle__select-input",
43907
+ value: selectedHref,
43908
+ onChange: handleSelectChange,
43909
+ "aria-label": ariaLabel,
43910
+ "data-canopy-language-select": "true"
43911
+ },
43912
+ links.map((link) => /* @__PURE__ */ React16.createElement(
43913
+ "option",
43914
+ {
43915
+ key: link.lang,
43916
+ value: link.href,
43917
+ "data-lang": link.lang,
43918
+ "data-canopy-language-option": "true"
43919
+ },
43920
+ link.label
43921
+ ))
43922
+ )) : /* @__PURE__ */ React16.createElement("nav", { className: "canopy-language-toggle__nav", "aria-label": ariaLabel }, /* @__PURE__ */ React16.createElement("ul", { className: "canopy-language-toggle__list", role: "list" }, links.map((link) => /* @__PURE__ */ React16.createElement("li", { key: link.lang }, /* @__PURE__ */ React16.createElement(
43923
+ "button",
43924
+ {
43925
+ type: "button",
43926
+ className: "canopy-language-toggle__button",
43927
+ "data-active": link.isActive ? "true" : void 0,
43928
+ "aria-pressed": link.isActive ? "true" : "false",
43929
+ "data-canopy-language-button": "true",
43930
+ "data-href": link.href,
43931
+ onClick: () => navigate(link.href)
43932
+ },
43933
+ link.label
43934
+ ))))), /* @__PURE__ */ React16.createElement(LanguageToggleRuntime, null));
43935
+ }
43936
+ function LanguageToggleRuntime() {
43937
+ const code = `
43938
+ (function () {
43939
+ if (typeof window === 'undefined' || typeof document === 'undefined') return;
43940
+ if (window.__CANOPY_LANGUAGE_TOGGLE_INIT__) return;
43941
+ window.__CANOPY_LANGUAGE_TOGGLE_INIT__ = true;
43942
+
43943
+ function navigate(href) {
43944
+ if (!href) return;
43945
+ try {
43946
+ if (window.location && typeof window.location.assign === 'function') {
43947
+ window.location.assign(href);
43948
+ } else if (window.location) {
43949
+ window.location.href = href;
43950
+ }
43951
+ } catch (_) {}
43952
+ }
43953
+
43954
+ function bindSelect(select) {
43955
+ if (!select || select.dataset.canopyLanguageBound === 'true') return;
43956
+ select.dataset.canopyLanguageBound = 'true';
43957
+ select.addEventListener('change', function (event) {
43958
+ var target = event && event.target ? event.target : select;
43959
+ var href = target && target.value;
43960
+ if (!href || href === '#') return;
43961
+ navigate(href);
43962
+ });
43963
+ }
43964
+
43965
+ function bindButtons(root) {
43966
+ var buttons = root.querySelectorAll('[data-canopy-language-button]');
43967
+ Array.prototype.forEach.call(buttons, function (btn) {
43968
+ if (!btn || btn.dataset.canopyLanguageBound === 'true') return;
43969
+ btn.dataset.canopyLanguageBound = 'true';
43970
+ btn.addEventListener('click', function (event) {
43971
+ event.preventDefault();
43972
+ var href = btn.getAttribute('data-href');
43973
+ navigate(href);
43974
+ });
43975
+ });
43976
+ }
43977
+
43978
+ function scan(root) {
43979
+ if (!root) root = document;
43980
+ var selects = root.querySelectorAll('[data-canopy-language-select]');
43981
+ Array.prototype.forEach.call(selects, bindSelect);
43982
+ bindButtons(root);
43983
+ }
43984
+
43985
+ if (document.readyState === 'loading') {
43986
+ document.addEventListener('DOMContentLoaded', function () {
43987
+ scan(document);
43988
+ });
43989
+ } else {
43990
+ scan(document);
43991
+ }
43992
+ })();
43993
+ `;
43994
+ return /* @__PURE__ */ React16.createElement("script", { dangerouslySetInnerHTML: { __html: code } });
43995
+ }
43996
+
43997
+ // ui/src/layout/LanguageToggle.jsx
43998
+ function LanguageToggle({
43999
+ languageToggle,
44000
+ page,
44001
+ variant = "inline",
44002
+ className = "",
44003
+ showLabel = false,
44004
+ control,
44005
+ label,
44006
+ ariaLabel
44007
+ }) {
44008
+ const PageContext = getSafePageContext();
44009
+ const context = React17.useContext(PageContext);
44010
+ const siteLanguageToggle = context && context.site && context.site.languageToggle || null;
44011
+ const pageData = page || (context && context.page ? context.page : null);
44012
+ const resolvedToggle = languageToggle === false ? null : languageToggle === true || typeof languageToggle === "undefined" ? siteLanguageToggle : languageToggle;
44013
+ const normalizeControl = (value) => value === "list" ? "list" : value === "select" ? "select" : null;
44014
+ const toggleControl = normalizeControl(
44015
+ resolvedToggle && typeof resolvedToggle.control === "string" ? resolvedToggle.control : null
44016
+ );
44017
+ const resolvedControl = normalizeControl(typeof control === "string" ? control : null) || toggleControl || "select";
44018
+ const config = React17.useMemo(() => {
44019
+ if (!resolvedToggle) return null;
44020
+ const base = buildLanguageToggleConfig(resolvedToggle, pageData);
44021
+ if (!base) return null;
44022
+ return {
44023
+ ...base,
44024
+ label: typeof label === "string" ? label : base.label,
44025
+ ariaLabel: typeof ariaLabel === "string" ? ariaLabel : base.ariaLabel
44026
+ };
44027
+ }, [resolvedToggle, pageData, label, ariaLabel]);
44028
+ if (!config) return null;
44029
+ return /* @__PURE__ */ React17.createElement(
44030
+ LanguageToggleControl,
44031
+ {
44032
+ config,
44033
+ variant,
44034
+ className,
44035
+ showLabel,
44036
+ control: resolvedControl
44037
+ }
44038
+ );
44039
+ }
44040
+
43679
44041
  // ui/src/layout/CanopyHeader.jsx
43680
44042
  function HeaderScript() {
43681
44043
  const code = `
@@ -43966,7 +44328,7 @@ function HeaderScript() {
43966
44328
  });
43967
44329
  })();
43968
44330
  `;
43969
- return /* @__PURE__ */ React15.createElement(
44331
+ return /* @__PURE__ */ React18.createElement(
43970
44332
  "script",
43971
44333
  {
43972
44334
  dangerouslySetInnerHTML: {
@@ -43975,20 +44337,6 @@ function HeaderScript() {
43975
44337
  }
43976
44338
  );
43977
44339
  }
43978
- var CONTEXT_KEY = typeof Symbol === "function" ? Symbol.for("__CANOPY_PAGE_CONTEXT__") : "__CANOPY_PAGE_CONTEXT__";
43979
- function getSharedRoot() {
43980
- if (typeof globalThis !== "undefined") return globalThis;
43981
- if (typeof window !== "undefined") return window;
43982
- if (typeof global !== "undefined") return global;
43983
- return null;
43984
- }
43985
- function getSafePageContext() {
43986
- const root2 = getSharedRoot();
43987
- if (root2 && root2[CONTEXT_KEY]) return root2[CONTEXT_KEY];
43988
- const ctx = React15.createContext({ navigation: null, page: null, site: null });
43989
- if (root2) root2[CONTEXT_KEY] = ctx;
43990
- return ctx;
43991
- }
43992
44340
  function ensureArray(navLinks) {
43993
44341
  if (!Array.isArray(navLinks)) return [];
43994
44342
  return navLinks.filter(
@@ -44053,15 +44401,26 @@ function CanopyHeader(props = {}) {
44053
44401
  searchPlaceholder = "Search\u2026",
44054
44402
  brandHref = "/",
44055
44403
  title: titleProp,
44056
- logo: SiteLogo
44404
+ logo: SiteLogo,
44405
+ languageToggle: languageToggleProp
44057
44406
  } = props;
44058
44407
  const PageContext = getSafePageContext();
44059
- const context = React15.useContext(PageContext);
44408
+ const context = React18.useContext(PageContext);
44060
44409
  const contextPrimaryNav = context && Array.isArray(context.primaryNavigation) ? context.primaryNavigation : [];
44061
44410
  const navLinks = navLinksProp && navLinksProp.length ? ensureArray(navLinksProp) : ensureArray(contextPrimaryNav);
44062
44411
  const contextNavigation = context && context.navigation ? context.navigation : null;
44063
44412
  const contextSite = context && context.site ? context.site : null;
44413
+ const pageData = context && context.page ? context.page : null;
44064
44414
  const contextSiteTitle = contextSite && typeof contextSite.title === "string" ? contextSite.title.trim() : "";
44415
+ const siteLanguageToggle = contextSite && contextSite.languageToggle ? contextSite.languageToggle : null;
44416
+ const siteRoutes = contextSite && contextSite.routes ? contextSite.routes : null;
44417
+ const siteDefaultRoutes = contextSite && contextSite.routesDefault ? contextSite.routesDefault : null;
44418
+ const searchRouteValue = siteRoutes && typeof siteRoutes.search === "string" ? siteRoutes.search : "";
44419
+ const defaultSearchRoute = siteDefaultRoutes && typeof siteDefaultRoutes.search === "string" ? siteDefaultRoutes.search : "search";
44420
+ const trimmedSearchRoute = searchRouteValue ? searchRouteValue.replace(/^\/+|\/+$/g, "") : "";
44421
+ const usesDirectorySearchRoute = trimmedSearchRoute && trimmedSearchRoute !== (defaultSearchRoute || "search");
44422
+ const normalizedSearchRoute = usesDirectorySearchRoute ? `/${trimmedSearchRoute}/` : `/${(trimmedSearchRoute || defaultSearchRoute || "search").replace(/^\/+/, "")}`;
44423
+ const resolvedLanguageToggle = languageToggleProp === false ? null : languageToggleProp === true || typeof languageToggleProp === "undefined" ? siteLanguageToggle : languageToggleProp;
44065
44424
  const defaultHeaderTitle = contextSiteTitle || "Site title";
44066
44425
  const normalizedTitleProp = typeof titleProp === "string" ? titleProp.trim() : "";
44067
44426
  const resolvedTitle = normalizedTitleProp || defaultHeaderTitle;
@@ -44083,14 +44442,14 @@ function CanopyHeader(props = {}) {
44083
44442
  return !!(rootNode && Array.isArray(rootNode.children) && rootNode.children.length);
44084
44443
  };
44085
44444
  const hasIntegratedSectionNav = navLinks.some(shouldAttachSectionNav);
44086
- return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(
44445
+ return /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(
44087
44446
  "header",
44088
44447
  {
44089
44448
  className: "canopy-header",
44090
44449
  "data-mobile-nav": "closed",
44091
44450
  "data-mobile-search": "closed"
44092
44451
  },
44093
- /* @__PURE__ */ React15.createElement("div", { className: "canopy-header__brand" }, /* @__PURE__ */ React15.createElement(
44452
+ /* @__PURE__ */ React18.createElement("div", { className: "canopy-header__brand" }, /* @__PURE__ */ React18.createElement(
44094
44453
  CanopyBrand,
44095
44454
  {
44096
44455
  label: resolvedTitle,
@@ -44099,21 +44458,22 @@ function CanopyHeader(props = {}) {
44099
44458
  Logo: SiteLogo
44100
44459
  }
44101
44460
  )),
44102
- /* @__PURE__ */ React15.createElement("div", { className: "canopy-header__desktop-search" }, /* @__PURE__ */ React15.createElement(
44461
+ /* @__PURE__ */ React18.createElement("div", { className: "canopy-header__desktop-search" }, /* @__PURE__ */ React18.createElement(
44103
44462
  SearchPanel,
44104
44463
  {
44105
44464
  label: searchLabel,
44106
44465
  hotkey: searchHotkey,
44107
- placeholder: searchPlaceholder
44466
+ placeholder: searchPlaceholder,
44467
+ searchPath: normalizedSearchRoute
44108
44468
  }
44109
44469
  )),
44110
- /* @__PURE__ */ React15.createElement(
44470
+ /* @__PURE__ */ React18.createElement(
44111
44471
  "nav",
44112
44472
  {
44113
44473
  className: "canopy-nav-links canopy-header__desktop-nav",
44114
44474
  "aria-label": "Primary navigation"
44115
44475
  },
44116
- navLinks.map((link) => /* @__PURE__ */ React15.createElement(
44476
+ navLinks.map((link) => /* @__PURE__ */ React18.createElement(
44117
44477
  "a",
44118
44478
  {
44119
44479
  key: link.href,
@@ -44123,7 +44483,15 @@ function CanopyHeader(props = {}) {
44123
44483
  link.label || link.href
44124
44484
  ))
44125
44485
  ),
44126
- /* @__PURE__ */ React15.createElement("div", { className: "canopy-header__actions" }, /* @__PURE__ */ React15.createElement(
44486
+ /* @__PURE__ */ React18.createElement("div", { className: "canopy-header__actions" }, resolvedLanguageToggle ? /* @__PURE__ */ React18.createElement(
44487
+ LanguageToggle,
44488
+ {
44489
+ languageToggle: resolvedLanguageToggle,
44490
+ page: pageData,
44491
+ variant: "desktop",
44492
+ className: "canopy-header__language-toggle canopy-header__language-toggle--desktop"
44493
+ }
44494
+ ) : null, /* @__PURE__ */ React18.createElement(
44127
44495
  "button",
44128
44496
  {
44129
44497
  type: "button",
@@ -44133,7 +44501,7 @@ function CanopyHeader(props = {}) {
44133
44501
  "aria-expanded": "false",
44134
44502
  "data-canopy-header-toggle": "search"
44135
44503
  },
44136
- /* @__PURE__ */ React15.createElement(
44504
+ /* @__PURE__ */ React18.createElement(
44137
44505
  "svg",
44138
44506
  {
44139
44507
  xmlns: "http://www.w3.org/2000/svg",
@@ -44143,7 +44511,7 @@ function CanopyHeader(props = {}) {
44143
44511
  strokeWidth: "1.5",
44144
44512
  className: "canopy-header__search-icon"
44145
44513
  },
44146
- /* @__PURE__ */ React15.createElement(
44514
+ /* @__PURE__ */ React18.createElement(
44147
44515
  "path",
44148
44516
  {
44149
44517
  strokeLinecap: "round",
@@ -44152,7 +44520,7 @@ function CanopyHeader(props = {}) {
44152
44520
  }
44153
44521
  )
44154
44522
  )
44155
- ), /* @__PURE__ */ React15.createElement(
44523
+ ), /* @__PURE__ */ React18.createElement(
44156
44524
  "button",
44157
44525
  {
44158
44526
  type: "button",
@@ -44162,7 +44530,7 @@ function CanopyHeader(props = {}) {
44162
44530
  "aria-expanded": "false",
44163
44531
  "data-canopy-header-toggle": "nav"
44164
44532
  },
44165
- /* @__PURE__ */ React15.createElement(
44533
+ /* @__PURE__ */ React18.createElement(
44166
44534
  "svg",
44167
44535
  {
44168
44536
  xmlns: "http://www.w3.org/2000/svg",
@@ -44172,7 +44540,7 @@ function CanopyHeader(props = {}) {
44172
44540
  stroke: "currentColor",
44173
44541
  className: "canopy-header__menu-icon"
44174
44542
  },
44175
- /* @__PURE__ */ React15.createElement(
44543
+ /* @__PURE__ */ React18.createElement(
44176
44544
  "path",
44177
44545
  {
44178
44546
  strokeLinecap: "round",
@@ -44182,7 +44550,7 @@ function CanopyHeader(props = {}) {
44182
44550
  )
44183
44551
  )
44184
44552
  ))
44185
- ), /* @__PURE__ */ React15.createElement(
44553
+ ), /* @__PURE__ */ React18.createElement(
44186
44554
  CanopyModal,
44187
44555
  {
44188
44556
  id: "canopy-modal-nav",
@@ -44194,13 +44562,22 @@ function CanopyHeader(props = {}) {
44194
44562
  closeLabel: "Close navigation",
44195
44563
  closeDataAttr: "nav"
44196
44564
  },
44197
- /* @__PURE__ */ React15.createElement(
44565
+ resolvedLanguageToggle ? /* @__PURE__ */ React18.createElement(
44566
+ LanguageToggle,
44567
+ {
44568
+ languageToggle: resolvedLanguageToggle,
44569
+ page: pageData,
44570
+ variant: "mobile",
44571
+ className: "canopy-header__language-toggle canopy-header__language-toggle--mobile"
44572
+ }
44573
+ ) : null,
44574
+ /* @__PURE__ */ React18.createElement(
44198
44575
  "nav",
44199
44576
  {
44200
44577
  className: "canopy-nav-links canopy-modal__nav",
44201
44578
  "aria-label": "Primary navigation"
44202
44579
  },
44203
- /* @__PURE__ */ React15.createElement("ul", { className: "canopy-modal__nav-list", role: "list" }, navLinks.map((link, index) => {
44580
+ /* @__PURE__ */ React18.createElement("ul", { className: "canopy-modal__nav-list", role: "list" }, navLinks.map((link, index) => {
44204
44581
  const navData = getLinkNavigationData(
44205
44582
  link,
44206
44583
  navigationRoots,
@@ -44211,7 +44588,7 @@ function CanopyHeader(props = {}) {
44211
44588
  const nestedId = hasChildren ? `canopy-modal-section-${index}` : null;
44212
44589
  const toggleLabel = link.label ? `Toggle ${link.label} menu` : "Toggle section menu";
44213
44590
  const defaultExpanded = hasChildren && !!navRoot.isExpanded;
44214
- return /* @__PURE__ */ React15.createElement(
44591
+ return /* @__PURE__ */ React18.createElement(
44215
44592
  "li",
44216
44593
  {
44217
44594
  className: "canopy-modal__nav-item",
@@ -44220,7 +44597,7 @@ function CanopyHeader(props = {}) {
44220
44597
  "data-expanded": defaultExpanded ? "true" : "false",
44221
44598
  "data-default-expanded": defaultExpanded ? "true" : void 0
44222
44599
  },
44223
- /* @__PURE__ */ React15.createElement("div", { className: "canopy-modal__nav-row" }, /* @__PURE__ */ React15.createElement("a", { href: link.href }, link.label || link.href), hasChildren ? /* @__PURE__ */ React15.createElement(
44600
+ /* @__PURE__ */ React18.createElement("div", { className: "canopy-modal__nav-row" }, /* @__PURE__ */ React18.createElement("a", { href: link.href }, link.label || link.href), hasChildren ? /* @__PURE__ */ React18.createElement(
44224
44601
  "button",
44225
44602
  {
44226
44603
  type: "button",
@@ -44230,7 +44607,7 @@ function CanopyHeader(props = {}) {
44230
44607
  "aria-label": toggleLabel,
44231
44608
  "data-canopy-nav-item-toggle": nestedId || void 0
44232
44609
  },
44233
- /* @__PURE__ */ React15.createElement(
44610
+ /* @__PURE__ */ React18.createElement(
44234
44611
  "svg",
44235
44612
  {
44236
44613
  xmlns: "http://www.w3.org/2000/svg",
@@ -44240,7 +44617,7 @@ function CanopyHeader(props = {}) {
44240
44617
  strokeWidth: "1.5",
44241
44618
  className: "canopy-modal__nav-toggle-icon"
44242
44619
  },
44243
- /* @__PURE__ */ React15.createElement(
44620
+ /* @__PURE__ */ React18.createElement(
44244
44621
  "path",
44245
44622
  {
44246
44623
  strokeLinecap: "round",
@@ -44249,9 +44626,9 @@ function CanopyHeader(props = {}) {
44249
44626
  }
44250
44627
  )
44251
44628
  ),
44252
- /* @__PURE__ */ React15.createElement("span", { className: "sr-only" }, toggleLabel)
44629
+ /* @__PURE__ */ React18.createElement("span", { className: "sr-only" }, toggleLabel)
44253
44630
  ) : null),
44254
- hasChildren ? /* @__PURE__ */ React15.createElement(
44631
+ hasChildren ? /* @__PURE__ */ React18.createElement(
44255
44632
  NavigationTree,
44256
44633
  {
44257
44634
  root: navRoot,
@@ -44267,7 +44644,7 @@ function CanopyHeader(props = {}) {
44267
44644
  );
44268
44645
  }))
44269
44646
  ),
44270
- hasSectionNav && !hasIntegratedSectionNav ? /* @__PURE__ */ React15.createElement(
44647
+ hasSectionNav && !hasIntegratedSectionNav ? /* @__PURE__ */ React18.createElement(
44271
44648
  NavigationTree,
44272
44649
  {
44273
44650
  root: sectionNavigation.root,
@@ -44277,7 +44654,7 @@ function CanopyHeader(props = {}) {
44277
44654
  parentKey: "fallback-nav"
44278
44655
  }
44279
44656
  ) : null
44280
- ), /* @__PURE__ */ React15.createElement(
44657
+ ), /* @__PURE__ */ React18.createElement(
44281
44658
  CanopyModal,
44282
44659
  {
44283
44660
  id: "canopy-modal-search",
@@ -44290,26 +44667,27 @@ function CanopyHeader(props = {}) {
44290
44667
  closeDataAttr: "search",
44291
44668
  bodyClassName: "canopy-modal__body--search"
44292
44669
  },
44293
- /* @__PURE__ */ React15.createElement(
44670
+ /* @__PURE__ */ React18.createElement(
44294
44671
  SearchPanel,
44295
44672
  {
44296
44673
  label: searchLabel,
44297
44674
  hotkey: searchHotkey,
44298
- placeholder: searchPlaceholder
44675
+ placeholder: searchPlaceholder,
44676
+ searchPath: normalizedSearchRoute
44299
44677
  }
44300
44678
  )
44301
- ), /* @__PURE__ */ React15.createElement(HeaderScript, null));
44679
+ ), /* @__PURE__ */ React18.createElement(HeaderScript, null));
44302
44680
  }
44303
44681
 
44304
44682
  // ui/src/layout/CanopyFooter.jsx
44305
- import React16 from "react";
44683
+ import React19 from "react";
44306
44684
  function CanopyFooter({ className = "", children }) {
44307
44685
  const footerClassName = ["canopy-footer", className].filter(Boolean).join(" ");
44308
- return /* @__PURE__ */ React16.createElement("footer", { className: footerClassName }, /* @__PURE__ */ React16.createElement("div", { className: "canopy-footer__inner" }, children));
44686
+ return /* @__PURE__ */ React19.createElement("footer", { className: footerClassName }, /* @__PURE__ */ React19.createElement("div", { className: "canopy-footer__inner" }, children));
44309
44687
  }
44310
44688
 
44311
44689
  // ui/src/layout/TeaserCard.jsx
44312
- import React17 from "react";
44690
+ import React20 from "react";
44313
44691
  function TeaserCard({
44314
44692
  href = "",
44315
44693
  title = "",
@@ -44330,7 +44708,7 @@ function TeaserCard({
44330
44708
  ].filter(Boolean).join(" ");
44331
44709
  const showThumb = type === "work" && thumbnail;
44332
44710
  const metaLine = (Array.isArray(metadata) && metadata.length ? metadata.filter(Boolean) : summary ? [summary] : []).filter(Boolean).slice(0, 2).join(" \u2022 ");
44333
- return /* @__PURE__ */ React17.createElement(
44711
+ return /* @__PURE__ */ React20.createElement(
44334
44712
  Tag,
44335
44713
  {
44336
44714
  className: classes,
@@ -44338,7 +44716,7 @@ function TeaserCard({
44338
44716
  "data-canopy-item": href ? "" : void 0,
44339
44717
  ...rest
44340
44718
  },
44341
- showThumb ? /* @__PURE__ */ React17.createElement("div", { className: "canopy-search-teaser__thumb" }, /* @__PURE__ */ React17.createElement(
44719
+ showThumb ? /* @__PURE__ */ React20.createElement("div", { className: "canopy-search-teaser__thumb" }, /* @__PURE__ */ React20.createElement(
44342
44720
  "img",
44343
44721
  {
44344
44722
  src: thumbnail,
@@ -44348,12 +44726,12 @@ function TeaserCard({
44348
44726
  className: "canopy-search-teaser__thumb-img"
44349
44727
  }
44350
44728
  )) : null,
44351
- /* @__PURE__ */ React17.createElement("div", { className: "canopy-search-teaser__text" }, /* @__PURE__ */ React17.createElement("span", { className: "canopy-search-teaser__title" }, title || href || "Untitled"), metaLine ? /* @__PURE__ */ React17.createElement("span", { className: "canopy-search-teaser__meta" }, metaLine) : null)
44729
+ /* @__PURE__ */ React20.createElement("div", { className: "canopy-search-teaser__text" }, /* @__PURE__ */ React20.createElement("span", { className: "canopy-search-teaser__title" }, title || href || "Untitled"), metaLine ? /* @__PURE__ */ React20.createElement("span", { className: "canopy-search-teaser__meta" }, metaLine) : null)
44352
44730
  );
44353
44731
  }
44354
44732
 
44355
44733
  // ui/src/layout/GoogleAnalytics.jsx
44356
- import React18 from "react";
44734
+ import React21 from "react";
44357
44735
  var GA_HOST = "https://www.googletagmanager.com/gtag/js";
44358
44736
  function GoogleAnalytics({ id }) {
44359
44737
  if (!id) return null;
@@ -44363,11 +44741,11 @@ function GoogleAnalytics({ id }) {
44363
44741
  gtag('js', new Date());
44364
44742
  gtag('config', '${id}');
44365
44743
  `;
44366
- return /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement("script", { async: true, src: `${GA_HOST}?id=${encodeURIComponent(id)}` }), /* @__PURE__ */ React18.createElement("script", { dangerouslySetInnerHTML: { __html: inlineConfig } }));
44744
+ return /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement("script", { async: true, src: `${GA_HOST}?id=${encodeURIComponent(id)}` }), /* @__PURE__ */ React21.createElement("script", { dangerouslySetInnerHTML: { __html: inlineConfig } }));
44367
44745
  }
44368
44746
 
44369
44747
  // ui/src/iiif/Viewer.jsx
44370
- import React19, { useEffect as useEffect2, useState as useState2 } from "react";
44748
+ import React22, { useEffect as useEffect2, useState as useState2 } from "react";
44371
44749
  var DEFAULT_VIEWER_OPTIONS = {
44372
44750
  showDownload: false,
44373
44751
  showIIIFBadge: false,
@@ -44423,7 +44801,7 @@ var Viewer = (props) => {
44423
44801
  } catch (_) {
44424
44802
  json = "{}";
44425
44803
  }
44426
- return /* @__PURE__ */ React19.createElement("div", { "data-canopy-viewer": "1", className: "not-prose" }, /* @__PURE__ */ React19.createElement(
44804
+ return /* @__PURE__ */ React22.createElement("div", { "data-canopy-viewer": "1", className: "not-prose" }, /* @__PURE__ */ React22.createElement(
44427
44805
  "script",
44428
44806
  {
44429
44807
  type: "application/json",
@@ -44431,11 +44809,11 @@ var Viewer = (props) => {
44431
44809
  }
44432
44810
  ));
44433
44811
  }
44434
- return /* @__PURE__ */ React19.createElement(CloverViewer, { ...props, options: mergedOptions });
44812
+ return /* @__PURE__ */ React22.createElement(CloverViewer, { ...props, options: mergedOptions });
44435
44813
  };
44436
44814
 
44437
44815
  // ui/src/iiif/Slider.jsx
44438
- import React20, { useEffect as useEffect3, useState as useState3 } from "react";
44816
+ import React23, { useEffect as useEffect3, useState as useState3 } from "react";
44439
44817
 
44440
44818
  // ui/src/iiif/sliderOptions.js
44441
44819
  var UNIT_TOKEN = "__canopySliderUnit";
@@ -44582,7 +44960,7 @@ var Slider = (props = {}) => {
44582
44960
  } catch (_) {
44583
44961
  json = "{}";
44584
44962
  }
44585
- return /* @__PURE__ */ React20.createElement("div", { className: sliderClassName, "data-canopy-slider": "1" }, /* @__PURE__ */ React20.createElement(
44963
+ return /* @__PURE__ */ React23.createElement("div", { className: sliderClassName, "data-canopy-slider": "1" }, /* @__PURE__ */ React23.createElement(
44586
44964
  "script",
44587
44965
  {
44588
44966
  type: "application/json",
@@ -44590,11 +44968,11 @@ var Slider = (props = {}) => {
44590
44968
  }
44591
44969
  ));
44592
44970
  }
44593
- return /* @__PURE__ */ React20.createElement(CloverSlider, { ...resolvedProps });
44971
+ return /* @__PURE__ */ React23.createElement(CloverSlider, { ...resolvedProps });
44594
44972
  };
44595
44973
 
44596
44974
  // ui/src/iiif/Scroll.jsx
44597
- import React21, { useEffect as useEffect4, useState as useState4 } from "react";
44975
+ import React24, { useEffect as useEffect4, useState as useState4 } from "react";
44598
44976
  var Scroll = (props) => {
44599
44977
  const [CloverScroll, setCloverScroll] = useState4(null);
44600
44978
  useEffect4(() => {
@@ -44619,7 +44997,7 @@ var Scroll = (props) => {
44619
44997
  } catch (_) {
44620
44998
  json = "{}";
44621
44999
  }
44622
- return /* @__PURE__ */ React21.createElement("div", { "data-canopy-scroll": "1", className: "not-prose" }, /* @__PURE__ */ React21.createElement(
45000
+ return /* @__PURE__ */ React24.createElement("div", { "data-canopy-scroll": "1", className: "not-prose" }, /* @__PURE__ */ React24.createElement(
44623
45001
  "script",
44624
45002
  {
44625
45003
  type: "application/json",
@@ -44627,11 +45005,11 @@ var Scroll = (props) => {
44627
45005
  }
44628
45006
  ));
44629
45007
  }
44630
- return /* @__PURE__ */ React21.createElement(CloverScroll, { ...props });
45008
+ return /* @__PURE__ */ React24.createElement(CloverScroll, { ...props });
44631
45009
  };
44632
45010
 
44633
45011
  // ui/src/iiif/Image.jsx
44634
- import React22, { useEffect as useEffect5, useState as useState5 } from "react";
45012
+ import React25, { useEffect as useEffect5, useState as useState5 } from "react";
44635
45013
  var Image = (props = {}) => {
44636
45014
  const [CloverImage, setCloverImage] = useState5(null);
44637
45015
  const baseClass = "canopy-iiif-image";
@@ -44664,7 +45042,7 @@ var Image = (props = {}) => {
44664
45042
  } catch (_) {
44665
45043
  json = "{}";
44666
45044
  }
44667
- return /* @__PURE__ */ React22.createElement("figure", { className: rootClassName }, /* @__PURE__ */ React22.createElement(
45045
+ return /* @__PURE__ */ React25.createElement("figure", { className: rootClassName }, /* @__PURE__ */ React25.createElement(
44668
45046
  "div",
44669
45047
  {
44670
45048
  className: `${baseClass}__placeholder`,
@@ -44674,20 +45052,20 @@ var Image = (props = {}) => {
44674
45052
  "--canopy-iiif-image-bg": backgroundColor
44675
45053
  }
44676
45054
  },
44677
- /* @__PURE__ */ React22.createElement(
45055
+ /* @__PURE__ */ React25.createElement(
44678
45056
  "script",
44679
45057
  {
44680
45058
  type: "application/json",
44681
45059
  dangerouslySetInnerHTML: { __html: json }
44682
45060
  }
44683
45061
  )
44684
- ), caption && /* @__PURE__ */ React22.createElement("figcaption", { className: `${baseClass}__caption` }, caption));
45062
+ ), caption && /* @__PURE__ */ React25.createElement("figcaption", { className: `${baseClass}__caption` }, caption));
44685
45063
  }
44686
- return /* @__PURE__ */ React22.createElement(CloverImage, { ...props, className: rootClassName });
45064
+ return /* @__PURE__ */ React25.createElement(CloverImage, { ...props, className: rootClassName });
44687
45065
  };
44688
45066
 
44689
45067
  // ui/src/iiif/ImageStory.jsx
44690
- import React23, { useEffect as useEffect6, useMemo as useMemo2, useRef as useRef2 } from "react";
45068
+ import React26, { useEffect as useEffect6, useMemo as useMemo2, useRef as useRef2 } from "react";
44691
45069
 
44692
45070
  // ui/src/iiif/imageStoryRuntime.js
44693
45071
  var STORIIIES_STYLE_URL = "https://unpkg.com/@cogapp/storiiies-viewer@latest/dist/storiiies-viewer.css";
@@ -44729,7 +45107,7 @@ function normalizeBasePath(value) {
44729
45107
  return cleaned === "/" ? "" : cleaned;
44730
45108
  }
44731
45109
  var cachedBasePath = null;
44732
- function readBasePath2() {
45110
+ function readBasePath3() {
44733
45111
  if (cachedBasePath !== null) return cachedBasePath;
44734
45112
  const candidates = [];
44735
45113
  try {
@@ -44760,13 +45138,13 @@ function readBasePath2() {
44760
45138
  cachedBasePath = "";
44761
45139
  return cachedBasePath;
44762
45140
  }
44763
- function withBasePath(href) {
45141
+ function withBasePath2(href) {
44764
45142
  if (typeof href !== "string") return href;
44765
45143
  const raw = href.trim();
44766
45144
  if (!raw) return href;
44767
45145
  if (/^(?:[a-z][a-z0-9+.-]*:|\/\/|#)/i.test(raw)) return raw;
44768
45146
  if (!raw.startsWith("/")) return raw;
44769
- const base = readBasePath2();
45147
+ const base = readBasePath3();
44770
45148
  if (!base || base === "/") return raw;
44771
45149
  if (raw === base || raw.startsWith(`${base}/`)) return raw;
44772
45150
  return `${base}${raw}`;
@@ -44806,13 +45184,13 @@ function resolveViewerConfig(element, props) {
44806
45184
  const viewerOptions = sanitized.viewerOptions && typeof sanitized.viewerOptions === "object" ? sanitized.viewerOptions : {};
44807
45185
  const config = { ...viewerOptions, container: element };
44808
45186
  if (sanitized.iiifContent) {
44809
- config.manifestUrl = withBasePath(sanitized.iiifContent);
45187
+ config.manifestUrl = withBasePath2(sanitized.iiifContent);
44810
45188
  }
44811
45189
  if (typeof sanitized.disablePanAndZoom === "boolean") {
44812
45190
  config.disablePanAndZoom = sanitized.disablePanAndZoom;
44813
45191
  }
44814
45192
  if (sanitized.pointOfInterestSvgUrl) {
44815
- config.pointOfInterestSvgUrl = withBasePath(sanitized.pointOfInterestSvgUrl);
45193
+ config.pointOfInterestSvgUrl = withBasePath2(sanitized.pointOfInterestSvgUrl);
44816
45194
  }
44817
45195
  return config;
44818
45196
  }
@@ -44912,7 +45290,7 @@ var ImageStory = (props = {}) => {
44912
45290
  }
44913
45291
  };
44914
45292
  }, [iiifContent, disablePanAndZoom, pointOfInterestSvgUrl, viewerOptions]);
44915
- return /* @__PURE__ */ React23.createElement(
45293
+ return /* @__PURE__ */ React26.createElement(
44916
45294
  "div",
44917
45295
  {
44918
45296
  ref: containerRef,
@@ -44925,18 +45303,18 @@ var ImageStory = (props = {}) => {
44925
45303
  },
44926
45304
  ...rest
44927
45305
  },
44928
- /* @__PURE__ */ React23.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: serializedProps } })
45306
+ /* @__PURE__ */ React26.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: serializedProps } })
44929
45307
  );
44930
45308
  };
44931
45309
 
44932
45310
  // ui/src/iiif/Properties/Id.jsx
44933
- import React24 from "react";
45311
+ import React27 from "react";
44934
45312
  function Id({ title = "IIIF Manifest", id, ...props }) {
44935
- return /* @__PURE__ */ React24.createElement("dl", null, /* @__PURE__ */ React24.createElement("dt", null, title), /* @__PURE__ */ React24.createElement("dd", null, /* @__PURE__ */ React24.createElement("a", { href: id }, id)));
45313
+ return /* @__PURE__ */ React27.createElement("dl", null, /* @__PURE__ */ React27.createElement("dt", null, title), /* @__PURE__ */ React27.createElement("dd", null, /* @__PURE__ */ React27.createElement("a", { href: id }, id)));
44936
45314
  }
44937
45315
 
44938
45316
  // ui/src/iiif/MdxRelatedItems.jsx
44939
- import React25 from "react";
45317
+ import React28 from "react";
44940
45318
  function MdxRelatedItems(props) {
44941
45319
  let json = "{}";
44942
45320
  try {
@@ -44944,7 +45322,7 @@ function MdxRelatedItems(props) {
44944
45322
  } catch (_) {
44945
45323
  json = "{}";
44946
45324
  }
44947
- return /* @__PURE__ */ React25.createElement("div", { "data-canopy-related-items": "1" }, /* @__PURE__ */ React25.createElement(
45325
+ return /* @__PURE__ */ React28.createElement("div", { "data-canopy-related-items": "1" }, /* @__PURE__ */ React28.createElement(
44948
45326
  "script",
44949
45327
  {
44950
45328
  type: "application/json",
@@ -44954,7 +45332,7 @@ function MdxRelatedItems(props) {
44954
45332
  }
44955
45333
 
44956
45334
  // ui/src/search/MdxSearchResults.jsx
44957
- import React26 from "react";
45335
+ import React29 from "react";
44958
45336
  function MdxSearchResults(props) {
44959
45337
  let json = "{}";
44960
45338
  try {
@@ -44962,11 +45340,11 @@ function MdxSearchResults(props) {
44962
45340
  } catch (_) {
44963
45341
  json = "{}";
44964
45342
  }
44965
- return /* @__PURE__ */ React26.createElement("div", { "data-canopy-search-results": "1" }, /* @__PURE__ */ React26.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
45343
+ return /* @__PURE__ */ React29.createElement("div", { "data-canopy-search-results": "1" }, /* @__PURE__ */ React29.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
44966
45344
  }
44967
45345
 
44968
45346
  // ui/src/search/SearchSummary.jsx
44969
- import React27 from "react";
45347
+ import React30 from "react";
44970
45348
  function SearchSummary(props) {
44971
45349
  let json = "{}";
44972
45350
  try {
@@ -44974,11 +45352,11 @@ function SearchSummary(props) {
44974
45352
  } catch (_) {
44975
45353
  json = "{}";
44976
45354
  }
44977
- return /* @__PURE__ */ React27.createElement("div", { "data-canopy-search-summary": "1" }, /* @__PURE__ */ React27.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
45355
+ return /* @__PURE__ */ React30.createElement("div", { "data-canopy-search-summary": "1" }, /* @__PURE__ */ React30.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
44978
45356
  }
44979
45357
 
44980
45358
  // ui/src/search/MdxSearchTabs.jsx
44981
- import React28 from "react";
45359
+ import React31 from "react";
44982
45360
  function MdxSearchTabs(props) {
44983
45361
  let json = "{}";
44984
45362
  try {
@@ -44986,11 +45364,11 @@ function MdxSearchTabs(props) {
44986
45364
  } catch (_) {
44987
45365
  json = "{}";
44988
45366
  }
44989
- return /* @__PURE__ */ React28.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React28.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
45367
+ return /* @__PURE__ */ React31.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React31.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
44990
45368
  }
44991
45369
 
44992
45370
  // ui/src/search/MdxSearch.jsx
44993
- import React29 from "react";
45371
+ import React32 from "react";
44994
45372
  function MdxSearch(props = {}) {
44995
45373
  const {
44996
45374
  layout,
@@ -45008,15 +45386,15 @@ function MdxSearch(props = {}) {
45008
45386
  resultsPayload.layout = layout;
45009
45387
  }
45010
45388
  const classes = ["canopy-search", className].filter(Boolean).join(" ");
45011
- return /* @__PURE__ */ React29.createElement("section", { className: classes, "data-canopy-search": "1" }, showTabs ? /* @__PURE__ */ React29.createElement(MdxSearchTabs, { ...tabsProps }) : null, showSummary ? /* @__PURE__ */ React29.createElement(SearchSummary, { ...summaryProps }) : null, showResults ? /* @__PURE__ */ React29.createElement(MdxSearchResults, { ...resultsPayload }) : null, children || null);
45389
+ return /* @__PURE__ */ React32.createElement("section", { className: classes, "data-canopy-search": "1" }, showTabs ? /* @__PURE__ */ React32.createElement(MdxSearchTabs, { ...tabsProps }) : null, showSummary ? /* @__PURE__ */ React32.createElement(SearchSummary, { ...summaryProps }) : null, showResults ? /* @__PURE__ */ React32.createElement(MdxSearchResults, { ...resultsPayload }) : null, children || null);
45012
45390
  }
45013
45391
 
45014
45392
  // ui/src/search/SearchResults.jsx
45015
- import React30 from "react";
45393
+ import React33 from "react";
45016
45394
  function DefaultArticleTemplate({ record, query }) {
45017
45395
  if (!record) return null;
45018
45396
  const metadata = Array.isArray(record.metadata) ? record.metadata : [];
45019
- return /* @__PURE__ */ React30.createElement(
45397
+ return /* @__PURE__ */ React33.createElement(
45020
45398
  ArticleCard,
45021
45399
  {
45022
45400
  href: record.href,
@@ -45034,7 +45412,7 @@ function DefaultFigureTemplate({ record, thumbnailAspectRatio }) {
45034
45412
  if (!record) return null;
45035
45413
  const hasDims = Number.isFinite(Number(record.thumbnailWidth)) && Number(record.thumbnailWidth) > 0 && Number.isFinite(Number(record.thumbnailHeight)) && Number(record.thumbnailHeight) > 0;
45036
45414
  const aspect = Number.isFinite(Number(thumbnailAspectRatio)) && Number(thumbnailAspectRatio) > 0 ? Number(thumbnailAspectRatio) : hasDims ? Number(record.thumbnailWidth) / Number(record.thumbnailHeight) : void 0;
45037
- return /* @__PURE__ */ React30.createElement(
45415
+ return /* @__PURE__ */ React33.createElement(
45038
45416
  Card,
45039
45417
  {
45040
45418
  href: record.href,
@@ -45055,7 +45433,7 @@ function SearchResults({
45055
45433
  variant = "auto"
45056
45434
  }) {
45057
45435
  if (!results.length) {
45058
- return /* @__PURE__ */ React30.createElement("div", { className: "text-slate-600" }, /* @__PURE__ */ React30.createElement("em", null, "No results"));
45436
+ return /* @__PURE__ */ React33.createElement("div", { className: "text-slate-600" }, /* @__PURE__ */ React33.createElement("em", null, "No results"));
45059
45437
  }
45060
45438
  const normalizedType = String(type || "all").toLowerCase();
45061
45439
  const normalizedVariant = variant === "figure" || variant === "article" ? variant : "auto";
@@ -45063,9 +45441,9 @@ function SearchResults({
45063
45441
  const FigureTemplate = templates && templates.figure ? templates.figure : DefaultFigureTemplate;
45064
45442
  const ArticleTemplate = templates && templates.article ? templates.article : DefaultArticleTemplate;
45065
45443
  if (isAnnotationView) {
45066
- return /* @__PURE__ */ React30.createElement("div", { id: "search-results", className: "space-y-4", role: "region", "aria-label": "Search results" }, results.map((r, i) => {
45444
+ return /* @__PURE__ */ React33.createElement("div", { id: "search-results", className: "space-y-4", role: "region", "aria-label": "Search results" }, results.map((r, i) => {
45067
45445
  if (!r) return null;
45068
- return /* @__PURE__ */ React30.createElement(
45446
+ return /* @__PURE__ */ React33.createElement(
45069
45447
  ArticleTemplate,
45070
45448
  {
45071
45449
  key: r.id || i,
@@ -45083,20 +45461,20 @@ function SearchResults({
45083
45461
  return !isWorkRecord(record) || normalizedType !== "work";
45084
45462
  };
45085
45463
  if (layout === "list") {
45086
- return /* @__PURE__ */ React30.createElement("div", { id: "search-results", className: "space-y-6", role: "region", "aria-label": "Search results" }, results.map((r, i) => {
45464
+ return /* @__PURE__ */ React33.createElement("div", { id: "search-results", className: "space-y-6", role: "region", "aria-label": "Search results" }, results.map((r, i) => {
45087
45465
  if (shouldRenderAsArticle(r)) {
45088
- return /* @__PURE__ */ React30.createElement("div", { key: i, className: `search-result ${r && r.type}` }, /* @__PURE__ */ React30.createElement(ArticleTemplate, { record: r, query, layout }));
45466
+ return /* @__PURE__ */ React33.createElement("div", { key: i, className: `search-result ${r && r.type}` }, /* @__PURE__ */ React33.createElement(ArticleTemplate, { record: r, query, layout }));
45089
45467
  }
45090
45468
  const hasDims = Number.isFinite(Number(r.thumbnailWidth)) && Number(r.thumbnailWidth) > 0 && Number.isFinite(Number(r.thumbnailHeight)) && Number(r.thumbnailHeight) > 0;
45091
45469
  const aspect = hasDims ? Number(r.thumbnailWidth) / Number(r.thumbnailHeight) : void 0;
45092
- return /* @__PURE__ */ React30.createElement(
45470
+ return /* @__PURE__ */ React33.createElement(
45093
45471
  "div",
45094
45472
  {
45095
45473
  key: i,
45096
45474
  className: `search-result ${r.type}`,
45097
45475
  "data-thumbnail-aspect-ratio": aspect
45098
45476
  },
45099
- /* @__PURE__ */ React30.createElement(
45477
+ /* @__PURE__ */ React33.createElement(
45100
45478
  FigureTemplate,
45101
45479
  {
45102
45480
  record: r,
@@ -45108,20 +45486,20 @@ function SearchResults({
45108
45486
  );
45109
45487
  }));
45110
45488
  }
45111
- return /* @__PURE__ */ React30.createElement("div", { id: "search-results", role: "region", "aria-label": "Search results" }, /* @__PURE__ */ React30.createElement(Grid, null, results.map((r, i) => {
45489
+ return /* @__PURE__ */ React33.createElement("div", { id: "search-results", role: "region", "aria-label": "Search results" }, /* @__PURE__ */ React33.createElement(Grid, null, results.map((r, i) => {
45112
45490
  if (shouldRenderAsArticle(r)) {
45113
- return /* @__PURE__ */ React30.createElement(GridItem, { key: i, className: `search-result ${r && r.type}` }, /* @__PURE__ */ React30.createElement(ArticleTemplate, { record: r, query, layout }));
45491
+ return /* @__PURE__ */ React33.createElement(GridItem, { key: i, className: `search-result ${r && r.type}` }, /* @__PURE__ */ React33.createElement(ArticleTemplate, { record: r, query, layout }));
45114
45492
  }
45115
45493
  const hasDims = Number.isFinite(Number(r.thumbnailWidth)) && Number(r.thumbnailWidth) > 0 && Number.isFinite(Number(r.thumbnailHeight)) && Number(r.thumbnailHeight) > 0;
45116
45494
  const aspect = hasDims ? Number(r.thumbnailWidth) / Number(r.thumbnailHeight) : void 0;
45117
- return /* @__PURE__ */ React30.createElement(
45495
+ return /* @__PURE__ */ React33.createElement(
45118
45496
  GridItem,
45119
45497
  {
45120
45498
  key: i,
45121
45499
  className: `search-result ${r.type}`,
45122
45500
  "data-thumbnail-aspect-ratio": aspect
45123
45501
  },
45124
- /* @__PURE__ */ React30.createElement(
45502
+ /* @__PURE__ */ React33.createElement(
45125
45503
  FigureTemplate,
45126
45504
  {
45127
45505
  record: r,
@@ -45135,7 +45513,7 @@ function SearchResults({
45135
45513
  }
45136
45514
 
45137
45515
  // ui/src/search/SearchTabs.jsx
45138
- import React31, { useRef as useRef3, useState as useState6, useEffect as useEffect7 } from "react";
45516
+ import React34, { useRef as useRef3, useState as useState6, useEffect as useEffect7 } from "react";
45139
45517
  function SearchTabs({
45140
45518
  type = "all",
45141
45519
  onTypeChange,
@@ -45189,7 +45567,7 @@ function SearchTabs({
45189
45567
  width: `${itemBoundingBox.width}px`
45190
45568
  };
45191
45569
  }
45192
- return /* @__PURE__ */ React31.createElement("div", { className: "canopy-search-tabs-wrapper" }, /* @__PURE__ */ React31.createElement(
45570
+ return /* @__PURE__ */ React34.createElement("div", { className: "canopy-search-tabs-wrapper" }, /* @__PURE__ */ React34.createElement(
45193
45571
  "div",
45194
45572
  {
45195
45573
  role: "tablist",
@@ -45198,7 +45576,7 @@ function SearchTabs({
45198
45576
  ref: wrapperRef,
45199
45577
  onMouseLeave: resetHighlight
45200
45578
  },
45201
- /* @__PURE__ */ React31.createElement(
45579
+ /* @__PURE__ */ React34.createElement(
45202
45580
  "div",
45203
45581
  {
45204
45582
  ref: highlightRef,
@@ -45210,7 +45588,7 @@ function SearchTabs({
45210
45588
  const active = String(type).toLowerCase() === String(t).toLowerCase();
45211
45589
  const cRaw = counts && Object.prototype.hasOwnProperty.call(counts, t) ? counts[t] : void 0;
45212
45590
  const c = Number.isFinite(Number(cRaw)) ? Number(cRaw) : 0;
45213
- return /* @__PURE__ */ React31.createElement(
45591
+ return /* @__PURE__ */ React34.createElement(
45214
45592
  "button",
45215
45593
  {
45216
45594
  key: t,
@@ -45228,7 +45606,7 @@ function SearchTabs({
45228
45606
  ")"
45229
45607
  );
45230
45608
  })
45231
- ), hasFilters ? /* @__PURE__ */ React31.createElement(
45609
+ ), hasFilters ? /* @__PURE__ */ React34.createElement(
45232
45610
  "button",
45233
45611
  {
45234
45612
  type: "button",
@@ -45236,12 +45614,12 @@ function SearchTabs({
45236
45614
  "aria-expanded": filtersOpen ? "true" : "false",
45237
45615
  className: "inline-flex items-center gap-2 rounded-md border border-slate-200 bg-white px-3 py-1.5 text-sm font-medium text-slate-700 shadow-sm transition hover:border-brand-200 hover:bg-brand-50 hover:text-brand-700"
45238
45616
  },
45239
- /* @__PURE__ */ React31.createElement("span", null, filtersLabel, filterBadge)
45617
+ /* @__PURE__ */ React34.createElement("span", null, filtersLabel, filterBadge)
45240
45618
  ) : null);
45241
45619
  }
45242
45620
 
45243
45621
  // ui/src/search/SearchFiltersDialog.jsx
45244
- import React32 from "react";
45622
+ import React35 from "react";
45245
45623
  function toArray(input) {
45246
45624
  if (!input) return [];
45247
45625
  if (Array.isArray(input)) return input;
@@ -45280,20 +45658,20 @@ function FacetSection({ facet, selected, onToggle }) {
45280
45658
  const selectedValues = selected.get(String(slug)) || /* @__PURE__ */ new Set();
45281
45659
  const checkboxId = (valueSlug) => `filter-${slug}-${valueSlug}`;
45282
45660
  const hasSelection = selectedValues.size > 0;
45283
- const [quickQuery, setQuickQuery] = React32.useState("");
45661
+ const [quickQuery, setQuickQuery] = React35.useState("");
45284
45662
  const hasQuery = quickQuery.trim().length > 0;
45285
- const filteredValues = React32.useMemo(
45663
+ const filteredValues = React35.useMemo(
45286
45664
  () => facetMatches(values, quickQuery),
45287
45665
  [values, quickQuery]
45288
45666
  );
45289
- return /* @__PURE__ */ React32.createElement(
45667
+ return /* @__PURE__ */ React35.createElement(
45290
45668
  "details",
45291
45669
  {
45292
45670
  className: "canopy-search-filters__facet",
45293
45671
  open: hasSelection
45294
45672
  },
45295
- /* @__PURE__ */ React32.createElement("summary", { className: "canopy-search-filters__facet-summary" }, /* @__PURE__ */ React32.createElement("span", null, label), /* @__PURE__ */ React32.createElement("span", { className: "canopy-search-filters__facet-count" }, values.length)),
45296
- /* @__PURE__ */ React32.createElement("div", { className: "canopy-search-filters__facet-content" }, /* @__PURE__ */ React32.createElement("div", { className: "canopy-search-filters__quick" }, /* @__PURE__ */ React32.createElement(
45673
+ /* @__PURE__ */ React35.createElement("summary", { className: "canopy-search-filters__facet-summary" }, /* @__PURE__ */ React35.createElement("span", null, label), /* @__PURE__ */ React35.createElement("span", { className: "canopy-search-filters__facet-count" }, values.length)),
45674
+ /* @__PURE__ */ React35.createElement("div", { className: "canopy-search-filters__facet-content" }, /* @__PURE__ */ React35.createElement("div", { className: "canopy-search-filters__quick" }, /* @__PURE__ */ React35.createElement(
45297
45675
  "input",
45298
45676
  {
45299
45677
  type: "search",
@@ -45303,7 +45681,7 @@ function FacetSection({ facet, selected, onToggle }) {
45303
45681
  className: "canopy-search-filters__quick-input",
45304
45682
  "aria-label": `Filter ${label} values`
45305
45683
  }
45306
- ), quickQuery ? /* @__PURE__ */ React32.createElement(
45684
+ ), quickQuery ? /* @__PURE__ */ React35.createElement(
45307
45685
  "button",
45308
45686
  {
45309
45687
  type: "button",
@@ -45312,11 +45690,11 @@ function FacetSection({ facet, selected, onToggle }) {
45312
45690
  "aria-label": `Clear ${label} filter search`
45313
45691
  },
45314
45692
  "Clear"
45315
- ) : null), hasQuery && !filteredValues.length ? /* @__PURE__ */ React32.createElement("p", { className: "canopy-search-filters__facet-notice" }, "No matches found.") : null, /* @__PURE__ */ React32.createElement("ul", { className: "canopy-search-filters__facet-list" }, filteredValues.map((entry) => {
45693
+ ) : null), hasQuery && !filteredValues.length ? /* @__PURE__ */ React35.createElement("p", { className: "canopy-search-filters__facet-notice" }, "No matches found.") : null, /* @__PURE__ */ React35.createElement("ul", { className: "canopy-search-filters__facet-list" }, filteredValues.map((entry) => {
45316
45694
  const valueSlug = String(entry.slug || entry.value || "");
45317
45695
  const isChecked = selectedValues.has(valueSlug);
45318
45696
  const inputId = checkboxId(valueSlug);
45319
- return /* @__PURE__ */ React32.createElement("li", { key: valueSlug, className: "canopy-search-filters__facet-item" }, /* @__PURE__ */ React32.createElement(
45697
+ return /* @__PURE__ */ React35.createElement("li", { key: valueSlug, className: "canopy-search-filters__facet-item" }, /* @__PURE__ */ React35.createElement(
45320
45698
  "input",
45321
45699
  {
45322
45700
  id: inputId,
@@ -45328,15 +45706,15 @@ function FacetSection({ facet, selected, onToggle }) {
45328
45706
  if (onToggle) onToggle(slug, valueSlug, nextChecked);
45329
45707
  }
45330
45708
  }
45331
- ), /* @__PURE__ */ React32.createElement(
45709
+ ), /* @__PURE__ */ React35.createElement(
45332
45710
  "label",
45333
45711
  {
45334
45712
  htmlFor: inputId,
45335
45713
  className: "canopy-search-filters__facet-label"
45336
45714
  },
45337
- /* @__PURE__ */ React32.createElement("span", null, entry.value, " ", Number.isFinite(entry.doc_count) ? /* @__PURE__ */ React32.createElement("span", { className: "canopy-search-filters__facet-count" }, "(", entry.doc_count, ")") : null)
45715
+ /* @__PURE__ */ React35.createElement("span", null, entry.value, " ", Number.isFinite(entry.doc_count) ? /* @__PURE__ */ React35.createElement("span", { className: "canopy-search-filters__facet-count" }, "(", entry.doc_count, ")") : null)
45338
45716
  ));
45339
- }), !filteredValues.length && !hasQuery ? /* @__PURE__ */ React32.createElement("li", { className: "canopy-search-filters__facet-empty" }, "No values available.") : null))
45717
+ }), !filteredValues.length && !hasQuery ? /* @__PURE__ */ React35.createElement("li", { className: "canopy-search-filters__facet-empty" }, "No values available.") : null))
45340
45718
  );
45341
45719
  }
45342
45720
  function SearchFiltersDialog(props = {}) {
@@ -45358,7 +45736,7 @@ function SearchFiltersDialog(props = {}) {
45358
45736
  (total, set) => total + set.size,
45359
45737
  0
45360
45738
  );
45361
- React32.useEffect(() => {
45739
+ React35.useEffect(() => {
45362
45740
  if (!open) return void 0;
45363
45741
  if (typeof document === "undefined") return void 0;
45364
45742
  const body = document.body;
@@ -45375,7 +45753,7 @@ function SearchFiltersDialog(props = {}) {
45375
45753
  if (!open) return null;
45376
45754
  const brandId = "canopy-modal-filters-label";
45377
45755
  const subtitleText = subtitle != null ? subtitle : title;
45378
- return /* @__PURE__ */ React32.createElement(
45756
+ return /* @__PURE__ */ React35.createElement(
45379
45757
  CanopyModal,
45380
45758
  {
45381
45759
  id: "canopy-modal-filters",
@@ -45390,8 +45768,8 @@ function SearchFiltersDialog(props = {}) {
45390
45768
  onBackgroundClick: () => onOpenChange && onOpenChange(false),
45391
45769
  bodyClassName: "canopy-modal__body--filters"
45392
45770
  },
45393
- subtitleText ? /* @__PURE__ */ React32.createElement("p", { className: "canopy-search-filters__subtitle" }, subtitleText) : null,
45394
- /* @__PURE__ */ React32.createElement("div", { className: "canopy-search-filters__body" }, Array.isArray(facets) && facets.length ? /* @__PURE__ */ React32.createElement("div", { className: "canopy-search-filters__facets" }, facets.map((facet) => /* @__PURE__ */ React32.createElement(
45771
+ subtitleText ? /* @__PURE__ */ React35.createElement("p", { className: "canopy-search-filters__subtitle" }, subtitleText) : null,
45772
+ /* @__PURE__ */ React35.createElement("div", { className: "canopy-search-filters__body" }, Array.isArray(facets) && facets.length ? /* @__PURE__ */ React35.createElement("div", { className: "canopy-search-filters__facets" }, facets.map((facet) => /* @__PURE__ */ React35.createElement(
45395
45773
  FacetSection,
45396
45774
  {
45397
45775
  key: facet.slug || facet.label,
@@ -45399,8 +45777,8 @@ function SearchFiltersDialog(props = {}) {
45399
45777
  selected: selectedMap,
45400
45778
  onToggle
45401
45779
  }
45402
- ))) : /* @__PURE__ */ React32.createElement("p", { className: "canopy-search-filters__empty" }, "No filters are available for this collection.")),
45403
- /* @__PURE__ */ React32.createElement("footer", { className: "canopy-search-filters__footer" }, /* @__PURE__ */ React32.createElement("div", null, activeCount ? `${activeCount} filter${activeCount === 1 ? "" : "s"} applied` : "No filters applied"), /* @__PURE__ */ React32.createElement("div", { className: "canopy-search-filters__footer-actions" }, /* @__PURE__ */ React32.createElement(
45780
+ ))) : /* @__PURE__ */ React35.createElement("p", { className: "canopy-search-filters__empty" }, "No filters are available for this collection.")),
45781
+ /* @__PURE__ */ React35.createElement("footer", { className: "canopy-search-filters__footer" }, /* @__PURE__ */ React35.createElement("div", null, activeCount ? `${activeCount} filter${activeCount === 1 ? "" : "s"} applied` : "No filters applied"), /* @__PURE__ */ React35.createElement("div", { className: "canopy-search-filters__footer-actions" }, /* @__PURE__ */ React35.createElement(
45404
45782
  "button",
45405
45783
  {
45406
45784
  type: "button",
@@ -45411,7 +45789,7 @@ function SearchFiltersDialog(props = {}) {
45411
45789
  className: "canopy-search-filters__button canopy-search-filters__button--secondary"
45412
45790
  },
45413
45791
  "Clear all"
45414
- ), /* @__PURE__ */ React32.createElement(
45792
+ ), /* @__PURE__ */ React35.createElement(
45415
45793
  "button",
45416
45794
  {
45417
45795
  type: "button",
@@ -45424,7 +45802,7 @@ function SearchFiltersDialog(props = {}) {
45424
45802
  }
45425
45803
 
45426
45804
  // ui/src/search-form/MdxSearchFormModal.jsx
45427
- import React33 from "react";
45805
+ import React36 from "react";
45428
45806
  function MdxSearchFormModal(props = {}) {
45429
45807
  const {
45430
45808
  placeholder = "Search\u2026",
@@ -45440,24 +45818,24 @@ function MdxSearchFormModal(props = {}) {
45440
45818
  const text = typeof label === "string" && label.trim() ? label.trim() : buttonLabel;
45441
45819
  const resolvedSearchPath = resolveSearchPath(searchPath);
45442
45820
  const data = { placeholder, hotkey, maxResults, groupOrder, label: text, searchPath: resolvedSearchPath };
45443
- return /* @__PURE__ */ React33.createElement("div", { "data-canopy-search-form": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React33.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React33.createElement(SearchPanelForm, { placeholder, buttonLabel, label, searchPath: resolvedSearchPath }), /* @__PURE__ */ React33.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React33.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
45821
+ return /* @__PURE__ */ React36.createElement("div", { "data-canopy-search-form": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React36.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React36.createElement(SearchPanelForm, { placeholder, buttonLabel, label, searchPath: resolvedSearchPath }), /* @__PURE__ */ React36.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React36.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
45444
45822
  }
45445
45823
 
45446
45824
  // ui/src/docs/MarkdownTable.jsx
45447
- import React34 from "react";
45825
+ import React37 from "react";
45448
45826
  function MarkdownTable({ className = "", ...rest }) {
45449
45827
  const merged = ["markdown-table", className].filter(Boolean).join(" ");
45450
- return /* @__PURE__ */ React34.createElement("div", { className: "markdown-table__frame" }, /* @__PURE__ */ React34.createElement("table", { className: merged, ...rest }));
45828
+ return /* @__PURE__ */ React37.createElement("div", { className: "markdown-table__frame" }, /* @__PURE__ */ React37.createElement("table", { className: merged, ...rest }));
45451
45829
  }
45452
45830
 
45453
45831
  // ui/src/docs/Diagram.jsx
45454
- import React35 from "react";
45832
+ import React38 from "react";
45455
45833
  function CanopyDiagram() {
45456
- return /* @__PURE__ */ React35.createElement("div", { className: "canopy-diagram" }, /* @__PURE__ */ React35.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--collections" }, /* @__PURE__ */ React35.createElement("h3", null, "IIIF Providers"), /* @__PURE__ */ React35.createElement("span", { className: "canopy-diagram__section-summary" }, "Source collections contribute 45 manifests while 5 manifests are directly retrieved as-is via IIIF endpoints."), /* @__PURE__ */ React35.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React35.createElement("article", null, /* @__PURE__ */ React35.createElement("h4", null, "Collection A"), /* @__PURE__ */ React35.createElement("ul", null, /* @__PURE__ */ React35.createElement("li", null, "30 Manifests"), /* @__PURE__ */ React35.createElement("li", null, /* @__PURE__ */ React35.createElement("em", null, "Manuscripts")))), /* @__PURE__ */ React35.createElement("article", null, /* @__PURE__ */ React35.createElement("h4", null, "Collection B"), /* @__PURE__ */ React35.createElement("ul", null, /* @__PURE__ */ React35.createElement("li", null, "15 Manifests"), /* @__PURE__ */ React35.createElement("li", null, /* @__PURE__ */ React35.createElement("em", null, "Portraits")))), /* @__PURE__ */ React35.createElement("article", null, /* @__PURE__ */ React35.createElement("h4", null, "Manifests (direct)"), /* @__PURE__ */ React35.createElement("ul", null, /* @__PURE__ */ React35.createElement("li", null, "5 Manifests"), /* @__PURE__ */ React35.createElement("li", null, /* @__PURE__ */ React35.createElement("em", null, "Scrapbooks")))))), /* @__PURE__ */ React35.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React35.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React35.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React35.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--build" }, /* @__PURE__ */ React35.createElement("h3", null, "Canopy Build Process"), /* @__PURE__ */ React35.createElement("span", { className: "canopy-diagram__section-summary" }, "Canopy retrieves collections and syncs all manifests, page content, and annotations before bundling the site."), /* @__PURE__ */ React35.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React35.createElement("article", null, /* @__PURE__ */ React35.createElement("h4", null, "Automated content"), /* @__PURE__ */ React35.createElement("ul", null, /* @__PURE__ */ React35.createElement("li", null, "50 manifests \u2192 50 work pages"), /* @__PURE__ */ React35.createElement("li", null, "One page per manifest"), /* @__PURE__ */ React35.createElement("li", null, "Customize page layout"))), /* @__PURE__ */ React35.createElement("article", null, /* @__PURE__ */ React35.createElement("h4", null, "Contextual content"), /* @__PURE__ */ React35.createElement("ul", null, /* @__PURE__ */ React35.createElement("li", null, "Markdown & MDX pages"), /* @__PURE__ */ React35.createElement("li", null, "Author narratives"), /* @__PURE__ */ React35.createElement("li", null, "Reference manifests inline"))), /* @__PURE__ */ React35.createElement("article", null, /* @__PURE__ */ React35.createElement("h4", null, "Search index"), /* @__PURE__ */ React35.createElement("ul", null, /* @__PURE__ */ React35.createElement("li", null, "Combines works + pages"), /* @__PURE__ */ React35.createElement("li", null, "Customize result layout"), /* @__PURE__ */ React35.createElement("li", null, "Optional annotations"))))), /* @__PURE__ */ React35.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React35.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React35.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React35.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--output" }, /* @__PURE__ */ React35.createElement("h3", null, "Static Digital Project"), /* @__PURE__ */ React35.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__ */ React35.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React35.createElement("article", null, /* @__PURE__ */ React35.createElement("h4", null, "Work pages"), /* @__PURE__ */ React35.createElement("ul", null, /* @__PURE__ */ React35.createElement("li", null, "50 generated HTML pages"), /* @__PURE__ */ React35.createElement("li", null, "Each links back to source manifests"), /* @__PURE__ */ React35.createElement("li", null, "Styled with Canopy components"))), /* @__PURE__ */ React35.createElement("article", null, /* @__PURE__ */ React35.createElement("h4", null, "Custom pages"), /* @__PURE__ */ React35.createElement("ul", null, /* @__PURE__ */ React35.createElement("li", null, "Markdown & MDX-authored content"), /* @__PURE__ */ React35.createElement("li", null, "Reusable layouts for narratives"), /* @__PURE__ */ React35.createElement("li", null, "Embed IIIF media & interstitials"))), /* @__PURE__ */ React35.createElement("article", null, /* @__PURE__ */ React35.createElement("h4", null, "Search bundle"), /* @__PURE__ */ React35.createElement("ul", null, /* @__PURE__ */ React35.createElement("li", null, "Static FlexSearch index"), /* @__PURE__ */ React35.createElement("li", null, "Works + pages share records"), /* @__PURE__ */ React35.createElement("li", null, "Optional annotation dataset"))))));
45834
+ return /* @__PURE__ */ React38.createElement("div", { className: "canopy-diagram" }, /* @__PURE__ */ React38.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--collections" }, /* @__PURE__ */ React38.createElement("h3", null, "IIIF Providers"), /* @__PURE__ */ React38.createElement("span", { className: "canopy-diagram__section-summary" }, "Source collections contribute 45 manifests while 5 manifests are directly retrieved as-is via IIIF endpoints."), /* @__PURE__ */ React38.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React38.createElement("article", null, /* @__PURE__ */ React38.createElement("h4", null, "Collection A"), /* @__PURE__ */ React38.createElement("ul", null, /* @__PURE__ */ React38.createElement("li", null, "30 Manifests"), /* @__PURE__ */ React38.createElement("li", null, /* @__PURE__ */ React38.createElement("em", null, "Manuscripts")))), /* @__PURE__ */ React38.createElement("article", null, /* @__PURE__ */ React38.createElement("h4", null, "Collection B"), /* @__PURE__ */ React38.createElement("ul", null, /* @__PURE__ */ React38.createElement("li", null, "15 Manifests"), /* @__PURE__ */ React38.createElement("li", null, /* @__PURE__ */ React38.createElement("em", null, "Portraits")))), /* @__PURE__ */ React38.createElement("article", null, /* @__PURE__ */ React38.createElement("h4", null, "Manifests (direct)"), /* @__PURE__ */ React38.createElement("ul", null, /* @__PURE__ */ React38.createElement("li", null, "5 Manifests"), /* @__PURE__ */ React38.createElement("li", null, /* @__PURE__ */ React38.createElement("em", null, "Scrapbooks")))))), /* @__PURE__ */ React38.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React38.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React38.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React38.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--build" }, /* @__PURE__ */ React38.createElement("h3", null, "Canopy Build Process"), /* @__PURE__ */ React38.createElement("span", { className: "canopy-diagram__section-summary" }, "Canopy retrieves collections and syncs all manifests, page content, and annotations before bundling the site."), /* @__PURE__ */ React38.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React38.createElement("article", null, /* @__PURE__ */ React38.createElement("h4", null, "Automated content"), /* @__PURE__ */ React38.createElement("ul", null, /* @__PURE__ */ React38.createElement("li", null, "50 manifests \u2192 50 work pages"), /* @__PURE__ */ React38.createElement("li", null, "One page per manifest"), /* @__PURE__ */ React38.createElement("li", null, "Customize page layout"))), /* @__PURE__ */ React38.createElement("article", null, /* @__PURE__ */ React38.createElement("h4", null, "Contextual content"), /* @__PURE__ */ React38.createElement("ul", null, /* @__PURE__ */ React38.createElement("li", null, "Markdown & MDX pages"), /* @__PURE__ */ React38.createElement("li", null, "Author narratives"), /* @__PURE__ */ React38.createElement("li", null, "Reference manifests inline"))), /* @__PURE__ */ React38.createElement("article", null, /* @__PURE__ */ React38.createElement("h4", null, "Search index"), /* @__PURE__ */ React38.createElement("ul", null, /* @__PURE__ */ React38.createElement("li", null, "Combines works + pages"), /* @__PURE__ */ React38.createElement("li", null, "Customize result layout"), /* @__PURE__ */ React38.createElement("li", null, "Optional annotations"))))), /* @__PURE__ */ React38.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React38.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React38.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React38.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--output" }, /* @__PURE__ */ React38.createElement("h3", null, "Static Digital Project"), /* @__PURE__ */ React38.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__ */ React38.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React38.createElement("article", null, /* @__PURE__ */ React38.createElement("h4", null, "Work pages"), /* @__PURE__ */ React38.createElement("ul", null, /* @__PURE__ */ React38.createElement("li", null, "50 generated HTML pages"), /* @__PURE__ */ React38.createElement("li", null, "Each links back to source manifests"), /* @__PURE__ */ React38.createElement("li", null, "Styled with Canopy components"))), /* @__PURE__ */ React38.createElement("article", null, /* @__PURE__ */ React38.createElement("h4", null, "Custom pages"), /* @__PURE__ */ React38.createElement("ul", null, /* @__PURE__ */ React38.createElement("li", null, "Markdown & MDX-authored content"), /* @__PURE__ */ React38.createElement("li", null, "Reusable layouts for narratives"), /* @__PURE__ */ React38.createElement("li", null, "Embed IIIF media & interstitials"))), /* @__PURE__ */ React38.createElement("article", null, /* @__PURE__ */ React38.createElement("h4", null, "Search bundle"), /* @__PURE__ */ React38.createElement("ul", null, /* @__PURE__ */ React38.createElement("li", null, "Static FlexSearch index"), /* @__PURE__ */ React38.createElement("li", null, "Works + pages share records"), /* @__PURE__ */ React38.createElement("li", null, "Optional annotation dataset"))))));
45457
45835
  }
45458
45836
 
45459
45837
  // ui/src/content/timeline/Timeline.jsx
45460
- import React37 from "react";
45838
+ import React40 from "react";
45461
45839
 
45462
45840
  // ui/src/content/timeline/date-utils.js
45463
45841
  var FALLBACK_LOCALE = (() => {
@@ -45610,7 +45988,7 @@ function clampProgress(value) {
45610
45988
  }
45611
45989
 
45612
45990
  // ui/src/layout/ReferencedManifestCard.jsx
45613
- import React36 from "react";
45991
+ import React39 from "react";
45614
45992
  function normalizeMetadata(metadata, summary) {
45615
45993
  if (Array.isArray(metadata) && metadata.length) {
45616
45994
  return metadata.filter(Boolean);
@@ -45644,7 +46022,7 @@ function ReferencedManifestCard({
45644
46022
  "canopy-referenced-manifest-card",
45645
46023
  className
45646
46024
  ].filter(Boolean).join(" ");
45647
- return /* @__PURE__ */ React36.createElement(
46025
+ return /* @__PURE__ */ React39.createElement(
45648
46026
  TeaserCard,
45649
46027
  {
45650
46028
  href: resolvedHref || void 0,
@@ -45826,14 +46204,14 @@ function TimelineConnector({ side, isActive, highlight }) {
45826
46204
  "canopy-timeline__connector-dot",
45827
46205
  highlight || isActive ? "is-active" : ""
45828
46206
  ].filter(Boolean).join(" ");
45829
- 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" })));
46207
+ return /* @__PURE__ */ React40.createElement("span", { className: connectorClasses, "aria-hidden": "true" }, side === "left" ? /* @__PURE__ */ React40.createElement(React40.Fragment, null, /* @__PURE__ */ React40.createElement("span", { className: "canopy-timeline__connector-line" }), /* @__PURE__ */ React40.createElement("span", { className: dotClasses })) : /* @__PURE__ */ React40.createElement(React40.Fragment, null, /* @__PURE__ */ React40.createElement("span", { className: dotClasses }), /* @__PURE__ */ React40.createElement("span", { className: "canopy-timeline__connector-line" })));
45830
46208
  }
45831
46209
  function renderResourceSection(point2) {
45832
46210
  if (!point2) return null;
45833
46211
  const manifestCards = Array.isArray(point2.manifests) ? point2.manifests.filter(Boolean) : [];
45834
46212
  const legacyResources = Array.isArray(point2.resources) ? point2.resources.filter(Boolean) : [];
45835
46213
  if (!manifestCards.length && !legacyResources.length) return null;
45836
- 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(
46214
+ return /* @__PURE__ */ React40.createElement("div", { className: "canopy-timeline__resources" }, /* @__PURE__ */ React40.createElement("div", { className: "canopy-timeline__resources-list" }, manifestCards.map((manifest) => /* @__PURE__ */ React40.createElement("div", { key: manifest.id || manifest.href }, /* @__PURE__ */ React40.createElement(ReferencedManifestCard, { manifest }))), legacyResources.map((resource, idx) => /* @__PURE__ */ React40.createElement("div", { key: resource.id || resource.href || `legacy-${idx}` }, /* @__PURE__ */ React40.createElement(
45837
46215
  TeaserCard,
45838
46216
  {
45839
46217
  href: resource.href,
@@ -45858,26 +46236,26 @@ function Timeline({
45858
46236
  ...rest
45859
46237
  }) {
45860
46238
  const payloadPoints = payload && Array.isArray(payload.points) ? payload.points : null;
45861
- const rawPoints = React37.useMemo(() => {
46239
+ const rawPoints = React40.useMemo(() => {
45862
46240
  if (Array.isArray(pointsProp) && pointsProp.length) return pointsProp;
45863
46241
  if (payloadPoints && payloadPoints.length) return payloadPoints;
45864
46242
  return [];
45865
46243
  }, [pointsProp, payloadPoints]);
45866
- const sanitizedPoints = React37.useMemo(
46244
+ const sanitizedPoints = React40.useMemo(
45867
46245
  () => sanitizePoints(rawPoints),
45868
46246
  [rawPoints]
45869
46247
  );
45870
46248
  const localeValue = payload && payload.locale ? payload.locale : localeProp;
45871
- const baseLocale = React37.useMemo(
46249
+ const baseLocale = React40.useMemo(
45872
46250
  () => createLocale(localeValue),
45873
46251
  [localeValue]
45874
46252
  );
45875
46253
  const rangeInput = payload && payload.range ? payload.range : rangeProp || {};
45876
- const rangeOverrides = React37.useMemo(
46254
+ const rangeOverrides = React40.useMemo(
45877
46255
  () => deriveRangeOverrides(sanitizedPoints, rangeInput),
45878
46256
  [sanitizedPoints, rangeInput]
45879
46257
  );
45880
- const effectiveRange = React37.useMemo(
46258
+ const effectiveRange = React40.useMemo(
45881
46259
  () => normalizeRange({
45882
46260
  ...rangeOverrides,
45883
46261
  locale: baseLocale
@@ -45886,7 +46264,7 @@ function Timeline({
45886
46264
  );
45887
46265
  const spanStart = effectiveRange.startDate.getTime();
45888
46266
  const span = effectiveRange.span;
45889
- const pointsWithPosition = React37.useMemo(() => {
46267
+ const pointsWithPosition = React40.useMemo(() => {
45890
46268
  if (!sanitizedPoints.length) return [];
45891
46269
  return sanitizedPoints.map((point2, index) => {
45892
46270
  const timestamp = point2.meta.timestamp;
@@ -45900,29 +46278,29 @@ function Timeline({
45900
46278
  };
45901
46279
  });
45902
46280
  }, [sanitizedPoints, spanStart, span]);
45903
- const [activeId, setActiveId] = React37.useState(
46281
+ const [activeId, setActiveId] = React40.useState(
45904
46282
  () => getActivePointId(pointsWithPosition)
45905
46283
  );
45906
- React37.useEffect(() => {
46284
+ React40.useEffect(() => {
45907
46285
  setActiveId(getActivePointId(pointsWithPosition));
45908
46286
  }, [pointsWithPosition]);
45909
46287
  const thresholdValue = typeof thresholdProp === "number" ? thresholdProp : payload && payload.threshold != null ? payload.threshold : null;
45910
46288
  const stepsValue = typeof steps === "number" ? Number(steps) : payload && typeof payload.steps === "number" ? Number(payload.steps) : null;
45911
- const thresholdMs = React37.useMemo(
46289
+ const thresholdMs = React40.useMemo(
45912
46290
  () => getThresholdMs(thresholdValue, effectiveRange.granularity),
45913
46291
  [thresholdValue, effectiveRange.granularity]
45914
46292
  );
45915
- const groupedEntries = React37.useMemo(
46293
+ const groupedEntries = React40.useMemo(
45916
46294
  () => buildGroupedEntries(pointsWithPosition, thresholdMs, {
45917
46295
  granularity: effectiveRange.granularity,
45918
46296
  locale: baseLocale
45919
46297
  }),
45920
46298
  [pointsWithPosition, thresholdMs, effectiveRange.granularity, baseLocale]
45921
46299
  );
45922
- const [expandedGroupIds, setExpandedGroupIds] = React37.useState(
46300
+ const [expandedGroupIds, setExpandedGroupIds] = React40.useState(
45923
46301
  () => /* @__PURE__ */ new Set()
45924
46302
  );
45925
- React37.useEffect(() => {
46303
+ React40.useEffect(() => {
45926
46304
  setExpandedGroupIds((prev) => {
45927
46305
  if (!prev || prev.size === 0) return prev;
45928
46306
  const validIds = new Set(
@@ -45937,7 +46315,7 @@ function Timeline({
45937
46315
  return changed ? next : prev;
45938
46316
  });
45939
46317
  }, [groupedEntries]);
45940
- const toggleGroup = React37.useCallback((groupId) => {
46318
+ const toggleGroup = React40.useCallback((groupId) => {
45941
46319
  setExpandedGroupIds((prev) => {
45942
46320
  const next = new Set(prev || []);
45943
46321
  if (next.has(groupId)) next.delete(groupId);
@@ -45960,7 +46338,7 @@ function Timeline({
45960
46338
  point2.id === activeId ? "is-active" : "",
45961
46339
  point2.highlight ? "is-highlighted" : ""
45962
46340
  ].filter(Boolean).join(" ");
45963
- const connector = /* @__PURE__ */ React37.createElement(
46341
+ const connector = /* @__PURE__ */ React40.createElement(
45964
46342
  TimelineConnector,
45965
46343
  {
45966
46344
  side: point2.side,
@@ -45968,9 +46346,9 @@ function Timeline({
45968
46346
  highlight: point2.highlight
45969
46347
  }
45970
46348
  );
45971
- const body = /* @__PURE__ */ React37.createElement("div", { className: "canopy-timeline__point-body" }, /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__point-date" }, point2.meta.label), /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__point-title" }, point2.title), point2.summary ? /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__point-summary" }, point2.summary) : null);
46349
+ const body = /* @__PURE__ */ React40.createElement("div", { className: "canopy-timeline__point-body" }, /* @__PURE__ */ React40.createElement("span", { className: "canopy-timeline__point-date" }, point2.meta.label), /* @__PURE__ */ React40.createElement("span", { className: "canopy-timeline__point-title" }, point2.title), point2.summary ? /* @__PURE__ */ React40.createElement("span", { className: "canopy-timeline__point-summary" }, point2.summary) : null);
45972
46350
  const resourceSection = renderResourceSection(point2);
45973
- return /* @__PURE__ */ React37.createElement(
46351
+ return /* @__PURE__ */ React40.createElement(
45974
46352
  "div",
45975
46353
  {
45976
46354
  key: point2.id,
@@ -45978,7 +46356,7 @@ function Timeline({
45978
46356
  style: wrapperStyle,
45979
46357
  role: "listitem"
45980
46358
  },
45981
- point2.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))
46359
+ point2.side === "left" ? /* @__PURE__ */ React40.createElement(React40.Fragment, null, /* @__PURE__ */ React40.createElement("div", { className: cardClasses }, body, resourceSection), connector) : /* @__PURE__ */ React40.createElement(React40.Fragment, null, connector, /* @__PURE__ */ React40.createElement("div", { className: cardClasses }, body, resourceSection))
45982
46360
  );
45983
46361
  }
45984
46362
  function renderGroupEntry(entry) {
@@ -45989,7 +46367,7 @@ function Timeline({
45989
46367
  const wrapperStyle = { top: `${entry.progress * 100}%` };
45990
46368
  const isExpanded = expandedGroupIds.has(entry.id);
45991
46369
  const hasActivePoint = entry.points.some((point2) => point2.id === activeId);
45992
- const connector = /* @__PURE__ */ React37.createElement(
46370
+ const connector = /* @__PURE__ */ React40.createElement(
45993
46371
  TimelineConnector,
45994
46372
  {
45995
46373
  side: entry.side,
@@ -46003,7 +46381,7 @@ function Timeline({
46003
46381
  hasActivePoint ? "is-active" : ""
46004
46382
  ].filter(Boolean).join(" ");
46005
46383
  const countLabel = `${entry.count} event${entry.count > 1 ? "s" : ""}`;
46006
- 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(
46384
+ const header = /* @__PURE__ */ React40.createElement("div", { className: "canopy-timeline__group-header" }, /* @__PURE__ */ React40.createElement("div", { className: "canopy-timeline__group-summary" }, /* @__PURE__ */ React40.createElement("span", { className: "canopy-timeline__point-date" }, entry.label), /* @__PURE__ */ React40.createElement("span", { className: "canopy-timeline__group-count" }, countLabel)), /* @__PURE__ */ React40.createElement(
46007
46385
  "button",
46008
46386
  {
46009
46387
  type: "button",
@@ -46013,7 +46391,7 @@ function Timeline({
46013
46391
  },
46014
46392
  isExpanded ? "Hide details" : "Show details"
46015
46393
  ));
46016
- const groupPoints = isExpanded ? /* @__PURE__ */ React37.createElement("div", { className: "canopy-timeline__group-points" }, entry.points.map((point2) => /* @__PURE__ */ React37.createElement(
46394
+ const groupPoints = isExpanded ? /* @__PURE__ */ React40.createElement("div", { className: "canopy-timeline__group-points" }, entry.points.map((point2) => /* @__PURE__ */ React40.createElement(
46017
46395
  "button",
46018
46396
  {
46019
46397
  key: point2.id,
@@ -46024,11 +46402,11 @@ function Timeline({
46024
46402
  ].filter(Boolean).join(" "),
46025
46403
  onClick: () => setActiveId(point2.id)
46026
46404
  },
46027
- /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__point-date" }, point2.meta.label),
46028
- /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__group-point-title" }, point2.title)
46405
+ /* @__PURE__ */ React40.createElement("span", { className: "canopy-timeline__point-date" }, point2.meta.label),
46406
+ /* @__PURE__ */ React40.createElement("span", { className: "canopy-timeline__group-point-title" }, point2.title)
46029
46407
  ))) : null;
46030
- const groupCard = /* @__PURE__ */ React37.createElement("div", { className: groupClasses }, header, groupPoints);
46031
- return /* @__PURE__ */ React37.createElement(
46408
+ const groupCard = /* @__PURE__ */ React40.createElement("div", { className: groupClasses }, header, groupPoints);
46409
+ return /* @__PURE__ */ React40.createElement(
46032
46410
  "div",
46033
46411
  {
46034
46412
  key: entry.id,
@@ -46036,17 +46414,17 @@ function Timeline({
46036
46414
  style: wrapperStyle,
46037
46415
  role: "listitem"
46038
46416
  },
46039
- entry.side === "left" ? /* @__PURE__ */ React37.createElement(React37.Fragment, null, groupCard, connector) : /* @__PURE__ */ React37.createElement(React37.Fragment, null, connector, groupCard)
46417
+ entry.side === "left" ? /* @__PURE__ */ React40.createElement(React40.Fragment, null, groupCard, connector) : /* @__PURE__ */ React40.createElement(React40.Fragment, null, connector, groupCard)
46040
46418
  );
46041
46419
  }
46042
- 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(
46420
+ return /* @__PURE__ */ React40.createElement("section", { className: containerClasses, ...rest }, title ? /* @__PURE__ */ React40.createElement("h2", { className: "canopy-timeline__title" }, title) : null, description ? /* @__PURE__ */ React40.createElement("p", { className: "canopy-timeline__description" }, description) : null, rangeLabel ? /* @__PURE__ */ React40.createElement("p", { className: "canopy-timeline__range", "aria-live": "polite" }, rangeLabel) : null, /* @__PURE__ */ React40.createElement("div", { className: "canopy-timeline__body" }, /* @__PURE__ */ React40.createElement(
46043
46421
  "div",
46044
46422
  {
46045
46423
  className: "canopy-timeline__list",
46046
46424
  role: "list",
46047
46425
  style: { minHeight: trackHeight }
46048
46426
  },
46049
- /* @__PURE__ */ React37.createElement("div", { className: "canopy-timeline__spine", "aria-hidden": "true" }),
46427
+ /* @__PURE__ */ React40.createElement("div", { className: "canopy-timeline__spine", "aria-hidden": "true" }),
46050
46428
  renderSteps(stepsValue, effectiveRange),
46051
46429
  groupedEntries.map((entry) => {
46052
46430
  if (entry.type === "group") return renderGroupEntry(entry);
@@ -46061,7 +46439,7 @@ function renderSteps(stepSize, range) {
46061
46439
  const markers = [];
46062
46440
  if (startYear < endYear) {
46063
46441
  markers.push(
46064
- /* @__PURE__ */ React37.createElement(
46442
+ /* @__PURE__ */ React40.createElement(
46065
46443
  "span",
46066
46444
  {
46067
46445
  key: "timeline-step-start",
@@ -46069,12 +46447,12 @@ function renderSteps(stepSize, range) {
46069
46447
  style: { top: "0%" },
46070
46448
  "aria-hidden": "true"
46071
46449
  },
46072
- /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__step-line" }),
46073
- /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__step-label" }, startYear)
46450
+ /* @__PURE__ */ React40.createElement("span", { className: "canopy-timeline__step-line" }),
46451
+ /* @__PURE__ */ React40.createElement("span", { className: "canopy-timeline__step-label" }, startYear)
46074
46452
  )
46075
46453
  );
46076
46454
  markers.push(
46077
- /* @__PURE__ */ React37.createElement(
46455
+ /* @__PURE__ */ React40.createElement(
46078
46456
  "span",
46079
46457
  {
46080
46458
  key: "timeline-step-end",
@@ -46082,8 +46460,8 @@ function renderSteps(stepSize, range) {
46082
46460
  style: { top: "100%" },
46083
46461
  "aria-hidden": "true"
46084
46462
  },
46085
- /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__step-line" }),
46086
- /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__step-label" }, endYear)
46463
+ /* @__PURE__ */ React40.createElement("span", { className: "canopy-timeline__step-line" }),
46464
+ /* @__PURE__ */ React40.createElement("span", { className: "canopy-timeline__step-label" }, endYear)
46087
46465
  )
46088
46466
  );
46089
46467
  }
@@ -46093,7 +46471,7 @@ function renderSteps(stepSize, range) {
46093
46471
  const progress = (timestamp - range.startDate.getTime()) / range.span;
46094
46472
  if (progress <= 0 || progress >= 1) continue;
46095
46473
  markers.push(
46096
- /* @__PURE__ */ React37.createElement(
46474
+ /* @__PURE__ */ React40.createElement(
46097
46475
  "span",
46098
46476
  {
46099
46477
  key: `timeline-step-${year}`,
@@ -46101,8 +46479,8 @@ function renderSteps(stepSize, range) {
46101
46479
  style: { top: `calc(${progress * 100}% - 0.5px)` },
46102
46480
  "aria-hidden": "true"
46103
46481
  },
46104
- /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__step-line" }),
46105
- /* @__PURE__ */ React37.createElement("span", { className: "canopy-timeline__step-label" }, year)
46482
+ /* @__PURE__ */ React40.createElement("span", { className: "canopy-timeline__step-line" }),
46483
+ /* @__PURE__ */ React40.createElement("span", { className: "canopy-timeline__step-label" }, year)
46106
46484
  )
46107
46485
  );
46108
46486
  }
@@ -46116,7 +46494,7 @@ function TimelinePoint() {
46116
46494
  TimelinePoint.displayName = "TimelinePoint";
46117
46495
 
46118
46496
  // ui/src/content/map/Map.jsx
46119
- import React38 from "react";
46497
+ import React41 from "react";
46120
46498
  import { createRoot } from "react-dom/client";
46121
46499
  var DEFAULT_TILE_LAYERS = [
46122
46500
  {
@@ -46182,7 +46560,7 @@ function waitForLeaflet(timeoutMs = 5e3) {
46182
46560
  poll();
46183
46561
  });
46184
46562
  }
46185
- function readBasePath3() {
46563
+ function readBasePath4() {
46186
46564
  const normalize = (val) => {
46187
46565
  if (!val) return "";
46188
46566
  const raw = String(val).trim();
@@ -46213,13 +46591,13 @@ function readBasePath3() {
46213
46591
  }
46214
46592
  return "";
46215
46593
  }
46216
- function withBasePath2(href) {
46594
+ function withBasePath3(href) {
46217
46595
  try {
46218
46596
  const raw = typeof href === "string" ? href.trim() : "";
46219
46597
  if (!raw) return raw;
46220
46598
  if (/^(?:[a-z][a-z0-9+.-]*:|\/\/|#)/i.test(raw)) return raw;
46221
46599
  if (!raw.startsWith("/")) return raw;
46222
- const base = readBasePath3();
46600
+ const base = readBasePath4();
46223
46601
  if (!base || base === "/") return raw;
46224
46602
  if (raw === base || raw.startsWith(`${base}/`)) return raw;
46225
46603
  return `${base}${raw}`;
@@ -46539,16 +46917,16 @@ function MapPopupContent({ marker }) {
46539
46917
  if (!marker) return null;
46540
46918
  const title = marker.title || marker.manifestTitle || "";
46541
46919
  const summary = marker.summary || marker.manifestSummary || "";
46542
- const href = marker.href ? withBasePath2(marker.href) : "";
46920
+ const href = marker.href ? withBasePath3(marker.href) : "";
46543
46921
  const thumbnail = marker.thumbnail || "";
46544
46922
  const thumbWidth = marker.thumbnailWidth;
46545
46923
  const thumbHeight = marker.thumbnailHeight;
46546
46924
  const manifestLinks = Array.isArray(marker.manifests) ? marker.manifests.filter((entry) => entry && (entry.href || entry.title)) : [];
46547
46925
  const normalizedManifests = manifestLinks.map((manifest) => ({
46548
46926
  ...manifest,
46549
- href: manifest.href ? withBasePath2(manifest.href) : manifest.href || ""
46927
+ href: manifest.href ? withBasePath3(manifest.href) : manifest.href || ""
46550
46928
  }));
46551
- return /* @__PURE__ */ React38.createElement("div", { className: "canopy-map__popup" }, thumbnail ? /* @__PURE__ */ React38.createElement("div", { className: "canopy-map__popup-media" }, /* @__PURE__ */ React38.createElement(
46929
+ return /* @__PURE__ */ React41.createElement("div", { className: "canopy-map__popup" }, thumbnail ? /* @__PURE__ */ React41.createElement("div", { className: "canopy-map__popup-media" }, /* @__PURE__ */ React41.createElement(
46552
46930
  "img",
46553
46931
  {
46554
46932
  src: thumbnail,
@@ -46557,19 +46935,19 @@ function MapPopupContent({ marker }) {
46557
46935
  width: typeof thumbWidth === "number" && thumbWidth > 0 ? thumbWidth : void 0,
46558
46936
  height: typeof thumbHeight === "number" && thumbHeight > 0 ? thumbHeight : void 0
46559
46937
  }
46560
- )) : null, /* @__PURE__ */ React38.createElement("div", { className: "canopy-map__popup-body" }, title ? href ? /* @__PURE__ */ React38.createElement("a", { href, className: "canopy-map__popup-title" }, title) : /* @__PURE__ */ React38.createElement("span", { className: "canopy-map__popup-title" }, title) : null, summary ? /* @__PURE__ */ React38.createElement("p", { className: "canopy-map__popup-summary" }, summary) : null, marker.detailsHtml ? /* @__PURE__ */ React38.createElement(
46938
+ )) : null, /* @__PURE__ */ React41.createElement("div", { className: "canopy-map__popup-body" }, title ? href ? /* @__PURE__ */ React41.createElement("a", { href, className: "canopy-map__popup-title" }, title) : /* @__PURE__ */ React41.createElement("span", { className: "canopy-map__popup-title" }, title) : null, summary ? /* @__PURE__ */ React41.createElement("p", { className: "canopy-map__popup-summary" }, summary) : null, marker.detailsHtml ? /* @__PURE__ */ React41.createElement(
46561
46939
  "div",
46562
46940
  {
46563
46941
  className: "canopy-map__popup-details",
46564
46942
  dangerouslySetInnerHTML: { __html: marker.detailsHtml }
46565
46943
  }
46566
- ) : null, !summary && !marker.detailsHtml && href && !title ? /* @__PURE__ */ React38.createElement("a", { href, className: "canopy-map__popup-link" }, "View item") : null, normalizedManifests.length ? /* @__PURE__ */ React38.createElement("div", { className: "canopy-map__popup-manifests" }, /* @__PURE__ */ React38.createElement("div", { className: "canopy-map__popup-manifests-list" }, normalizedManifests.map((manifest, index) => /* @__PURE__ */ React38.createElement(
46944
+ ) : null, !summary && !marker.detailsHtml && href && !title ? /* @__PURE__ */ React41.createElement("a", { href, className: "canopy-map__popup-link" }, "View item") : null, normalizedManifests.length ? /* @__PURE__ */ React41.createElement("div", { className: "canopy-map__popup-manifests" }, /* @__PURE__ */ React41.createElement("div", { className: "canopy-map__popup-manifests-list" }, normalizedManifests.map((manifest, index) => /* @__PURE__ */ React41.createElement(
46567
46945
  "div",
46568
46946
  {
46569
46947
  key: manifest.id || manifest.href || `manifest-${index}`,
46570
46948
  className: "canopy-map__popup-manifests-item"
46571
46949
  },
46572
- /* @__PURE__ */ React38.createElement(ReferencedManifestCard, { manifest })
46950
+ /* @__PURE__ */ React41.createElement(ReferencedManifestCard, { manifest })
46573
46951
  )))) : null));
46574
46952
  }
46575
46953
  function renderPopup(marker) {
@@ -46581,7 +46959,7 @@ function renderPopup(marker) {
46581
46959
  if (hadError) return;
46582
46960
  try {
46583
46961
  if (!root2) root2 = createRoot(container);
46584
- root2.render(/* @__PURE__ */ React38.createElement(MapPopupContent, { marker }));
46962
+ root2.render(/* @__PURE__ */ React41.createElement(MapPopupContent, { marker }));
46585
46963
  } catch (error) {
46586
46964
  hadError = true;
46587
46965
  if (root2) {
@@ -46763,26 +47141,26 @@ function Map3({
46763
47141
  defaultCenter = null,
46764
47142
  defaultZoom = null
46765
47143
  } = {}) {
46766
- const containerRef = React38.useRef(null);
46767
- const mapRef = React38.useRef(null);
46768
- const layerRef = React38.useRef(null);
46769
- const [leafletLib, setLeafletLib] = React38.useState(() => resolveGlobalLeaflet());
46770
- const [leafletError, setLeafletError] = React38.useState(null);
47144
+ const containerRef = React41.useRef(null);
47145
+ const mapRef = React41.useRef(null);
47146
+ const layerRef = React41.useRef(null);
47147
+ const [leafletLib, setLeafletLib] = React41.useState(() => resolveGlobalLeaflet());
47148
+ const [leafletError, setLeafletError] = React41.useState(null);
46771
47149
  const datasetInfo = navDataset && typeof navDataset === "object" ? navDataset : null;
46772
47150
  const datasetHref = datasetInfo && datasetInfo.href || "/api/navplace.json";
46773
47151
  const datasetVersion = datasetInfo && datasetInfo.version;
46774
47152
  const datasetHasFeatures = !!(datasetInfo && datasetInfo.hasFeatures);
46775
- const [navState, setNavState] = React38.useState(() => ({
47153
+ const [navState, setNavState] = React41.useState(() => ({
46776
47154
  loading: false,
46777
47155
  error: null,
46778
47156
  markers: []
46779
47157
  }));
46780
- const [iiifTargets, setIiifTargets] = React38.useState(() => ({
47158
+ const [iiifTargets, setIiifTargets] = React41.useState(() => ({
46781
47159
  loading: false,
46782
47160
  error: null,
46783
47161
  keys: []
46784
47162
  }));
46785
- React38.useEffect(() => {
47163
+ React41.useEffect(() => {
46786
47164
  if (!iiifContent) {
46787
47165
  setIiifTargets({ loading: false, error: null, keys: [] });
46788
47166
  return;
@@ -46803,7 +47181,7 @@ function Map3({
46803
47181
  }
46804
47182
  let cancelled = false;
46805
47183
  setIiifTargets({ loading: true, error: null, keys: [] });
46806
- const iiifUrl = withBasePath2(target);
47184
+ const iiifUrl = withBasePath3(target);
46807
47185
  fetch(iiifUrl).then((res) => {
46808
47186
  if (!res.ok) throw new Error(`Failed to load IIIF content (${res.status})`);
46809
47187
  return res.json();
@@ -46830,7 +47208,7 @@ function Map3({
46830
47208
  const navTargets = iiifTargets.keys || [];
46831
47209
  const navTargetsKey = navTargets.join("|");
46832
47210
  const shouldFetchNav = datasetHasFeatures && navTargets.length > 0;
46833
- React38.useEffect(() => {
47211
+ React41.useEffect(() => {
46834
47212
  if (!shouldFetchNav) {
46835
47213
  setNavState({ loading: false, error: null, markers: [] });
46836
47214
  return void 0;
@@ -46838,7 +47216,7 @@ function Map3({
46838
47216
  let cancelled = false;
46839
47217
  setNavState({ loading: true, error: null, markers: [] });
46840
47218
  const url = (() => {
46841
- const base = withBasePath2(datasetHref);
47219
+ const base = withBasePath3(datasetHref);
46842
47220
  if (!datasetVersion) return base;
46843
47221
  const joiner = base.includes("?") ? "&" : "?";
46844
47222
  return `${base}${joiner}v=${encodeURIComponent(datasetVersion)}`;
@@ -46862,7 +47240,7 @@ function Map3({
46862
47240
  cancelled = true;
46863
47241
  };
46864
47242
  }, [datasetHref, datasetVersion, navTargetsKey, shouldFetchNav]);
46865
- React38.useEffect(() => {
47243
+ React41.useEffect(() => {
46866
47244
  if (leafletLib) return;
46867
47245
  let cancelled = false;
46868
47246
  waitForLeaflet().then((lib) => {
@@ -46874,7 +47252,7 @@ function Map3({
46874
47252
  cancelled = true;
46875
47253
  };
46876
47254
  }, [leafletLib]);
46877
- const navMatchMap = React38.useMemo(() => {
47255
+ const navMatchMap = React41.useMemo(() => {
46878
47256
  const matchMap = createMarkerMap();
46879
47257
  (navState.markers || []).forEach((marker) => {
46880
47258
  if (!marker || !Array.isArray(marker.matchKeys)) return;
@@ -46885,7 +47263,7 @@ function Map3({
46885
47263
  });
46886
47264
  return matchMap;
46887
47265
  }, [navState.markers]);
46888
- const normalizedCustom = React38.useMemo(() => {
47266
+ const normalizedCustom = React41.useMemo(() => {
46889
47267
  return normalizeCustomMarkers(customPoints).map((point2) => {
46890
47268
  if (!point2 || point2.thumbnail || !point2.href) return point2;
46891
47269
  const match2 = navMatchMap.get(normalizeKey(point2.href));
@@ -46900,20 +47278,20 @@ function Map3({
46900
47278
  };
46901
47279
  });
46902
47280
  }, [customPoints, navMatchMap]);
46903
- const allMarkers = React38.useMemo(() => {
47281
+ const allMarkers = React41.useMemo(() => {
46904
47282
  return [...navState.markers || [], ...normalizedCustom];
46905
47283
  }, [navState.markers, normalizedCustom]);
46906
- const normalizedGeoReferences = React38.useMemo(
47284
+ const normalizedGeoReferences = React41.useMemo(
46907
47285
  () => normalizeGeoReferences(geoReferences),
46908
47286
  [geoReferences]
46909
47287
  );
46910
- const resolvedKeyInput = React38.useMemo(() => {
47288
+ const resolvedKeyInput = React41.useMemo(() => {
46911
47289
  if (Array.isArray(keyConfig) && keyConfig.length) return keyConfig;
46912
47290
  if (Array.isArray(mapKey) && mapKey.length) return mapKey;
46913
47291
  if (Array.isArray(legend) && legend.length) return legend;
46914
47292
  return [];
46915
47293
  }, [keyConfig, mapKey, legend]);
46916
- const normalizedLegendConfig = React38.useMemo(() => {
47294
+ const normalizedLegendConfig = React41.useMemo(() => {
46917
47295
  if (!Array.isArray(resolvedKeyInput) || !resolvedKeyInput.length) return [];
46918
47296
  return resolvedKeyInput.map((entry) => {
46919
47297
  if (!entry) return null;
@@ -46929,7 +47307,7 @@ function Map3({
46929
47307
  };
46930
47308
  }).filter(Boolean);
46931
47309
  }, [resolvedKeyInput]);
46932
- const markerKeyData = React38.useMemo(() => {
47310
+ const markerKeyData = React41.useMemo(() => {
46933
47311
  if (!normalizedLegendConfig.length) return { groups: [], metaMap: null };
46934
47312
  const metaMap = createMarkerMap();
46935
47313
  const palette = generateLegendColors(normalizedLegendConfig.length);
@@ -46950,11 +47328,11 @@ function Map3({
46950
47328
  }, [normalizedLegendConfig]);
46951
47329
  const markerKeyGroups = markerKeyData.groups;
46952
47330
  const markerKeyMetaMap = markerKeyData.metaMap;
46953
- const clusterOptions = React38.useMemo(
47331
+ const clusterOptions = React41.useMemo(
46954
47332
  () => buildClusterOptions(leafletLib, typeof maxClusterRadius === "number" ? maxClusterRadius : null),
46955
47333
  [leafletLib, maxClusterRadius]
46956
47334
  );
46957
- React38.useEffect(() => {
47335
+ React41.useEffect(() => {
46958
47336
  if (!containerRef.current || mapRef.current || !leafletLib) return void 0;
46959
47337
  const map = leafletLib.map(containerRef.current, {
46960
47338
  zoomControl: true,
@@ -46992,7 +47370,7 @@ function Map3({
46992
47370
  layerRef.current = null;
46993
47371
  };
46994
47372
  }, [tileLayers, disableTileLayers, scrollWheelZoom, cluster, clusterOptions, leafletLib]);
46995
- React38.useEffect(() => {
47373
+ React41.useEffect(() => {
46996
47374
  const map = mapRef.current;
46997
47375
  if (!map || !leafletLib) return void 0;
46998
47376
  if (!normalizedGeoReferences.length) return void 0;
@@ -47031,7 +47409,7 @@ function Map3({
47031
47409
  });
47032
47410
  };
47033
47411
  }, [leafletLib, normalizedGeoReferences]);
47034
- React38.useEffect(() => {
47412
+ React41.useEffect(() => {
47035
47413
  const map = mapRef.current;
47036
47414
  const layer = layerRef.current;
47037
47415
  if (!map || !layer || !leafletLib) return;
@@ -47169,16 +47547,16 @@ function Map3({
47169
47547
  ].filter(Boolean).join(" ");
47170
47548
  const statusLabel = leafletError ? leafletError.message || "Failed to load map library" : !leafletLib ? "Loading map\u2026" : iiifTargets.error ? iiifTargets.error : datasetUnavailable ? "Map data is unavailable for this site." : navState.error ? navState.error : isLoadingMarkers ? "Loading map data\u2026" : !iiifContent && !hasCustomPoints && !hasGeoReferences ? "Add iiifContent or MapPoint markers to populate this map." : !hasMarkers && !hasGeoReferences ? "No map locations available." : "";
47171
47549
  const showStatus = Boolean(statusLabel);
47172
- const mapElement = /* @__PURE__ */ React38.createElement("div", { className: rootClass, id: id || void 0, style: style || void 0 }, /* @__PURE__ */ React38.createElement(
47550
+ const mapElement = /* @__PURE__ */ React41.createElement("div", { className: rootClass, id: id || void 0, style: style || void 0 }, /* @__PURE__ */ React41.createElement(
47173
47551
  "div",
47174
47552
  {
47175
47553
  ref: containerRef,
47176
47554
  className: "canopy-map__canvas",
47177
47555
  style: { height: height || "600px" }
47178
47556
  }
47179
- ), showStatus ? /* @__PURE__ */ React38.createElement("div", { className: "canopy-map__overlays" }, /* @__PURE__ */ React38.createElement("div", { className: "canopy-map__status", "aria-live": "polite" }, statusLabel)) : null);
47557
+ ), showStatus ? /* @__PURE__ */ React41.createElement("div", { className: "canopy-map__overlays" }, /* @__PURE__ */ React41.createElement("div", { className: "canopy-map__status", "aria-live": "polite" }, statusLabel)) : null);
47180
47558
  if (!hasKey) return mapElement;
47181
- return /* @__PURE__ */ React38.createElement(React38.Fragment, null, mapElement, /* @__PURE__ */ React38.createElement("div", { className: "canopy-map__key", "aria-label": "Map key" }, /* @__PURE__ */ React38.createElement("ul", { className: "canopy-map__key-list" }, markerKeyGroups.map((group) => /* @__PURE__ */ React38.createElement("li", { key: group.label, className: "canopy-map__key-item" }, /* @__PURE__ */ React38.createElement(
47559
+ return /* @__PURE__ */ React41.createElement(React41.Fragment, null, mapElement, /* @__PURE__ */ React41.createElement("div", { className: "canopy-map__key", "aria-label": "Map key" }, /* @__PURE__ */ React41.createElement("ul", { className: "canopy-map__key-list" }, markerKeyGroups.map((group) => /* @__PURE__ */ React41.createElement("li", { key: group.label, className: "canopy-map__key-item" }, /* @__PURE__ */ React41.createElement(
47182
47560
  "span",
47183
47561
  {
47184
47562
  className: [
@@ -47188,7 +47566,7 @@ function Map3({
47188
47566
  "aria-hidden": "true",
47189
47567
  style: { backgroundColor: group.color || void 0 }
47190
47568
  }
47191
- ), /* @__PURE__ */ React38.createElement("span", { className: "canopy-map__key-label" }, group.label))))));
47569
+ ), /* @__PURE__ */ React41.createElement("span", { className: "canopy-map__key-label" }, group.label))))));
47192
47570
  }
47193
47571
 
47194
47572
  // ui/src/content/map/MapPoint.jsx
@@ -47198,10 +47576,10 @@ function MapPoint() {
47198
47576
  MapPoint.displayName = "MapPoint";
47199
47577
 
47200
47578
  // ui/src/content/gallery/Gallery.jsx
47201
- import React40 from "react";
47579
+ import React43 from "react";
47202
47580
 
47203
47581
  // ui/src/utils/manifestReferences.js
47204
- import React39 from "react";
47582
+ import React42 from "react";
47205
47583
  var CONTEXT_KEY2 = typeof Symbol === "function" ? Symbol.for("__CANOPY_PAGE_CONTEXT__") : "__CANOPY_PAGE_CONTEXT__";
47206
47584
  function getGlobalRoot() {
47207
47585
  if (typeof globalThis !== "undefined") return globalThis;
@@ -47212,7 +47590,7 @@ function getGlobalRoot() {
47212
47590
  function getPageContext() {
47213
47591
  const root2 = getGlobalRoot();
47214
47592
  if (root2 && root2[CONTEXT_KEY2]) return root2[CONTEXT_KEY2];
47215
- const ctx = React39.createContext({
47593
+ const ctx = React42.createContext({
47216
47594
  navigation: null,
47217
47595
  page: null,
47218
47596
  site: null,
@@ -47236,7 +47614,7 @@ function normalizeManifestId(raw) {
47236
47614
  return String(raw || "").trim();
47237
47615
  }
47238
47616
  }
47239
- var PageContextFallback = React39.createContext(null);
47617
+ var PageContextFallback = React42.createContext(null);
47240
47618
  var referencedModule = null;
47241
47619
  var REFERENCED_SPEC = "@canopy-iiif/app/lib/components/referenced.js";
47242
47620
  function getReferencedModule() {
@@ -47262,9 +47640,9 @@ function getReferencedModule() {
47262
47640
  }
47263
47641
  function useReferencedManifestMap() {
47264
47642
  const PageContext = getPageContext() || PageContextFallback;
47265
- const pageContext = React39.useContext(PageContext);
47643
+ const pageContext = React42.useContext(PageContext);
47266
47644
  const referencedItems = pageContext && pageContext.page && Array.isArray(pageContext.page.referencedItems) ? pageContext.page.referencedItems : [];
47267
- return React39.useMemo(() => {
47645
+ return React42.useMemo(() => {
47268
47646
  const map = /* @__PURE__ */ new Map();
47269
47647
  referencedItems.forEach((item) => {
47270
47648
  if (!item) return;
@@ -47578,8 +47956,19 @@ var INLINE_SCRIPT = `(() => {
47578
47956
  const navOptions = optionNodes ? Array.prototype.slice.call(optionNodes) : [];
47579
47957
  if (!navOptions.length) return;
47580
47958
  nav.setAttribute('data-canopy-gallery-nav-bound', '1');
47581
- const prevBtn = nav.querySelector('[data-canopy-gallery-nav-prev]');
47582
- const nextBtn = nav.querySelector('[data-canopy-gallery-nav-next]');
47959
+ const navModal = nav.closest('[data-canopy-gallery-modal]');
47960
+ const prevBtn =
47961
+ nav.querySelector('[data-canopy-gallery-nav-prev]') ||
47962
+ (navModal &&
47963
+ navModal.querySelector(
47964
+ '.canopy-gallery__modal-panel [data-canopy-gallery-nav-prev]'
47965
+ ));
47966
+ const nextBtn =
47967
+ nav.querySelector('[data-canopy-gallery-nav-next]') ||
47968
+ (navModal &&
47969
+ navModal.querySelector(
47970
+ '.canopy-gallery__modal-panel [data-canopy-gallery-nav-next]'
47971
+ ));
47583
47972
 
47584
47973
  function updateButtons() {
47585
47974
  if (prevBtn) prevBtn.disabled = false;
@@ -47859,7 +48248,7 @@ function shuffleItems(list) {
47859
48248
  function renderMetaList(meta, className) {
47860
48249
  const entries = ensureArray4(meta).filter((entry) => entry || entry === 0);
47861
48250
  if (!entries.length) return null;
47862
- return /* @__PURE__ */ React40.createElement("ul", { className, role: "list" }, entries.map((entry, index) => /* @__PURE__ */ React40.createElement("li", { key: `meta-${index}` }, entry)));
48251
+ return /* @__PURE__ */ React43.createElement("ul", { className, role: "list" }, entries.map((entry, index) => /* @__PURE__ */ React43.createElement("li", { key: `meta-${index}` }, entry)));
47863
48252
  }
47864
48253
  function renderPreview(props = {}) {
47865
48254
  const source = typeof props.media === "string" && props.media || props.thumbnail || props.src || props.image && props.image.src || props.image;
@@ -47867,7 +48256,7 @@ function renderPreview(props = {}) {
47867
48256
  const alt = props.thumbnailAlt || props.imageAlt || props.alt || props.title || "";
47868
48257
  const width = props.thumbnailWidth || props.imageWidth || props.width;
47869
48258
  const height = props.thumbnailHeight || props.imageHeight || props.height;
47870
- return /* @__PURE__ */ React40.createElement(
48259
+ return /* @__PURE__ */ React43.createElement(
47871
48260
  "img",
47872
48261
  {
47873
48262
  src: source,
@@ -47878,11 +48267,11 @@ function renderPreview(props = {}) {
47878
48267
  }
47879
48268
  );
47880
48269
  }
47881
- return /* @__PURE__ */ React40.createElement("div", { className: "canopy-gallery__placeholder", "aria-hidden": "true" });
48270
+ return /* @__PURE__ */ React43.createElement("div", { className: "canopy-gallery__placeholder", "aria-hidden": "true" });
47882
48271
  }
47883
48272
  function normalizeItem(child, index, galleryId, manifestMap) {
47884
48273
  var _a2;
47885
- if (!React40.isValidElement(child)) return null;
48274
+ if (!React43.isValidElement(child)) return null;
47886
48275
  if (child.type !== GalleryItem && ((_a2 = child.type) == null ? void 0 : _a2.displayName) !== "GalleryItem")
47887
48276
  return null;
47888
48277
  const props = child.props || {};
@@ -47957,7 +48346,7 @@ function buildCaptionContent(itemProps) {
47957
48346
  if (itemProps.caption) return itemProps.caption;
47958
48347
  const kicker = itemProps.kicker || itemProps.label || itemProps.eyebrow;
47959
48348
  const summary = itemProps.summary || itemProps.description;
47960
- 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, summary ? /* @__PURE__ */ React40.createElement("span", { className: "canopy-gallery__summary" }, summary) : null, renderMetaList(
48349
+ return /* @__PURE__ */ React43.createElement(React43.Fragment, null, kicker ? /* @__PURE__ */ React43.createElement("span", { className: "canopy-gallery__kicker" }, kicker) : null, itemProps.title ? /* @__PURE__ */ React43.createElement("span", { className: "canopy-gallery__title-text" }, itemProps.title) : null, summary ? /* @__PURE__ */ React43.createElement("span", { className: "canopy-gallery__summary" }, summary) : null, renderMetaList(
47961
48350
  itemProps.meta,
47962
48351
  "canopy-gallery__meta canopy-gallery__meta--caption"
47963
48352
  ));
@@ -47975,7 +48364,7 @@ function GalleryModal({ item, closeTargetId, navItems, navGroupName }) {
47975
48364
  const kicker = props.kicker || props.label || props.eyebrow;
47976
48365
  const summary = props.popupDescription || props.modalDescription || props.description || props.summary || null;
47977
48366
  const modalTitle = props.popupTitle || props.modalTitle || props.title || `Item ${index + 1}`;
47978
- return /* @__PURE__ */ React40.createElement(
48367
+ return /* @__PURE__ */ React43.createElement(
47979
48368
  "div",
47980
48369
  {
47981
48370
  id: modalId,
@@ -47988,22 +48377,58 @@ function GalleryModal({ item, closeTargetId, navItems, navGroupName }) {
47988
48377
  "data-canopy-gallery-modal": "true",
47989
48378
  "data-canopy-gallery-close": closeTargetId
47990
48379
  },
47991
- /* @__PURE__ */ React40.createElement("div", { className: "canopy-gallery__modal-scrim" }, /* @__PURE__ */ React40.createElement("div", { className: "canopy-gallery__modal-panel" }, /* @__PURE__ */ React40.createElement("div", { className: "canopy-gallery__modal-actions" }, /* @__PURE__ */ React40.createElement(
48380
+ /* @__PURE__ */ React43.createElement("div", { className: "canopy-gallery__modal-scrim" }, /* @__PURE__ */ React43.createElement("div", { className: "canopy-gallery__modal-actions" }, /* @__PURE__ */ React43.createElement(
47992
48381
  GalleryThumbnailNav,
47993
48382
  {
47994
48383
  items: navItems,
47995
48384
  activeModalId: modalId,
47996
48385
  groupName: `${navGroupName || "canopy-gallery"}-${modalId}`
47997
48386
  }
47998
- ), /* @__PURE__ */ React40.createElement(
48387
+ ), /* @__PURE__ */ React43.createElement(
47999
48388
  "a",
48000
48389
  {
48001
48390
  className: "canopy-gallery__modal-close",
48002
48391
  href: `#${closeTargetId}`,
48003
48392
  "aria-label": `Close popup for ${modalTitle}`
48004
48393
  },
48005
- "Close"
48006
- )), /* @__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), summary ? /* @__PURE__ */ React40.createElement(
48394
+ "X"
48395
+ )), /* @__PURE__ */ React43.createElement("div", { className: "canopy-gallery__modal-panel" }, /* @__PURE__ */ React43.createElement(
48396
+ "button",
48397
+ {
48398
+ type: "button",
48399
+ className: "canopy-gallery__nav-button canopy-gallery__nav-button--prev",
48400
+ "aria-label": "Scroll left through gallery thumbnails",
48401
+ "data-canopy-gallery-nav-prev": "true"
48402
+ },
48403
+ /* @__PURE__ */ React43.createElement(
48404
+ "span",
48405
+ {
48406
+ className: "canopy-gallery__nav-button-icon",
48407
+ "aria-hidden": "true",
48408
+ role: "presentation"
48409
+ },
48410
+ "<"
48411
+ ),
48412
+ /* @__PURE__ */ React43.createElement("span", { className: "canopy-gallery__visually-hidden" }, "Previous item")
48413
+ ), /* @__PURE__ */ React43.createElement(
48414
+ "button",
48415
+ {
48416
+ type: "button",
48417
+ className: "canopy-gallery__nav-button canopy-gallery__nav-button--next",
48418
+ "aria-label": "Scroll right through gallery thumbnails",
48419
+ "data-canopy-gallery-nav-next": "true"
48420
+ },
48421
+ /* @__PURE__ */ React43.createElement(
48422
+ "span",
48423
+ {
48424
+ className: "canopy-gallery__nav-button-icon",
48425
+ "aria-hidden": "true",
48426
+ role: "presentation"
48427
+ },
48428
+ ">"
48429
+ ),
48430
+ /* @__PURE__ */ React43.createElement("span", { className: "canopy-gallery__visually-hidden" }, "Next item")
48431
+ ), /* @__PURE__ */ React43.createElement("header", { className: "canopy-gallery__modal-header" }, /* @__PURE__ */ React43.createElement("div", { className: "canopy-gallery__modal-text" }, kicker ? /* @__PURE__ */ React43.createElement("p", { className: "canopy-gallery__modal-kicker" }, kicker) : null, /* @__PURE__ */ React43.createElement("h3", { id: modalTitleId, className: "canopy-gallery__modal-title" }, modalTitle), summary ? /* @__PURE__ */ React43.createElement(
48007
48432
  "p",
48008
48433
  {
48009
48434
  id: modalDescriptionId || void 0,
@@ -48013,20 +48438,20 @@ function GalleryModal({ item, closeTargetId, navItems, navGroupName }) {
48013
48438
  ) : null, renderMetaList(
48014
48439
  props.meta,
48015
48440
  "canopy-gallery__meta canopy-gallery__meta--modal"
48016
- ))), /* @__PURE__ */ React40.createElement("div", { className: "canopy-gallery__modal-body" }, props.children, manifests && manifests.length ? /* @__PURE__ */ React40.createElement("section", { className: "canopy-gallery__referenced" }, /* @__PURE__ */ React40.createElement("h4", null, "Referenced works"), /* @__PURE__ */ React40.createElement("ul", { role: "list" }, manifests.map((manifest) => /* @__PURE__ */ React40.createElement("li", { key: manifest.id || manifest.href }, /* @__PURE__ */ React40.createElement("a", { href: manifest.href }, manifest.title || manifest.href))))) : null)))
48441
+ ), manifests && manifests.length ? manifests.map((manifest) => /* @__PURE__ */ React43.createElement("a", { key: manifest.id || manifest.href, href: manifest.href }, manifest.title || manifest.href)) : null)), /* @__PURE__ */ React43.createElement("div", { className: "canopy-gallery__modal-body" }, props.children)))
48017
48442
  );
48018
48443
  }
48019
48444
  function GalleryFigure({ item }) {
48020
48445
  const { props, modalId, triggerLabel } = item;
48021
- return /* @__PURE__ */ React40.createElement(
48446
+ return /* @__PURE__ */ React43.createElement(
48022
48447
  "figure",
48023
48448
  {
48024
48449
  className: "canopy-gallery__item",
48025
48450
  "data-gallery-item-index": item.index
48026
48451
  },
48027
- /* @__PURE__ */ React40.createElement("div", { className: "canopy-gallery__media" }, renderPreview(props)),
48028
- /* @__PURE__ */ React40.createElement("figcaption", { className: "canopy-gallery__caption" }, buildCaptionContent(props)),
48029
- /* @__PURE__ */ React40.createElement(
48452
+ /* @__PURE__ */ React43.createElement("div", { className: "canopy-gallery__media" }, renderPreview(props)),
48453
+ /* @__PURE__ */ React43.createElement("figcaption", { className: "canopy-gallery__caption" }, buildCaptionContent(props)),
48454
+ /* @__PURE__ */ React43.createElement(
48030
48455
  "a",
48031
48456
  {
48032
48457
  className: "canopy-gallery__trigger",
@@ -48036,27 +48461,27 @@ function GalleryFigure({ item }) {
48036
48461
  "aria-label": triggerLabel,
48037
48462
  "data-canopy-gallery-trigger": modalId
48038
48463
  },
48039
- /* @__PURE__ */ React40.createElement("span", { className: "canopy-gallery__trigger-label" }, triggerLabel)
48464
+ /* @__PURE__ */ React43.createElement("span", { className: "canopy-gallery__trigger-label" }, triggerLabel)
48040
48465
  )
48041
48466
  );
48042
48467
  }
48043
48468
  function GalleryThumbnailNav({ items, activeModalId, groupName }) {
48044
48469
  if (!items || items.length < 2) return null;
48045
48470
  const radioGroup = groupName || "canopy-gallery-nav";
48046
- return /* @__PURE__ */ React40.createElement(
48471
+ return /* @__PURE__ */ React43.createElement(
48047
48472
  "nav",
48048
48473
  {
48049
48474
  className: "canopy-gallery__nav",
48050
48475
  "aria-label": "Gallery navigation",
48051
48476
  "data-canopy-gallery-nav": "true"
48052
48477
  },
48053
- /* @__PURE__ */ React40.createElement(
48478
+ /* @__PURE__ */ React43.createElement(
48054
48479
  "div",
48055
48480
  {
48056
48481
  className: "canopy-gallery__nav-viewport",
48057
48482
  "data-canopy-gallery-nav-viewport": "true"
48058
48483
  },
48059
- /* @__PURE__ */ React40.createElement(
48484
+ /* @__PURE__ */ React43.createElement(
48060
48485
  "ul",
48061
48486
  {
48062
48487
  className: "canopy-gallery__nav-list",
@@ -48066,7 +48491,7 @@ function GalleryThumbnailNav({ items, activeModalId, groupName }) {
48066
48491
  items.map((item, index) => {
48067
48492
  const optionId = `${radioGroup}-${item.modalId || index}`;
48068
48493
  const isActive = item.modalId === activeModalId;
48069
- return /* @__PURE__ */ React40.createElement(
48494
+ return /* @__PURE__ */ React43.createElement(
48070
48495
  "li",
48071
48496
  {
48072
48497
  key: `${item.key}-nav`,
@@ -48074,7 +48499,7 @@ function GalleryThumbnailNav({ items, activeModalId, groupName }) {
48074
48499
  "data-canopy-gallery-nav-item": "true",
48075
48500
  "data-canopy-gallery-nav-selected": isActive ? "1" : void 0
48076
48501
  },
48077
- /* @__PURE__ */ React40.createElement(
48502
+ /* @__PURE__ */ React43.createElement(
48078
48503
  "input",
48079
48504
  {
48080
48505
  type: "radio",
@@ -48090,57 +48515,20 @@ function GalleryThumbnailNav({ items, activeModalId, groupName }) {
48090
48515
  "data-canopy-gallery-nav-selected": isActive ? "1" : void 0
48091
48516
  }
48092
48517
  ),
48093
- /* @__PURE__ */ React40.createElement(
48518
+ /* @__PURE__ */ React43.createElement(
48094
48519
  "label",
48095
48520
  {
48096
48521
  className: "canopy-gallery__nav-link",
48097
48522
  htmlFor: optionId,
48098
48523
  "data-canopy-gallery-nav-active": isActive ? "1" : void 0
48099
48524
  },
48100
- /* @__PURE__ */ React40.createElement("span", { className: "canopy-gallery__nav-thumb" }, renderPreview(item.props)),
48101
- /* @__PURE__ */ React40.createElement("span", { className: "canopy-gallery__nav-label" }, item.props.title || `Item ${item.index + 1}`)
48525
+ /* @__PURE__ */ React43.createElement("span", { className: "canopy-gallery__nav-thumb" }, renderPreview(item.props)),
48526
+ /* @__PURE__ */ React43.createElement("span", { className: "canopy-gallery__nav-label" }, item.props.title || `Item ${item.index + 1}`)
48102
48527
  )
48103
48528
  );
48104
48529
  })
48105
48530
  )
48106
- ),
48107
- /* @__PURE__ */ React40.createElement("div", { className: "canopy-gallery__nav-controls" }, /* @__PURE__ */ React40.createElement(
48108
- "button",
48109
- {
48110
- type: "button",
48111
- className: "canopy-gallery__nav-button canopy-gallery__nav-button--prev",
48112
- "aria-label": "Scroll left through gallery thumbnails",
48113
- "data-canopy-gallery-nav-prev": "true"
48114
- },
48115
- /* @__PURE__ */ React40.createElement(
48116
- "span",
48117
- {
48118
- className: "canopy-gallery__nav-button-icon",
48119
- "aria-hidden": "true",
48120
- role: "presentation"
48121
- },
48122
- "<"
48123
- ),
48124
- /* @__PURE__ */ React40.createElement("span", { className: "canopy-gallery__visually-hidden" }, "Previous item")
48125
- ), /* @__PURE__ */ React40.createElement(
48126
- "button",
48127
- {
48128
- type: "button",
48129
- className: "canopy-gallery__nav-button canopy-gallery__nav-button--next",
48130
- "aria-label": "Scroll right through gallery thumbnails",
48131
- "data-canopy-gallery-nav-next": "true"
48132
- },
48133
- /* @__PURE__ */ React40.createElement(
48134
- "span",
48135
- {
48136
- className: "canopy-gallery__nav-button-icon",
48137
- "aria-hidden": "true",
48138
- role: "presentation"
48139
- },
48140
- ">"
48141
- ),
48142
- /* @__PURE__ */ React40.createElement("span", { className: "canopy-gallery__visually-hidden" }, "Next item")
48143
- ))
48531
+ )
48144
48532
  );
48145
48533
  }
48146
48534
  function GalleryContent({ children, flex = false }) {
@@ -48148,7 +48536,7 @@ function GalleryContent({ children, flex = false }) {
48148
48536
  "canopy-gallery-item__content",
48149
48537
  flex ? "canopy-gallery-item__content_flex" : null
48150
48538
  ].filter(Boolean).join(" ");
48151
- return /* @__PURE__ */ React40.createElement("div", { className: contentClassName }, children);
48539
+ return /* @__PURE__ */ React43.createElement("div", { className: contentClassName }, children);
48152
48540
  }
48153
48541
  function GalleryItem() {
48154
48542
  return null;
@@ -48172,7 +48560,7 @@ function Gallery({
48172
48560
  const galleryId = id ? String(id) : nextGalleryInstanceId();
48173
48561
  const HeadingTag = "h3";
48174
48562
  const closeTargetId = `${galleryId}-close`;
48175
- const childArray = React40.Children.toArray(children);
48563
+ const childArray = React43.Children.toArray(children);
48176
48564
  const items = childArray.map((child, index) => normalizeItem(child, index, galleryId, manifestMap)).filter(Boolean);
48177
48565
  if (!items.length) return null;
48178
48566
  const popupMode = normalizePopupSize(popupSize);
@@ -48184,7 +48572,7 @@ function Gallery({
48184
48572
  className
48185
48573
  ].filter(Boolean).join(" ");
48186
48574
  const navGroupName = `${galleryId}-nav`;
48187
- return /* @__PURE__ */ React40.createElement("section", { className: rootClassName, style, "data-canopy-gallery": "true" }, /* @__PURE__ */ React40.createElement(
48575
+ return /* @__PURE__ */ React43.createElement("section", { className: rootClassName, style, "data-canopy-gallery": "true" }, /* @__PURE__ */ React43.createElement(
48188
48576
  "div",
48189
48577
  {
48190
48578
  id: closeTargetId,
@@ -48192,7 +48580,7 @@ function Gallery({
48192
48580
  "aria-hidden": "true",
48193
48581
  tabIndex: -1
48194
48582
  }
48195
- ), (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(
48583
+ ), (title || description) && /* @__PURE__ */ React43.createElement("div", { className: "canopy-gallery__header" }, title ? /* @__PURE__ */ React43.createElement(HeadingTag, { className: "canopy-gallery__heading" }, title) : null, description ? /* @__PURE__ */ React43.createElement("p", { className: "canopy-gallery__description" }, description) : null), /* @__PURE__ */ React43.createElement("div", { className: "canopy-gallery__grid" }, orderedItems.map((item) => /* @__PURE__ */ React43.createElement(GalleryFigure, { key: item.key, item }))), /* @__PURE__ */ React43.createElement("div", { className: "canopy-gallery__modals" }, orderedItems.map((item) => /* @__PURE__ */ React43.createElement(
48196
48584
  GalleryModal,
48197
48585
  {
48198
48586
  key: `${item.modalId}-modal`,
@@ -48201,7 +48589,7 @@ function Gallery({
48201
48589
  navItems: orderedItems,
48202
48590
  navGroupName
48203
48591
  }
48204
- ))), /* @__PURE__ */ React40.createElement(
48592
+ ))), /* @__PURE__ */ React43.createElement(
48205
48593
  "script",
48206
48594
  {
48207
48595
  "data-canopy-gallery-script": "true",
@@ -48233,6 +48621,7 @@ export {
48233
48621
  Id,
48234
48622
  Image,
48235
48623
  ImageStory,
48624
+ LanguageToggle,
48236
48625
  Map3 as Map,
48237
48626
  MapPoint,
48238
48627
  MdxRelatedItems as RelatedItems,