@canopy-iiif/app 1.2.2 → 1.2.4

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.
@@ -2105,8 +2105,22 @@ function TeaserCard({
2105
2105
  );
2106
2106
  }
2107
2107
 
2108
- // ui/src/layout/Container.jsx
2108
+ // ui/src/layout/GoogleAnalytics.jsx
2109
2109
  import React22 from "react";
2110
+ var GA_HOST = "https://www.googletagmanager.com/gtag/js";
2111
+ function GoogleAnalytics({ id }) {
2112
+ if (!id) return null;
2113
+ const inlineConfig = `
2114
+ window.dataLayer = window.dataLayer || [];
2115
+ function gtag(){window.dataLayer.push(arguments);}
2116
+ gtag('js', new Date());
2117
+ gtag('config', '${id}');
2118
+ `;
2119
+ return /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement("script", { async: true, src: `${GA_HOST}?id=${encodeURIComponent(id)}` }), /* @__PURE__ */ React22.createElement("script", { dangerouslySetInnerHTML: { __html: inlineConfig } }));
2120
+ }
2121
+
2122
+ // ui/src/layout/Container.jsx
2123
+ import React23 from "react";
2110
2124
  function Container({
2111
2125
  className = "",
2112
2126
  variant = "content",
@@ -2115,7 +2129,7 @@ function Container({
2115
2129
  }) {
2116
2130
  const variantClass = variant === "wide" ? "max-w-wide" : "max-w-content";
2117
2131
  const classes = ["mx-auto", variantClass, "w-full", className].filter(Boolean).join(" ");
2118
- return /* @__PURE__ */ React22.createElement(
2132
+ return /* @__PURE__ */ React23.createElement(
2119
2133
  "div",
2120
2134
  {
2121
2135
  className: classes,
@@ -2127,7 +2141,7 @@ function Container({
2127
2141
  }
2128
2142
 
2129
2143
  // ui/src/layout/Card.jsx
2130
- import React23, { useEffect as useEffect5, useRef, useState as useState5 } from "react";
2144
+ import React24, { useEffect as useEffect5, useRef, useState as useState5 } from "react";
2131
2145
  var DEFAULT_CARD_ASPECT_RATIO = 4 / 3;
2132
2146
  function Card({
2133
2147
  href,
@@ -2191,8 +2205,8 @@ function Card({
2191
2205
  const hasDimensions = Number.isFinite(w) && w > 0 && Number.isFinite(h) && h > 0;
2192
2206
  const ratio = hasAspectRatio ? Number(aspectRatio) : hasDimensions ? w / h : src ? DEFAULT_CARD_ASPECT_RATIO : void 0;
2193
2207
  const paddingPercent = ratio ? 100 / ratio : 100;
2194
- const caption = /* @__PURE__ */ React23.createElement("figcaption", null, title && /* @__PURE__ */ React23.createElement("span", null, title), subtitle && /* @__PURE__ */ React23.createElement("span", null, subtitle), children);
2195
- return /* @__PURE__ */ React23.createElement(
2208
+ const caption = /* @__PURE__ */ React24.createElement("figcaption", null, title && /* @__PURE__ */ React24.createElement("span", null, title), subtitle && /* @__PURE__ */ React24.createElement("span", null, subtitle), children);
2209
+ return /* @__PURE__ */ React24.createElement(
2196
2210
  "a",
2197
2211
  {
2198
2212
  href,
@@ -2204,13 +2218,13 @@ function Card({
2204
2218
  "data-image-loaded": imageLoaded ? "true" : "false",
2205
2219
  ...rest
2206
2220
  },
2207
- /* @__PURE__ */ React23.createElement("figure", null, src ? ratio ? /* @__PURE__ */ React23.createElement(
2221
+ /* @__PURE__ */ React24.createElement("figure", null, src ? ratio ? /* @__PURE__ */ React24.createElement(
2208
2222
  "div",
2209
2223
  {
2210
2224
  className: "canopy-card-media",
2211
2225
  style: { "--canopy-card-padding": `${paddingPercent}%` }
2212
2226
  },
2213
- inView ? /* @__PURE__ */ React23.createElement(
2227
+ inView ? /* @__PURE__ */ React24.createElement(
2214
2228
  "img",
2215
2229
  {
2216
2230
  src,
@@ -2220,7 +2234,7 @@ function Card({
2220
2234
  onError: () => setImageLoaded(true)
2221
2235
  }
2222
2236
  ) : null
2223
- ) : /* @__PURE__ */ React23.createElement(
2237
+ ) : /* @__PURE__ */ React24.createElement(
2224
2238
  "img",
2225
2239
  {
2226
2240
  src,
@@ -2235,13 +2249,13 @@ function Card({
2235
2249
  }
2236
2250
 
2237
2251
  // ui/src/content/ReferencedItems.jsx
2238
- import React24 from "react";
2252
+ import React25 from "react";
2239
2253
  import navigationHelpers4 from "@canopy-iiif/app/lib/components/navigation.js";
2240
2254
  function useReferencedItems(itemsProp) {
2241
2255
  if (Array.isArray(itemsProp)) return itemsProp;
2242
2256
  const PageContext = navigationHelpers4 && typeof navigationHelpers4.getPageContext === "function" ? navigationHelpers4.getPageContext() : null;
2243
2257
  if (!PageContext) return [];
2244
- const context = React24.useContext(PageContext);
2258
+ const context = React25.useContext(PageContext);
2245
2259
  const items = context && context.page ? context.page.referencedItems : null;
2246
2260
  return Array.isArray(items) ? items : [];
2247
2261
  }
@@ -2261,13 +2275,13 @@ function ReferencedItems({
2261
2275
  "referenced-items--empty",
2262
2276
  className
2263
2277
  ].filter(Boolean).join(" ");
2264
- return /* @__PURE__ */ React24.createElement("div", { className: emptyClass, ...rest }, typeof emptyLabel === "function" ? emptyLabel() : emptyLabel);
2278
+ return /* @__PURE__ */ React25.createElement("div", { className: emptyClass, ...rest }, typeof emptyLabel === "function" ? emptyLabel() : emptyLabel);
2265
2279
  }
2266
2280
  const containerClassName = ["referenced-items", className].filter(Boolean).join(" ");
2267
- return /* @__PURE__ */ React24.createElement("section", { className: containerClassName, ...rest }, children, /* @__PURE__ */ React24.createElement("div", { className: "referenced-items__grid", role: "list" }, items.map((item) => {
2281
+ return /* @__PURE__ */ React25.createElement("section", { className: containerClassName, ...rest }, children, /* @__PURE__ */ React25.createElement("div", { className: "referenced-items__grid", role: "list" }, items.map((item) => {
2268
2282
  if (!item) return null;
2269
2283
  const key = item.href || item.slug || item.id;
2270
- return /* @__PURE__ */ React24.createElement("div", { className: "referenced-items__item", role: "listitem", key }, /* @__PURE__ */ React24.createElement(
2284
+ return /* @__PURE__ */ React25.createElement("div", { className: "referenced-items__item", role: "listitem", key }, /* @__PURE__ */ React25.createElement(
2271
2285
  Card,
2272
2286
  {
2273
2287
  href: item.href,
@@ -2284,7 +2298,7 @@ function ReferencedItems({
2284
2298
  }
2285
2299
 
2286
2300
  // ui/src/content/References.jsx
2287
- import React25 from "react";
2301
+ import React26 from "react";
2288
2302
  import navigationHelpers5 from "@canopy-iiif/app/lib/components/navigation.js";
2289
2303
  import referenced from "@canopy-iiif/app/lib/components/referenced.js";
2290
2304
  function getPageContext() {
@@ -2315,7 +2329,7 @@ function References({
2315
2329
  ...rest
2316
2330
  }) {
2317
2331
  const PageContext = getPageContext();
2318
- const context = PageContext ? React25.useContext(PageContext) : null;
2332
+ const context = PageContext ? React26.useContext(PageContext) : null;
2319
2333
  const contextPage = context && context.page ? context.page : null;
2320
2334
  const manifestId = id || contextPage && contextPage.manifestId || "";
2321
2335
  const contextReferences = !id && contextPage && Array.isArray(contextPage.referencedBy) ? contextPage.referencedBy : null;
@@ -2324,15 +2338,15 @@ function References({
2324
2338
  const entries = references && references.length ? references : null;
2325
2339
  if (!entries || !entries.length) return null;
2326
2340
  const containerClass = ["references", className].filter(Boolean).join(" ");
2327
- return /* @__PURE__ */ React25.createElement("dl", { className: containerClass, ...rest }, /* @__PURE__ */ React25.createElement("div", { className: "references__group" }, /* @__PURE__ */ React25.createElement("dt", null, title), entries.map((entry) => /* @__PURE__ */ React25.createElement("dd", { key: entry.href, className: "references__item" }, /* @__PURE__ */ React25.createElement("a", { href: entry.href }, entry.title || entry.href)))));
2341
+ return /* @__PURE__ */ React26.createElement("dl", { className: containerClass, ...rest }, /* @__PURE__ */ React26.createElement("div", { className: "references__group" }, /* @__PURE__ */ React26.createElement("dt", null, title), entries.map((entry) => /* @__PURE__ */ React26.createElement("dd", { key: entry.href, className: "references__item" }, /* @__PURE__ */ React26.createElement("a", { href: entry.href }, entry.title || entry.href)))));
2328
2342
  }
2329
2343
 
2330
2344
  // ui/src/content/timeline/MdxTimeline.jsx
2331
- import React27 from "react";
2345
+ import React28 from "react";
2332
2346
  import ReactDOMServer from "react-dom/server";
2333
2347
 
2334
2348
  // ui/src/content/timeline/Timeline.jsx
2335
- import React26 from "react";
2349
+ import React27 from "react";
2336
2350
 
2337
2351
  // ui/src/content/timeline/date-utils.js
2338
2352
  var FALLBACK_LOCALE = (() => {
@@ -2659,14 +2673,14 @@ function TimelineConnector({ side, isActive, highlight }) {
2659
2673
  "canopy-timeline__connector-dot",
2660
2674
  highlight || isActive ? "is-active" : ""
2661
2675
  ].filter(Boolean).join(" ");
2662
- return /* @__PURE__ */ React26.createElement("span", { className: connectorClasses, "aria-hidden": "true" }, side === "left" ? /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__connector-line" }), /* @__PURE__ */ React26.createElement("span", { className: dotClasses })) : /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement("span", { className: dotClasses }), /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__connector-line" })));
2676
+ return /* @__PURE__ */ React27.createElement("span", { className: connectorClasses, "aria-hidden": "true" }, side === "left" ? /* @__PURE__ */ React27.createElement(React27.Fragment, null, /* @__PURE__ */ React27.createElement("span", { className: "canopy-timeline__connector-line" }), /* @__PURE__ */ React27.createElement("span", { className: dotClasses })) : /* @__PURE__ */ React27.createElement(React27.Fragment, null, /* @__PURE__ */ React27.createElement("span", { className: dotClasses }), /* @__PURE__ */ React27.createElement("span", { className: "canopy-timeline__connector-line" })));
2663
2677
  }
2664
2678
  function renderResourceSection(point) {
2665
2679
  if (!point) return null;
2666
2680
  const manifestCards = Array.isArray(point.manifests) ? point.manifests.filter(Boolean) : [];
2667
2681
  const legacyResources = Array.isArray(point.resources) ? point.resources.filter(Boolean) : [];
2668
2682
  if (!manifestCards.length && !legacyResources.length) return null;
2669
- return /* @__PURE__ */ React26.createElement("div", { className: "canopy-timeline__resources" }, /* @__PURE__ */ React26.createElement("div", { className: "canopy-timeline__resources-list" }, manifestCards.map((manifest) => /* @__PURE__ */ React26.createElement("div", { key: manifest.id || manifest.href }, /* @__PURE__ */ React26.createElement(
2683
+ return /* @__PURE__ */ React27.createElement("div", { className: "canopy-timeline__resources" }, /* @__PURE__ */ React27.createElement("div", { className: "canopy-timeline__resources-list" }, manifestCards.map((manifest) => /* @__PURE__ */ React27.createElement("div", { key: manifest.id || manifest.href }, /* @__PURE__ */ React27.createElement(
2670
2684
  TeaserCard,
2671
2685
  {
2672
2686
  href: manifest.href,
@@ -2676,7 +2690,7 @@ function renderResourceSection(point) {
2676
2690
  thumbnail: manifest.thumbnail,
2677
2691
  type: manifest.type || "work"
2678
2692
  }
2679
- ))), legacyResources.map((resource, idx) => /* @__PURE__ */ React26.createElement("div", { key: resource.id || resource.href || `legacy-${idx}` }, /* @__PURE__ */ React26.createElement(
2693
+ ))), legacyResources.map((resource, idx) => /* @__PURE__ */ React27.createElement("div", { key: resource.id || resource.href || `legacy-${idx}` }, /* @__PURE__ */ React27.createElement(
2680
2694
  TeaserCard,
2681
2695
  {
2682
2696
  href: resource.href,
@@ -2701,26 +2715,26 @@ function Timeline({
2701
2715
  ...rest
2702
2716
  }) {
2703
2717
  const payloadPoints = payload && Array.isArray(payload.points) ? payload.points : null;
2704
- const rawPoints = React26.useMemo(() => {
2718
+ const rawPoints = React27.useMemo(() => {
2705
2719
  if (Array.isArray(pointsProp) && pointsProp.length) return pointsProp;
2706
2720
  if (payloadPoints && payloadPoints.length) return payloadPoints;
2707
2721
  return [];
2708
2722
  }, [pointsProp, payloadPoints]);
2709
- const sanitizedPoints = React26.useMemo(
2723
+ const sanitizedPoints = React27.useMemo(
2710
2724
  () => sanitizePoints(rawPoints),
2711
2725
  [rawPoints]
2712
2726
  );
2713
2727
  const localeValue = payload && payload.locale ? payload.locale : localeProp;
2714
- const baseLocale = React26.useMemo(
2728
+ const baseLocale = React27.useMemo(
2715
2729
  () => createLocale(localeValue),
2716
2730
  [localeValue]
2717
2731
  );
2718
2732
  const rangeInput = payload && payload.range ? payload.range : rangeProp || {};
2719
- const rangeOverrides = React26.useMemo(
2733
+ const rangeOverrides = React27.useMemo(
2720
2734
  () => deriveRangeOverrides(sanitizedPoints, rangeInput),
2721
2735
  [sanitizedPoints, rangeInput]
2722
2736
  );
2723
- const effectiveRange = React26.useMemo(
2737
+ const effectiveRange = React27.useMemo(
2724
2738
  () => normalizeRange({
2725
2739
  ...rangeOverrides,
2726
2740
  locale: baseLocale
@@ -2729,7 +2743,7 @@ function Timeline({
2729
2743
  );
2730
2744
  const spanStart = effectiveRange.startDate.getTime();
2731
2745
  const span = effectiveRange.span;
2732
- const pointsWithPosition = React26.useMemo(() => {
2746
+ const pointsWithPosition = React27.useMemo(() => {
2733
2747
  if (!sanitizedPoints.length) return [];
2734
2748
  return sanitizedPoints.map((point, index) => {
2735
2749
  const timestamp = point.meta.timestamp;
@@ -2743,29 +2757,29 @@ function Timeline({
2743
2757
  };
2744
2758
  });
2745
2759
  }, [sanitizedPoints, spanStart, span]);
2746
- const [activeId, setActiveId] = React26.useState(
2760
+ const [activeId, setActiveId] = React27.useState(
2747
2761
  () => getActivePointId(pointsWithPosition)
2748
2762
  );
2749
- React26.useEffect(() => {
2763
+ React27.useEffect(() => {
2750
2764
  setActiveId(getActivePointId(pointsWithPosition));
2751
2765
  }, [pointsWithPosition]);
2752
2766
  const thresholdValue = typeof thresholdProp === "number" ? thresholdProp : payload && payload.threshold != null ? payload.threshold : null;
2753
2767
  const stepsValue = typeof steps === "number" ? Number(steps) : payload && typeof payload.steps === "number" ? Number(payload.steps) : null;
2754
- const thresholdMs = React26.useMemo(
2768
+ const thresholdMs = React27.useMemo(
2755
2769
  () => getThresholdMs(thresholdValue, effectiveRange.granularity),
2756
2770
  [thresholdValue, effectiveRange.granularity]
2757
2771
  );
2758
- const groupedEntries = React26.useMemo(
2772
+ const groupedEntries = React27.useMemo(
2759
2773
  () => buildGroupedEntries(pointsWithPosition, thresholdMs, {
2760
2774
  granularity: effectiveRange.granularity,
2761
2775
  locale: baseLocale
2762
2776
  }),
2763
2777
  [pointsWithPosition, thresholdMs, effectiveRange.granularity, baseLocale]
2764
2778
  );
2765
- const [expandedGroupIds, setExpandedGroupIds] = React26.useState(
2779
+ const [expandedGroupIds, setExpandedGroupIds] = React27.useState(
2766
2780
  () => /* @__PURE__ */ new Set()
2767
2781
  );
2768
- React26.useEffect(() => {
2782
+ React27.useEffect(() => {
2769
2783
  setExpandedGroupIds((prev) => {
2770
2784
  if (!prev || prev.size === 0) return prev;
2771
2785
  const validIds = new Set(
@@ -2780,7 +2794,7 @@ function Timeline({
2780
2794
  return changed ? next : prev;
2781
2795
  });
2782
2796
  }, [groupedEntries]);
2783
- const toggleGroup = React26.useCallback((groupId) => {
2797
+ const toggleGroup = React27.useCallback((groupId) => {
2784
2798
  setExpandedGroupIds((prev) => {
2785
2799
  const next = new Set(prev || []);
2786
2800
  if (next.has(groupId)) next.delete(groupId);
@@ -2803,7 +2817,7 @@ function Timeline({
2803
2817
  point.id === activeId ? "is-active" : "",
2804
2818
  point.highlight ? "is-highlighted" : ""
2805
2819
  ].filter(Boolean).join(" ");
2806
- const connector = /* @__PURE__ */ React26.createElement(
2820
+ const connector = /* @__PURE__ */ React27.createElement(
2807
2821
  TimelineConnector,
2808
2822
  {
2809
2823
  side: point.side,
@@ -2811,9 +2825,9 @@ function Timeline({
2811
2825
  highlight: point.highlight
2812
2826
  }
2813
2827
  );
2814
- const body = /* @__PURE__ */ React26.createElement("div", { className: "canopy-timeline__point-body" }, /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label), /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__point-title" }, point.title), point.summary ? /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__point-summary" }, point.summary) : null);
2828
+ const body = /* @__PURE__ */ React27.createElement("div", { className: "canopy-timeline__point-body" }, /* @__PURE__ */ React27.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label), /* @__PURE__ */ React27.createElement("span", { className: "canopy-timeline__point-title" }, point.title), point.summary ? /* @__PURE__ */ React27.createElement("span", { className: "canopy-timeline__point-summary" }, point.summary) : null);
2815
2829
  const resourceSection = renderResourceSection(point);
2816
- return /* @__PURE__ */ React26.createElement(
2830
+ return /* @__PURE__ */ React27.createElement(
2817
2831
  "div",
2818
2832
  {
2819
2833
  key: point.id,
@@ -2821,7 +2835,7 @@ function Timeline({
2821
2835
  style: wrapperStyle,
2822
2836
  role: "listitem"
2823
2837
  },
2824
- point.side === "left" ? /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement("div", { className: cardClasses }, body, resourceSection), connector) : /* @__PURE__ */ React26.createElement(React26.Fragment, null, connector, /* @__PURE__ */ React26.createElement("div", { className: cardClasses }, body, resourceSection))
2838
+ point.side === "left" ? /* @__PURE__ */ React27.createElement(React27.Fragment, null, /* @__PURE__ */ React27.createElement("div", { className: cardClasses }, body, resourceSection), connector) : /* @__PURE__ */ React27.createElement(React27.Fragment, null, connector, /* @__PURE__ */ React27.createElement("div", { className: cardClasses }, body, resourceSection))
2825
2839
  );
2826
2840
  }
2827
2841
  function renderGroupEntry(entry) {
@@ -2832,7 +2846,7 @@ function Timeline({
2832
2846
  const wrapperStyle = { top: `${entry.progress * 100}%` };
2833
2847
  const isExpanded = expandedGroupIds.has(entry.id);
2834
2848
  const hasActivePoint = entry.points.some((point) => point.id === activeId);
2835
- const connector = /* @__PURE__ */ React26.createElement(
2849
+ const connector = /* @__PURE__ */ React27.createElement(
2836
2850
  TimelineConnector,
2837
2851
  {
2838
2852
  side: entry.side,
@@ -2846,7 +2860,7 @@ function Timeline({
2846
2860
  hasActivePoint ? "is-active" : ""
2847
2861
  ].filter(Boolean).join(" ");
2848
2862
  const countLabel = `${entry.count} event${entry.count > 1 ? "s" : ""}`;
2849
- const header = /* @__PURE__ */ React26.createElement("div", { className: "canopy-timeline__group-header" }, /* @__PURE__ */ React26.createElement("div", { className: "canopy-timeline__group-summary" }, /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__point-date" }, entry.label), /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__group-count" }, countLabel)), /* @__PURE__ */ React26.createElement(
2863
+ const header = /* @__PURE__ */ React27.createElement("div", { className: "canopy-timeline__group-header" }, /* @__PURE__ */ React27.createElement("div", { className: "canopy-timeline__group-summary" }, /* @__PURE__ */ React27.createElement("span", { className: "canopy-timeline__point-date" }, entry.label), /* @__PURE__ */ React27.createElement("span", { className: "canopy-timeline__group-count" }, countLabel)), /* @__PURE__ */ React27.createElement(
2850
2864
  "button",
2851
2865
  {
2852
2866
  type: "button",
@@ -2856,7 +2870,7 @@ function Timeline({
2856
2870
  },
2857
2871
  isExpanded ? "Hide details" : "Show details"
2858
2872
  ));
2859
- const groupPoints = isExpanded ? /* @__PURE__ */ React26.createElement("div", { className: "canopy-timeline__group-points" }, entry.points.map((point) => /* @__PURE__ */ React26.createElement(
2873
+ const groupPoints = isExpanded ? /* @__PURE__ */ React27.createElement("div", { className: "canopy-timeline__group-points" }, entry.points.map((point) => /* @__PURE__ */ React27.createElement(
2860
2874
  "button",
2861
2875
  {
2862
2876
  key: point.id,
@@ -2867,11 +2881,11 @@ function Timeline({
2867
2881
  ].filter(Boolean).join(" "),
2868
2882
  onClick: () => setActiveId(point.id)
2869
2883
  },
2870
- /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label),
2871
- /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__group-point-title" }, point.title)
2884
+ /* @__PURE__ */ React27.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label),
2885
+ /* @__PURE__ */ React27.createElement("span", { className: "canopy-timeline__group-point-title" }, point.title)
2872
2886
  ))) : null;
2873
- const groupCard = /* @__PURE__ */ React26.createElement("div", { className: groupClasses }, header, groupPoints);
2874
- return /* @__PURE__ */ React26.createElement(
2887
+ const groupCard = /* @__PURE__ */ React27.createElement("div", { className: groupClasses }, header, groupPoints);
2888
+ return /* @__PURE__ */ React27.createElement(
2875
2889
  "div",
2876
2890
  {
2877
2891
  key: entry.id,
@@ -2879,17 +2893,17 @@ function Timeline({
2879
2893
  style: wrapperStyle,
2880
2894
  role: "listitem"
2881
2895
  },
2882
- entry.side === "left" ? /* @__PURE__ */ React26.createElement(React26.Fragment, null, groupCard, connector) : /* @__PURE__ */ React26.createElement(React26.Fragment, null, connector, groupCard)
2896
+ entry.side === "left" ? /* @__PURE__ */ React27.createElement(React27.Fragment, null, groupCard, connector) : /* @__PURE__ */ React27.createElement(React27.Fragment, null, connector, groupCard)
2883
2897
  );
2884
2898
  }
2885
- return /* @__PURE__ */ React26.createElement("section", { className: containerClasses, ...rest }, title ? /* @__PURE__ */ React26.createElement("h2", { className: "canopy-timeline__title" }, title) : null, description ? /* @__PURE__ */ React26.createElement("p", { className: "canopy-timeline__description" }, description) : null, rangeLabel ? /* @__PURE__ */ React26.createElement("p", { className: "canopy-timeline__range", "aria-live": "polite" }, rangeLabel) : null, /* @__PURE__ */ React26.createElement("div", { className: "canopy-timeline__body" }, /* @__PURE__ */ React26.createElement(
2899
+ return /* @__PURE__ */ React27.createElement("section", { className: containerClasses, ...rest }, title ? /* @__PURE__ */ React27.createElement("h2", { className: "canopy-timeline__title" }, title) : null, description ? /* @__PURE__ */ React27.createElement("p", { className: "canopy-timeline__description" }, description) : null, rangeLabel ? /* @__PURE__ */ React27.createElement("p", { className: "canopy-timeline__range", "aria-live": "polite" }, rangeLabel) : null, /* @__PURE__ */ React27.createElement("div", { className: "canopy-timeline__body" }, /* @__PURE__ */ React27.createElement(
2886
2900
  "div",
2887
2901
  {
2888
2902
  className: "canopy-timeline__list",
2889
2903
  role: "list",
2890
2904
  style: { minHeight: trackHeight }
2891
2905
  },
2892
- /* @__PURE__ */ React26.createElement("div", { className: "canopy-timeline__spine", "aria-hidden": "true" }),
2906
+ /* @__PURE__ */ React27.createElement("div", { className: "canopy-timeline__spine", "aria-hidden": "true" }),
2893
2907
  renderSteps(stepsValue, effectiveRange),
2894
2908
  groupedEntries.map((entry) => {
2895
2909
  if (entry.type === "group") return renderGroupEntry(entry);
@@ -2904,7 +2918,7 @@ function renderSteps(stepSize, range) {
2904
2918
  const markers = [];
2905
2919
  if (startYear < endYear) {
2906
2920
  markers.push(
2907
- /* @__PURE__ */ React26.createElement(
2921
+ /* @__PURE__ */ React27.createElement(
2908
2922
  "span",
2909
2923
  {
2910
2924
  key: "timeline-step-start",
@@ -2912,12 +2926,12 @@ function renderSteps(stepSize, range) {
2912
2926
  style: { top: "0%" },
2913
2927
  "aria-hidden": "true"
2914
2928
  },
2915
- /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__step-line" }),
2916
- /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__step-label" }, startYear)
2929
+ /* @__PURE__ */ React27.createElement("span", { className: "canopy-timeline__step-line" }),
2930
+ /* @__PURE__ */ React27.createElement("span", { className: "canopy-timeline__step-label" }, startYear)
2917
2931
  )
2918
2932
  );
2919
2933
  markers.push(
2920
- /* @__PURE__ */ React26.createElement(
2934
+ /* @__PURE__ */ React27.createElement(
2921
2935
  "span",
2922
2936
  {
2923
2937
  key: "timeline-step-end",
@@ -2925,8 +2939,8 @@ function renderSteps(stepSize, range) {
2925
2939
  style: { top: "100%" },
2926
2940
  "aria-hidden": "true"
2927
2941
  },
2928
- /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__step-line" }),
2929
- /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__step-label" }, endYear)
2942
+ /* @__PURE__ */ React27.createElement("span", { className: "canopy-timeline__step-line" }),
2943
+ /* @__PURE__ */ React27.createElement("span", { className: "canopy-timeline__step-label" }, endYear)
2930
2944
  )
2931
2945
  );
2932
2946
  }
@@ -2936,7 +2950,7 @@ function renderSteps(stepSize, range) {
2936
2950
  const progress = (timestamp - range.startDate.getTime()) / range.span;
2937
2951
  if (progress <= 0 || progress >= 1) continue;
2938
2952
  markers.push(
2939
- /* @__PURE__ */ React26.createElement(
2953
+ /* @__PURE__ */ React27.createElement(
2940
2954
  "span",
2941
2955
  {
2942
2956
  key: `timeline-step-${year}`,
@@ -2944,8 +2958,8 @@ function renderSteps(stepSize, range) {
2944
2958
  style: { top: `calc(${progress * 100}% - 0.5px)` },
2945
2959
  "aria-hidden": "true"
2946
2960
  },
2947
- /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__step-line" }),
2948
- /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__step-label" }, year)
2961
+ /* @__PURE__ */ React27.createElement("span", { className: "canopy-timeline__step-line" }),
2962
+ /* @__PURE__ */ React27.createElement("span", { className: "canopy-timeline__step-label" }, year)
2949
2963
  )
2950
2964
  );
2951
2965
  }
@@ -2975,13 +2989,13 @@ function normalizeManifestId(raw) {
2975
2989
  return String(raw || "").trim();
2976
2990
  }
2977
2991
  }
2978
- var PageContextFallback = React27.createContext(null);
2992
+ var PageContextFallback = React28.createContext(null);
2979
2993
  function useReferencedManifestMap() {
2980
2994
  var _a, _b;
2981
2995
  const PageContext = ((_b = (_a = navigationHelpers6) == null ? void 0 : _a.getPageContext) == null ? void 0 : _b.call(_a)) || PageContextFallback;
2982
- const pageContext = React27.useContext(PageContext);
2996
+ const pageContext = React28.useContext(PageContext);
2983
2997
  const referencedItems = pageContext && pageContext.page && Array.isArray(pageContext.page.referencedItems) ? pageContext.page.referencedItems : [];
2984
- return React27.useMemo(() => {
2998
+ return React28.useMemo(() => {
2985
2999
  const map = /* @__PURE__ */ new Map();
2986
3000
  referencedItems.forEach((item) => {
2987
3001
  if (!item) return;
@@ -3009,7 +3023,7 @@ function normalizeResource(resource, index) {
3009
3023
  }
3010
3024
  function normalizePoint(child, index, options) {
3011
3025
  var _a, _b, _c, _d, _e, _f;
3012
- if (!React27.isValidElement(child)) return null;
3026
+ if (!React28.isValidElement(child)) return null;
3013
3027
  if (child.type !== TimelinePoint && ((_a = child.type) == null ? void 0 : _a.displayName) !== "TimelinePoint")
3014
3028
  return null;
3015
3029
  const props = child.props || {};
@@ -3025,7 +3039,7 @@ function normalizePoint(child, index, options) {
3025
3039
  try {
3026
3040
  if (props.children) {
3027
3041
  detailsHtml = ReactDOMServer.renderToStaticMarkup(
3028
- React27.createElement(React27.Fragment, null, props.children)
3042
+ React28.createElement(React28.Fragment, null, props.children)
3029
3043
  );
3030
3044
  }
3031
3045
  } catch (_) {
@@ -3099,7 +3113,7 @@ function MdxTimeline({ children, ...rest }) {
3099
3113
  const localeObj = createLocale(localeValue);
3100
3114
  const localeBase = typeof localeObj === "string" ? localeObj : localeObj.baseName || "en-US";
3101
3115
  const manifestMap = useReferencedManifestMap();
3102
- const childArray = React27.Children.toArray(children);
3116
+ const childArray = React28.Children.toArray(children);
3103
3117
  const points = childArray.map(
3104
3118
  (child, index) => normalizePoint(child, index, {
3105
3119
  range: rest.range || {},
@@ -3115,7 +3129,7 @@ function MdxTimeline({ children, ...rest }) {
3115
3129
  steps: rest.steps != null ? rest.steps : null
3116
3130
  };
3117
3131
  const json = serializeForScript(serializeProps(rest, payload, localeBase));
3118
- return /* @__PURE__ */ React27.createElement("div", { "data-canopy-timeline": "1" }, /* @__PURE__ */ React27.createElement(Timeline, { ...rest, __canopyTimeline: payload }), /* @__PURE__ */ React27.createElement(
3132
+ return /* @__PURE__ */ React28.createElement("div", { "data-canopy-timeline": "1" }, /* @__PURE__ */ React28.createElement(Timeline, { ...rest, __canopyTimeline: payload }), /* @__PURE__ */ React28.createElement(
3119
3133
  "script",
3120
3134
  {
3121
3135
  type: "application/json",
@@ -3125,7 +3139,7 @@ function MdxTimeline({ children, ...rest }) {
3125
3139
  }
3126
3140
 
3127
3141
  // ui/src/search/MdxSearchResults.jsx
3128
- import React28 from "react";
3142
+ import React29 from "react";
3129
3143
  function MdxSearchResults(props) {
3130
3144
  let json = "{}";
3131
3145
  try {
@@ -3133,11 +3147,11 @@ function MdxSearchResults(props) {
3133
3147
  } catch (_) {
3134
3148
  json = "{}";
3135
3149
  }
3136
- return /* @__PURE__ */ React28.createElement("div", { "data-canopy-search-results": "1" }, /* @__PURE__ */ React28.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3150
+ return /* @__PURE__ */ React29.createElement("div", { "data-canopy-search-results": "1" }, /* @__PURE__ */ React29.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3137
3151
  }
3138
3152
 
3139
3153
  // ui/src/search/SearchSummary.jsx
3140
- import React29 from "react";
3154
+ import React30 from "react";
3141
3155
  function SearchSummary(props) {
3142
3156
  let json = "{}";
3143
3157
  try {
@@ -3145,11 +3159,11 @@ function SearchSummary(props) {
3145
3159
  } catch (_) {
3146
3160
  json = "{}";
3147
3161
  }
3148
- return /* @__PURE__ */ React29.createElement("div", { "data-canopy-search-summary": "1" }, /* @__PURE__ */ React29.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3162
+ return /* @__PURE__ */ React30.createElement("div", { "data-canopy-search-summary": "1" }, /* @__PURE__ */ React30.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3149
3163
  }
3150
3164
 
3151
3165
  // ui/src/search/MdxSearchTabs.jsx
3152
- import React30 from "react";
3166
+ import React31 from "react";
3153
3167
  function MdxSearchTabs(props) {
3154
3168
  let json = "{}";
3155
3169
  try {
@@ -3157,11 +3171,11 @@ function MdxSearchTabs(props) {
3157
3171
  } catch (_) {
3158
3172
  json = "{}";
3159
3173
  }
3160
- return /* @__PURE__ */ React30.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React30.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3174
+ return /* @__PURE__ */ React31.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React31.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3161
3175
  }
3162
3176
 
3163
3177
  // ui/src/search/MdxSearch.jsx
3164
- import React31 from "react";
3178
+ import React32 from "react";
3165
3179
  function MdxSearch(props = {}) {
3166
3180
  const {
3167
3181
  layout,
@@ -3179,11 +3193,11 @@ function MdxSearch(props = {}) {
3179
3193
  resultsPayload.layout = layout;
3180
3194
  }
3181
3195
  const classes = ["canopy-search", className].filter(Boolean).join(" ");
3182
- return /* @__PURE__ */ React31.createElement("section", { className: classes, "data-canopy-search": "1" }, showTabs ? /* @__PURE__ */ React31.createElement(MdxSearchTabs, { ...tabsProps }) : null, showSummary ? /* @__PURE__ */ React31.createElement(SearchSummary, { ...summaryProps }) : null, showResults ? /* @__PURE__ */ React31.createElement(MdxSearchResults, { ...resultsPayload }) : null, children || null);
3196
+ 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);
3183
3197
  }
3184
3198
 
3185
3199
  // ui/src/search-form/MdxSearchFormModal.jsx
3186
- import React32 from "react";
3200
+ import React33 from "react";
3187
3201
  function MdxSearchFormModal(props = {}) {
3188
3202
  const {
3189
3203
  placeholder = "Search\u2026",
@@ -3199,11 +3213,11 @@ function MdxSearchFormModal(props = {}) {
3199
3213
  const text = typeof label === "string" && label.trim() ? label.trim() : buttonLabel;
3200
3214
  const resolvedSearchPath = resolveSearchPath(searchPath);
3201
3215
  const data = { placeholder, hotkey, maxResults, groupOrder, label: text, searchPath: resolvedSearchPath };
3202
- return /* @__PURE__ */ React32.createElement("div", { "data-canopy-search-form": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React32.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React32.createElement(SearchPanelForm, { placeholder, buttonLabel, label, searchPath: resolvedSearchPath }), /* @__PURE__ */ React32.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React32.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
3216
+ 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) } }));
3203
3217
  }
3204
3218
 
3205
3219
  // ui/src/iiif/ManifestPrimitives.jsx
3206
- import React33 from "react";
3220
+ import React34 from "react";
3207
3221
  import {
3208
3222
  Label as CloverLabel,
3209
3223
  Metadata as CloverMetadata,
@@ -3228,28 +3242,28 @@ function ensureMetadata(items) {
3228
3242
  function Label({ manifest, label, ...rest }) {
3229
3243
  const intl = label || manifest && manifest.label;
3230
3244
  if (!hasInternationalValue(intl)) return null;
3231
- return /* @__PURE__ */ React33.createElement(CloverLabel, { label: intl, ...rest });
3245
+ return /* @__PURE__ */ React34.createElement(CloverLabel, { label: intl, ...rest });
3232
3246
  }
3233
3247
  function Summary({ manifest, summary, ...rest }) {
3234
3248
  const intl = summary || manifest && manifest.summary;
3235
3249
  if (!hasInternationalValue(intl)) return null;
3236
- return /* @__PURE__ */ React33.createElement(CloverSummary, { summary: intl, ...rest });
3250
+ return /* @__PURE__ */ React34.createElement(CloverSummary, { summary: intl, ...rest });
3237
3251
  }
3238
3252
  function Metadata({ manifest, metadata, ...rest }) {
3239
3253
  const items = ensureMetadata(metadata || manifest && manifest.metadata);
3240
3254
  if (!items.length) return null;
3241
- return /* @__PURE__ */ React33.createElement(CloverMetadata, { metadata: items, ...rest });
3255
+ return /* @__PURE__ */ React34.createElement(CloverMetadata, { metadata: items, ...rest });
3242
3256
  }
3243
3257
  function RequiredStatement({ manifest, requiredStatement, ...rest }) {
3244
3258
  const stmt = requiredStatement || manifest && manifest.requiredStatement;
3245
3259
  if (!stmt || !hasInternationalValue(stmt.label) || !hasInternationalValue(stmt.value)) {
3246
3260
  return null;
3247
3261
  }
3248
- return /* @__PURE__ */ React33.createElement(CloverRequiredStatement, { requiredStatement: stmt, ...rest });
3262
+ return /* @__PURE__ */ React34.createElement(CloverRequiredStatement, { requiredStatement: stmt, ...rest });
3249
3263
  }
3250
3264
 
3251
3265
  // ui/src/docs/CodeBlock.jsx
3252
- import React34 from "react";
3266
+ import React35 from "react";
3253
3267
  function parseHighlightAttr(attr) {
3254
3268
  if (!attr) return /* @__PURE__ */ new Set();
3255
3269
  const cleaned = String(attr || "").trim();
@@ -3295,10 +3309,10 @@ var highlightBaseStyle = {
3295
3309
  };
3296
3310
  function DocsCodeBlock(props = {}) {
3297
3311
  const { children, ...rest } = props;
3298
- const childArray = React34.Children.toArray(children);
3299
- const codeElement = childArray.find((el) => React34.isValidElement(el));
3312
+ const childArray = React35.Children.toArray(children);
3313
+ const codeElement = childArray.find((el) => React35.isValidElement(el));
3300
3314
  if (!codeElement || !codeElement.props) {
3301
- return React34.createElement("pre", props);
3315
+ return React35.createElement("pre", props);
3302
3316
  }
3303
3317
  const {
3304
3318
  className = "",
@@ -3313,8 +3327,8 @@ function DocsCodeBlock(props = {}) {
3313
3327
  const highlightSet = parseHighlightAttr(highlightAttr);
3314
3328
  const copyAttr = codeProps["data-copy"];
3315
3329
  const enableCopy = copyAttr !== void 0 ? copyAttr === true || copyAttr === "true" || copyAttr === "" : false;
3316
- const [copied, setCopied] = React34.useState(false);
3317
- const handleCopy = React34.useCallback(async () => {
3330
+ const [copied, setCopied] = React35.useState(false);
3331
+ const handleCopy = React35.useCallback(async () => {
3318
3332
  const text = rawCode;
3319
3333
  try {
3320
3334
  if (typeof navigator !== "undefined" && navigator.clipboard && navigator.clipboard.writeText) {
@@ -3379,20 +3393,20 @@ function DocsCodeBlock(props = {}) {
3379
3393
  const highlight = highlightSet.has(lineNumber);
3380
3394
  const style = highlight ? { ...baseLineStyle, ...highlightBaseStyle } : baseLineStyle;
3381
3395
  const displayLine = line === "" ? " " : line;
3382
- return React34.createElement(
3396
+ return React35.createElement(
3383
3397
  "span",
3384
3398
  { key: lineNumber, style },
3385
- React34.createElement("span", { style: lineContentStyle }, displayLine)
3399
+ React35.createElement("span", { style: lineContentStyle }, displayLine)
3386
3400
  );
3387
3401
  });
3388
- return React34.createElement(
3402
+ return React35.createElement(
3389
3403
  "div",
3390
3404
  { style: containerStyle },
3391
- showHeader ? React34.createElement(
3405
+ showHeader ? React35.createElement(
3392
3406
  "div",
3393
3407
  { style: headerStyle },
3394
- React34.createElement("span", null, showFilename ? filename : null),
3395
- enableCopy ? React34.createElement(
3408
+ React35.createElement("span", null, showFilename ? filename : null),
3409
+ enableCopy ? React35.createElement(
3396
3410
  "button",
3397
3411
  {
3398
3412
  type: "button",
@@ -3411,29 +3425,29 @@ function DocsCodeBlock(props = {}) {
3411
3425
  copied ? "Copied" : "Copy"
3412
3426
  ) : null
3413
3427
  ) : null,
3414
- React34.createElement(
3428
+ React35.createElement(
3415
3429
  "pre",
3416
3430
  { ...preRest, className: preClassName, style: mergedPreStyle },
3417
- React34.createElement("code", { style: codeStyle }, lineElements)
3431
+ React35.createElement("code", { style: codeStyle }, lineElements)
3418
3432
  )
3419
3433
  );
3420
3434
  }
3421
3435
 
3422
3436
  // ui/src/docs/MarkdownTable.jsx
3423
- import React35 from "react";
3437
+ import React36 from "react";
3424
3438
  function MarkdownTable({ className = "", ...rest }) {
3425
3439
  const merged = ["markdown-table", className].filter(Boolean).join(" ");
3426
- return /* @__PURE__ */ React35.createElement("div", { className: "markdown-table__frame" }, /* @__PURE__ */ React35.createElement("table", { className: merged, ...rest }));
3440
+ return /* @__PURE__ */ React36.createElement("div", { className: "markdown-table__frame" }, /* @__PURE__ */ React36.createElement("table", { className: merged, ...rest }));
3427
3441
  }
3428
3442
 
3429
3443
  // ui/src/docs/Diagram.jsx
3430
- import React36 from "react";
3444
+ import React37 from "react";
3431
3445
  function CanopyDiagram() {
3432
- return /* @__PURE__ */ React36.createElement("div", { className: "canopy-diagram" }, /* @__PURE__ */ React36.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--collections" }, /* @__PURE__ */ React36.createElement("h3", null, "IIIF Collection(s)"), /* @__PURE__ */ React36.createElement("span", { className: "canopy-diagram__section-summary" }, "Source collections contribute 105 total manifests that Canopy retrieves as-is via IIIF endpoints."), /* @__PURE__ */ React36.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React36.createElement("article", null, /* @__PURE__ */ React36.createElement("h4", null, "Collection A"), /* @__PURE__ */ React36.createElement("ul", null, /* @__PURE__ */ React36.createElement("li", null, "70 Manifests"), /* @__PURE__ */ React36.createElement("li", null, "IIIF Images + A/V"), /* @__PURE__ */ React36.createElement("li", null, "Textual Annotations"))), /* @__PURE__ */ React36.createElement("article", null, /* @__PURE__ */ React36.createElement("h4", null, "Collection B"), /* @__PURE__ */ React36.createElement("ul", null, /* @__PURE__ */ React36.createElement("li", null, "35 Manifests"), /* @__PURE__ */ React36.createElement("li", null, "IIIF Images + A/V"), /* @__PURE__ */ React36.createElement("li", null, "Textual Annotations"))))), /* @__PURE__ */ React36.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React36.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React36.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React36.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--build" }, /* @__PURE__ */ React36.createElement("h3", null, "Canopy Build Process"), /* @__PURE__ */ React36.createElement("span", { className: "canopy-diagram__section-summary" }, "Canopy syncs manifests, page content, and annotations before bundling the site."), /* @__PURE__ */ React36.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React36.createElement("article", null, /* @__PURE__ */ React36.createElement("h4", null, "Automated content"), /* @__PURE__ */ React36.createElement("ul", null, /* @__PURE__ */ React36.createElement("li", null, "105 manifests \u2192 105 work pages"), /* @__PURE__ */ React36.createElement("li", null, "One page per manifest"), /* @__PURE__ */ React36.createElement("li", null, "Customize page layout"))), /* @__PURE__ */ React36.createElement("article", null, /* @__PURE__ */ React36.createElement("h4", null, "Contextual content"), /* @__PURE__ */ React36.createElement("ul", null, /* @__PURE__ */ React36.createElement("li", null, "Markdown & MDX pages"), /* @__PURE__ */ React36.createElement("li", null, "Author narratives & tours"), /* @__PURE__ */ React36.createElement("li", null, "Reference manifests inline"))), /* @__PURE__ */ React36.createElement("article", null, /* @__PURE__ */ React36.createElement("h4", null, "Search index"), /* @__PURE__ */ React36.createElement("ul", null, /* @__PURE__ */ React36.createElement("li", null, "Combines works + pages"), /* @__PURE__ */ React36.createElement("li", null, "Customize result layout"), /* @__PURE__ */ React36.createElement("li", null, "Optional annotations"))))), /* @__PURE__ */ React36.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React36.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React36.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React36.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--output" }, /* @__PURE__ */ React36.createElement("h3", null, "Static Digital Project"), /* @__PURE__ */ React36.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__ */ React36.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React36.createElement("article", null, /* @__PURE__ */ React36.createElement("h4", null, "Work pages"), /* @__PURE__ */ React36.createElement("ul", null, /* @__PURE__ */ React36.createElement("li", null, "105 generated HTML pages"), /* @__PURE__ */ React36.createElement("li", null, "Each links back to source manifests"), /* @__PURE__ */ React36.createElement("li", null, "Styled with Canopy components"))), /* @__PURE__ */ React36.createElement("article", null, /* @__PURE__ */ React36.createElement("h4", null, "Custom pages"), /* @__PURE__ */ React36.createElement("ul", null, /* @__PURE__ */ React36.createElement("li", null, "Markdown & MDX-authored content"), /* @__PURE__ */ React36.createElement("li", null, "Reusable layouts for narratives"), /* @__PURE__ */ React36.createElement("li", null, "Embed IIIF media & interstitials"))), /* @__PURE__ */ React36.createElement("article", null, /* @__PURE__ */ React36.createElement("h4", null, "Search bundle"), /* @__PURE__ */ React36.createElement("ul", null, /* @__PURE__ */ React36.createElement("li", null, "Static FlexSearch index"), /* @__PURE__ */ React36.createElement("li", null, "Works + pages share records"), /* @__PURE__ */ React36.createElement("li", null, "Optional annotation dataset"))))));
3446
+ return /* @__PURE__ */ React37.createElement("div", { className: "canopy-diagram" }, /* @__PURE__ */ React37.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--collections" }, /* @__PURE__ */ React37.createElement("h3", null, "IIIF Collection(s)"), /* @__PURE__ */ React37.createElement("span", { className: "canopy-diagram__section-summary" }, "Source collections contribute 105 total manifests that Canopy retrieves as-is via IIIF endpoints."), /* @__PURE__ */ React37.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React37.createElement("article", null, /* @__PURE__ */ React37.createElement("h4", null, "Collection A"), /* @__PURE__ */ React37.createElement("ul", null, /* @__PURE__ */ React37.createElement("li", null, "70 Manifests"), /* @__PURE__ */ React37.createElement("li", null, "IIIF Images + A/V"), /* @__PURE__ */ React37.createElement("li", null, "Textual Annotations"))), /* @__PURE__ */ React37.createElement("article", null, /* @__PURE__ */ React37.createElement("h4", null, "Collection B"), /* @__PURE__ */ React37.createElement("ul", null, /* @__PURE__ */ React37.createElement("li", null, "35 Manifests"), /* @__PURE__ */ React37.createElement("li", null, "IIIF Images + A/V"), /* @__PURE__ */ React37.createElement("li", null, "Textual Annotations"))))), /* @__PURE__ */ React37.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React37.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React37.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React37.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--build" }, /* @__PURE__ */ React37.createElement("h3", null, "Canopy Build Process"), /* @__PURE__ */ React37.createElement("span", { className: "canopy-diagram__section-summary" }, "Canopy syncs manifests, page content, and annotations before bundling the site."), /* @__PURE__ */ React37.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React37.createElement("article", null, /* @__PURE__ */ React37.createElement("h4", null, "Automated content"), /* @__PURE__ */ React37.createElement("ul", null, /* @__PURE__ */ React37.createElement("li", null, "105 manifests \u2192 105 work pages"), /* @__PURE__ */ React37.createElement("li", null, "One page per manifest"), /* @__PURE__ */ React37.createElement("li", null, "Customize page layout"))), /* @__PURE__ */ React37.createElement("article", null, /* @__PURE__ */ React37.createElement("h4", null, "Contextual content"), /* @__PURE__ */ React37.createElement("ul", null, /* @__PURE__ */ React37.createElement("li", null, "Markdown & MDX pages"), /* @__PURE__ */ React37.createElement("li", null, "Author narratives & tours"), /* @__PURE__ */ React37.createElement("li", null, "Reference manifests inline"))), /* @__PURE__ */ React37.createElement("article", null, /* @__PURE__ */ React37.createElement("h4", null, "Search index"), /* @__PURE__ */ React37.createElement("ul", null, /* @__PURE__ */ React37.createElement("li", null, "Combines works + pages"), /* @__PURE__ */ React37.createElement("li", null, "Customize result layout"), /* @__PURE__ */ React37.createElement("li", null, "Optional annotations"))))), /* @__PURE__ */ React37.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React37.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React37.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React37.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--output" }, /* @__PURE__ */ React37.createElement("h3", null, "Static Digital Project"), /* @__PURE__ */ React37.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__ */ React37.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React37.createElement("article", null, /* @__PURE__ */ React37.createElement("h4", null, "Work pages"), /* @__PURE__ */ React37.createElement("ul", null, /* @__PURE__ */ React37.createElement("li", null, "105 generated HTML pages"), /* @__PURE__ */ React37.createElement("li", null, "Each links back to source manifests"), /* @__PURE__ */ React37.createElement("li", null, "Styled with Canopy components"))), /* @__PURE__ */ React37.createElement("article", null, /* @__PURE__ */ React37.createElement("h4", null, "Custom pages"), /* @__PURE__ */ React37.createElement("ul", null, /* @__PURE__ */ React37.createElement("li", null, "Markdown & MDX-authored content"), /* @__PURE__ */ React37.createElement("li", null, "Reusable layouts for narratives"), /* @__PURE__ */ React37.createElement("li", null, "Embed IIIF media & interstitials"))), /* @__PURE__ */ React37.createElement("article", null, /* @__PURE__ */ React37.createElement("h4", null, "Search bundle"), /* @__PURE__ */ React37.createElement("ul", null, /* @__PURE__ */ React37.createElement("li", null, "Static FlexSearch index"), /* @__PURE__ */ React37.createElement("li", null, "Works + pages share records"), /* @__PURE__ */ React37.createElement("li", null, "Optional annotation dataset"))))));
3433
3447
  }
3434
3448
 
3435
3449
  // ui/src/docs/ThemeShowcase.jsx
3436
- import React37 from "react";
3450
+ import React38 from "react";
3437
3451
 
3438
3452
  // ../../node_modules/@radix-ui/colors/index.mjs
3439
3453
  var colors_exports = {};
@@ -7266,21 +7280,21 @@ var ACCENT_COLOR_NAMES = [
7266
7280
  "sky"
7267
7281
  ];
7268
7282
  var GRAY_COLOR_NAMES = ["gray", "mauve", "slate", "sage", "olive", "sand"];
7269
- var Section = ({ title, description, children }) => /* @__PURE__ */ React37.createElement("div", { className: "canopy-theme-showcase__section" }, /* @__PURE__ */ React37.createElement("h3", { className: "canopy-theme-showcase__section-title" }, title), description ? /* @__PURE__ */ React37.createElement("p", { className: "canopy-theme-showcase__section-description" }, description) : null, children);
7270
- var ColorScaleRow = ({ label, prefix }) => /* @__PURE__ */ React37.createElement("div", { className: "canopy-theme-showcase__scale-row" }, /* @__PURE__ */ React37.createElement("div", { className: "canopy-theme-showcase__scale-label" }, /* @__PURE__ */ React37.createElement("strong", null, label)), /* @__PURE__ */ React37.createElement("div", { className: "canopy-theme-showcase__scale-track" }, COLOR_STOPS.map((stop) => /* @__PURE__ */ React37.createElement(
7283
+ var Section = ({ title, description, children }) => /* @__PURE__ */ React38.createElement("div", { className: "canopy-theme-showcase__section" }, /* @__PURE__ */ React38.createElement("h3", { className: "canopy-theme-showcase__section-title" }, title), description ? /* @__PURE__ */ React38.createElement("p", { className: "canopy-theme-showcase__section-description" }, description) : null, children);
7284
+ var ColorScaleRow = ({ label, prefix }) => /* @__PURE__ */ React38.createElement("div", { className: "canopy-theme-showcase__scale-row" }, /* @__PURE__ */ React38.createElement("div", { className: "canopy-theme-showcase__scale-label" }, /* @__PURE__ */ React38.createElement("strong", null, label)), /* @__PURE__ */ React38.createElement("div", { className: "canopy-theme-showcase__scale-track" }, COLOR_STOPS.map((stop) => /* @__PURE__ */ React38.createElement(
7271
7285
  "div",
7272
7286
  {
7273
7287
  key: `${label}-${stop}`,
7274
7288
  className: "canopy-theme-showcase__scale-stop"
7275
7289
  },
7276
- /* @__PURE__ */ React37.createElement(
7290
+ /* @__PURE__ */ React38.createElement(
7277
7291
  "span",
7278
7292
  {
7279
7293
  className: "canopy-theme-showcase__scale-chip",
7280
7294
  style: { backgroundColor: `var(${prefix}-${stop})` }
7281
7295
  }
7282
7296
  ),
7283
- /* @__PURE__ */ React37.createElement("span", { className: "canopy-theme-showcase__scale-token" }, stop)
7297
+ /* @__PURE__ */ React38.createElement("span", { className: "canopy-theme-showcase__scale-token" }, stop)
7284
7298
  ))));
7285
7299
  function ThemeShowcase() {
7286
7300
  const accentColors = ACCENT_COLOR_NAMES;
@@ -7291,15 +7305,15 @@ function ThemeShowcase() {
7291
7305
  if (!scale) return null;
7292
7306
  return scale[`${name}9`] || Object.values(scale)[8];
7293
7307
  };
7294
- const ColorsLabeled = ({ colors }) => /* @__PURE__ */ React37.createElement("div", { className: "canopy-theme-showcase__swatch-grid" }, colors.map((name) => {
7308
+ const ColorsLabeled = ({ colors }) => /* @__PURE__ */ React38.createElement("div", { className: "canopy-theme-showcase__swatch-grid" }, colors.map((name) => {
7295
7309
  const colorValue = getRadixSwatch(name);
7296
- return /* @__PURE__ */ React37.createElement("div", { key: name, className: "canopy-theme-showcase__swatch" }, /* @__PURE__ */ React37.createElement(
7310
+ return /* @__PURE__ */ React38.createElement("div", { key: name, className: "canopy-theme-showcase__swatch" }, /* @__PURE__ */ React38.createElement(
7297
7311
  "div",
7298
7312
  {
7299
7313
  className: "canopy-theme-showcase__swatch-chip",
7300
7314
  style: { background: colorValue || "var(--color-gray-200)" }
7301
7315
  }
7302
- ), /* @__PURE__ */ React37.createElement("div", { className: "canopy-theme-showcase__swatch-label" }, name));
7316
+ ), /* @__PURE__ */ React38.createElement("div", { className: "canopy-theme-showcase__swatch-label" }, name));
7303
7317
  }));
7304
7318
  const styles = `
7305
7319
  .canopy-theme-showcase__section {
@@ -7383,13 +7397,13 @@ function ThemeShowcase() {
7383
7397
  font-weight: 300;
7384
7398
  }
7385
7399
  `;
7386
- return /* @__PURE__ */ React37.createElement("div", { className: "canopy-theme-showcase" }, /* @__PURE__ */ React37.createElement("style", { dangerouslySetInnerHTML: { __html: styles } }), /* @__PURE__ */ React37.createElement(
7400
+ return /* @__PURE__ */ React38.createElement("div", { className: "canopy-theme-showcase" }, /* @__PURE__ */ React38.createElement("style", { dangerouslySetInnerHTML: { __html: styles } }), /* @__PURE__ */ React38.createElement(
7387
7401
  Section,
7388
7402
  {
7389
7403
  title: "Color scales",
7390
7404
  description: "Accent and gray ramps from the active theme."
7391
7405
  },
7392
- /* @__PURE__ */ React37.createElement("div", { style: { display: "flex", flexDirection: "column", gap: "1.5rem" } }, COLOR_SCALES.map((scale) => /* @__PURE__ */ React37.createElement(
7406
+ /* @__PURE__ */ React38.createElement("div", { style: { display: "flex", flexDirection: "column", gap: "1.5rem" } }, COLOR_SCALES.map((scale) => /* @__PURE__ */ React38.createElement(
7393
7407
  ColorScaleRow,
7394
7408
  {
7395
7409
  key: scale.label,
@@ -7397,20 +7411,20 @@ function ThemeShowcase() {
7397
7411
  prefix: scale.prefix
7398
7412
  }
7399
7413
  )))
7400
- ), /* @__PURE__ */ React37.createElement(
7414
+ ), /* @__PURE__ */ React38.createElement(
7401
7415
  Section,
7402
7416
  {
7403
7417
  title: "Accent color palette options",
7404
7418
  description: "Primary color steps used for buttons, links, and highlights."
7405
7419
  },
7406
- /* @__PURE__ */ React37.createElement(ColorsLabeled, { colors: accentColors })
7407
- ), /* @__PURE__ */ React37.createElement(
7420
+ /* @__PURE__ */ React38.createElement(ColorsLabeled, { colors: accentColors })
7421
+ ), /* @__PURE__ */ React38.createElement(
7408
7422
  Section,
7409
7423
  {
7410
7424
  title: "Gray color palette options",
7411
7425
  description: "Neutral color steps used for backgrounds, borders, and text."
7412
7426
  },
7413
- /* @__PURE__ */ React37.createElement(ColorsLabeled, { colors: grayColors })
7427
+ /* @__PURE__ */ React38.createElement(ColorsLabeled, { colors: grayColors })
7414
7428
  ));
7415
7429
  }
7416
7430
  export {
@@ -7425,6 +7439,7 @@ export {
7425
7439
  Container,
7426
7440
  DocsCodeBlock,
7427
7441
  MarkdownTable as DocsMarkdownTable,
7442
+ GoogleAnalytics,
7428
7443
  HelloWorld,
7429
7444
  Image,
7430
7445
  interstitials_exports as Interstitials,