@canopy-iiif/app 1.4.7 → 1.4.9

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.
@@ -2415,12 +2415,60 @@ function References({
2415
2415
  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)))));
2416
2416
  }
2417
2417
 
2418
+ // ui/src/content/Biblography.jsx
2419
+ import React27 from "react";
2420
+ import bibliography from "@canopy-iiif/app/lib/components/bibliography.js";
2421
+ function resolveHeadingTag(tag, fallback) {
2422
+ if (typeof tag === "string" && tag.trim()) return tag;
2423
+ if (typeof tag === "function") return tag;
2424
+ return fallback;
2425
+ }
2426
+ function NoteBody({ note }) {
2427
+ if (!note) return null;
2428
+ if (note.html) {
2429
+ return /* @__PURE__ */ React27.createElement(
2430
+ "div",
2431
+ {
2432
+ className: "biblography__note-body",
2433
+ dangerouslySetInnerHTML: { __html: note.html }
2434
+ }
2435
+ );
2436
+ }
2437
+ if (note.text) {
2438
+ return /* @__PURE__ */ React27.createElement("div", { className: "biblography__note-body" }, note.text);
2439
+ }
2440
+ return null;
2441
+ }
2442
+ function Biblography({
2443
+ className = "",
2444
+ pageHeadingTag = "h3"
2445
+ } = {}) {
2446
+ var _a, _b;
2447
+ let entries = [];
2448
+ try {
2449
+ entries = ((_b = (_a = bibliography) == null ? void 0 : _a.getBibliographyEntries) == null ? void 0 : _b.call(_a)) || [];
2450
+ } catch (_) {
2451
+ entries = [];
2452
+ }
2453
+ if (!entries.length) return null;
2454
+ const PageHeadingTag = resolveHeadingTag(pageHeadingTag, "h3");
2455
+ const rootClass = ["biblography", className].filter(Boolean).join(" ");
2456
+ return /* @__PURE__ */ React27.createElement("section", { className: rootClass }, /* @__PURE__ */ React27.createElement("div", { className: "biblography__pages" }, entries.map((entry) => {
2457
+ const key = entry.href || entry.relativePath || entry.title;
2458
+ const pageTitle = entry.title || entry.href;
2459
+ return /* @__PURE__ */ React27.createElement("article", { key, className: "biblography__page" }, /* @__PURE__ */ React27.createElement("header", { className: "biblography__page-header" }, pageTitle ? /* @__PURE__ */ React27.createElement(PageHeadingTag, { className: "biblography__page-title" }, pageTitle) : null, entry.href ? /* @__PURE__ */ React27.createElement("a", { className: "biblography__page-link", href: entry.href }, entry.href) : null), /* @__PURE__ */ React27.createElement("ol", { className: "biblography__notes" }, (entry.footnotes || []).map((note, idx) => {
2460
+ const noteKey = `${key || "entry"}-${note.identifier || idx}`;
2461
+ return /* @__PURE__ */ React27.createElement("li", { key: noteKey, className: "biblography__note" }, note.identifier ? /* @__PURE__ */ React27.createElement("span", { className: "biblography__note-label" }, note.identifier) : null, /* @__PURE__ */ React27.createElement(NoteBody, { note }));
2462
+ })));
2463
+ })));
2464
+ }
2465
+
2418
2466
  // ui/src/content/timeline/MdxTimeline.jsx
2419
- import React30 from "react";
2467
+ import React31 from "react";
2420
2468
  import ReactDOMServer from "react-dom/server";
2421
2469
 
2422
2470
  // ui/src/content/timeline/Timeline.jsx
2423
- import React28 from "react";
2471
+ import React29 from "react";
2424
2472
 
2425
2473
  // ui/src/content/timeline/date-utils.js
2426
2474
  var FALLBACK_LOCALE = (() => {
@@ -2581,7 +2629,7 @@ function clampProgress(value) {
2581
2629
  }
2582
2630
 
2583
2631
  // ui/src/layout/ReferencedManifestCard.jsx
2584
- import React27 from "react";
2632
+ import React28 from "react";
2585
2633
  function normalizeMetadata(metadata, summary) {
2586
2634
  if (Array.isArray(metadata) && metadata.length) {
2587
2635
  return metadata.filter(Boolean);
@@ -2615,7 +2663,7 @@ function ReferencedManifestCard({
2615
2663
  "canopy-referenced-manifest-card",
2616
2664
  className
2617
2665
  ].filter(Boolean).join(" ");
2618
- return /* @__PURE__ */ React27.createElement(
2666
+ return /* @__PURE__ */ React28.createElement(
2619
2667
  TeaserCard,
2620
2668
  {
2621
2669
  href: resolvedHref || void 0,
@@ -2797,14 +2845,14 @@ function TimelineConnector({ side, isActive, highlight }) {
2797
2845
  "canopy-timeline__connector-dot",
2798
2846
  highlight || isActive ? "is-active" : ""
2799
2847
  ].filter(Boolean).join(" ");
2800
- return /* @__PURE__ */ React28.createElement("span", { className: connectorClasses, "aria-hidden": "true" }, side === "left" ? /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement("span", { className: "canopy-timeline__connector-line" }), /* @__PURE__ */ React28.createElement("span", { className: dotClasses })) : /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement("span", { className: dotClasses }), /* @__PURE__ */ React28.createElement("span", { className: "canopy-timeline__connector-line" })));
2848
+ return /* @__PURE__ */ React29.createElement("span", { className: connectorClasses, "aria-hidden": "true" }, side === "left" ? /* @__PURE__ */ React29.createElement(React29.Fragment, null, /* @__PURE__ */ React29.createElement("span", { className: "canopy-timeline__connector-line" }), /* @__PURE__ */ React29.createElement("span", { className: dotClasses })) : /* @__PURE__ */ React29.createElement(React29.Fragment, null, /* @__PURE__ */ React29.createElement("span", { className: dotClasses }), /* @__PURE__ */ React29.createElement("span", { className: "canopy-timeline__connector-line" })));
2801
2849
  }
2802
2850
  function renderResourceSection(point) {
2803
2851
  if (!point) return null;
2804
2852
  const manifestCards = Array.isArray(point.manifests) ? point.manifests.filter(Boolean) : [];
2805
2853
  const legacyResources = Array.isArray(point.resources) ? point.resources.filter(Boolean) : [];
2806
2854
  if (!manifestCards.length && !legacyResources.length) return null;
2807
- return /* @__PURE__ */ React28.createElement("div", { className: "canopy-timeline__resources" }, /* @__PURE__ */ React28.createElement("div", { className: "canopy-timeline__resources-list" }, manifestCards.map((manifest) => /* @__PURE__ */ React28.createElement("div", { key: manifest.id || manifest.href }, /* @__PURE__ */ React28.createElement(ReferencedManifestCard, { manifest }))), legacyResources.map((resource, idx) => /* @__PURE__ */ React28.createElement("div", { key: resource.id || resource.href || `legacy-${idx}` }, /* @__PURE__ */ React28.createElement(
2855
+ return /* @__PURE__ */ React29.createElement("div", { className: "canopy-timeline__resources" }, /* @__PURE__ */ React29.createElement("div", { className: "canopy-timeline__resources-list" }, manifestCards.map((manifest) => /* @__PURE__ */ React29.createElement("div", { key: manifest.id || manifest.href }, /* @__PURE__ */ React29.createElement(ReferencedManifestCard, { manifest }))), legacyResources.map((resource, idx) => /* @__PURE__ */ React29.createElement("div", { key: resource.id || resource.href || `legacy-${idx}` }, /* @__PURE__ */ React29.createElement(
2808
2856
  TeaserCard,
2809
2857
  {
2810
2858
  href: resource.href,
@@ -2829,26 +2877,26 @@ function Timeline({
2829
2877
  ...rest
2830
2878
  }) {
2831
2879
  const payloadPoints = payload && Array.isArray(payload.points) ? payload.points : null;
2832
- const rawPoints = React28.useMemo(() => {
2880
+ const rawPoints = React29.useMemo(() => {
2833
2881
  if (Array.isArray(pointsProp) && pointsProp.length) return pointsProp;
2834
2882
  if (payloadPoints && payloadPoints.length) return payloadPoints;
2835
2883
  return [];
2836
2884
  }, [pointsProp, payloadPoints]);
2837
- const sanitizedPoints = React28.useMemo(
2885
+ const sanitizedPoints = React29.useMemo(
2838
2886
  () => sanitizePoints(rawPoints),
2839
2887
  [rawPoints]
2840
2888
  );
2841
2889
  const localeValue = payload && payload.locale ? payload.locale : localeProp;
2842
- const baseLocale = React28.useMemo(
2890
+ const baseLocale = React29.useMemo(
2843
2891
  () => createLocale(localeValue),
2844
2892
  [localeValue]
2845
2893
  );
2846
2894
  const rangeInput = payload && payload.range ? payload.range : rangeProp || {};
2847
- const rangeOverrides = React28.useMemo(
2895
+ const rangeOverrides = React29.useMemo(
2848
2896
  () => deriveRangeOverrides(sanitizedPoints, rangeInput),
2849
2897
  [sanitizedPoints, rangeInput]
2850
2898
  );
2851
- const effectiveRange = React28.useMemo(
2899
+ const effectiveRange = React29.useMemo(
2852
2900
  () => normalizeRange({
2853
2901
  ...rangeOverrides,
2854
2902
  locale: baseLocale
@@ -2857,7 +2905,7 @@ function Timeline({
2857
2905
  );
2858
2906
  const spanStart = effectiveRange.startDate.getTime();
2859
2907
  const span = effectiveRange.span;
2860
- const pointsWithPosition = React28.useMemo(() => {
2908
+ const pointsWithPosition = React29.useMemo(() => {
2861
2909
  if (!sanitizedPoints.length) return [];
2862
2910
  return sanitizedPoints.map((point, index) => {
2863
2911
  const timestamp = point.meta.timestamp;
@@ -2871,29 +2919,29 @@ function Timeline({
2871
2919
  };
2872
2920
  });
2873
2921
  }, [sanitizedPoints, spanStart, span]);
2874
- const [activeId, setActiveId] = React28.useState(
2922
+ const [activeId, setActiveId] = React29.useState(
2875
2923
  () => getActivePointId(pointsWithPosition)
2876
2924
  );
2877
- React28.useEffect(() => {
2925
+ React29.useEffect(() => {
2878
2926
  setActiveId(getActivePointId(pointsWithPosition));
2879
2927
  }, [pointsWithPosition]);
2880
2928
  const thresholdValue = typeof thresholdProp === "number" ? thresholdProp : payload && payload.threshold != null ? payload.threshold : null;
2881
2929
  const stepsValue = typeof steps === "number" ? Number(steps) : payload && typeof payload.steps === "number" ? Number(payload.steps) : null;
2882
- const thresholdMs = React28.useMemo(
2930
+ const thresholdMs = React29.useMemo(
2883
2931
  () => getThresholdMs(thresholdValue, effectiveRange.granularity),
2884
2932
  [thresholdValue, effectiveRange.granularity]
2885
2933
  );
2886
- const groupedEntries = React28.useMemo(
2934
+ const groupedEntries = React29.useMemo(
2887
2935
  () => buildGroupedEntries(pointsWithPosition, thresholdMs, {
2888
2936
  granularity: effectiveRange.granularity,
2889
2937
  locale: baseLocale
2890
2938
  }),
2891
2939
  [pointsWithPosition, thresholdMs, effectiveRange.granularity, baseLocale]
2892
2940
  );
2893
- const [expandedGroupIds, setExpandedGroupIds] = React28.useState(
2941
+ const [expandedGroupIds, setExpandedGroupIds] = React29.useState(
2894
2942
  () => /* @__PURE__ */ new Set()
2895
2943
  );
2896
- React28.useEffect(() => {
2944
+ React29.useEffect(() => {
2897
2945
  setExpandedGroupIds((prev) => {
2898
2946
  if (!prev || prev.size === 0) return prev;
2899
2947
  const validIds = new Set(
@@ -2908,7 +2956,7 @@ function Timeline({
2908
2956
  return changed ? next : prev;
2909
2957
  });
2910
2958
  }, [groupedEntries]);
2911
- const toggleGroup = React28.useCallback((groupId) => {
2959
+ const toggleGroup = React29.useCallback((groupId) => {
2912
2960
  setExpandedGroupIds((prev) => {
2913
2961
  const next = new Set(prev || []);
2914
2962
  if (next.has(groupId)) next.delete(groupId);
@@ -2931,7 +2979,7 @@ function Timeline({
2931
2979
  point.id === activeId ? "is-active" : "",
2932
2980
  point.highlight ? "is-highlighted" : ""
2933
2981
  ].filter(Boolean).join(" ");
2934
- const connector = /* @__PURE__ */ React28.createElement(
2982
+ const connector = /* @__PURE__ */ React29.createElement(
2935
2983
  TimelineConnector,
2936
2984
  {
2937
2985
  side: point.side,
@@ -2939,9 +2987,9 @@ function Timeline({
2939
2987
  highlight: point.highlight
2940
2988
  }
2941
2989
  );
2942
- const body = /* @__PURE__ */ React28.createElement("div", { className: "canopy-timeline__point-body" }, /* @__PURE__ */ React28.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label), /* @__PURE__ */ React28.createElement("span", { className: "canopy-timeline__point-title" }, point.title), point.summary ? /* @__PURE__ */ React28.createElement("span", { className: "canopy-timeline__point-summary" }, point.summary) : null);
2990
+ const body = /* @__PURE__ */ React29.createElement("div", { className: "canopy-timeline__point-body" }, /* @__PURE__ */ React29.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label), /* @__PURE__ */ React29.createElement("span", { className: "canopy-timeline__point-title" }, point.title), point.summary ? /* @__PURE__ */ React29.createElement("span", { className: "canopy-timeline__point-summary" }, point.summary) : null);
2943
2991
  const resourceSection = renderResourceSection(point);
2944
- return /* @__PURE__ */ React28.createElement(
2992
+ return /* @__PURE__ */ React29.createElement(
2945
2993
  "div",
2946
2994
  {
2947
2995
  key: point.id,
@@ -2949,7 +2997,7 @@ function Timeline({
2949
2997
  style: wrapperStyle,
2950
2998
  role: "listitem"
2951
2999
  },
2952
- point.side === "left" ? /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement("div", { className: cardClasses }, body, resourceSection), connector) : /* @__PURE__ */ React28.createElement(React28.Fragment, null, connector, /* @__PURE__ */ React28.createElement("div", { className: cardClasses }, body, resourceSection))
3000
+ point.side === "left" ? /* @__PURE__ */ React29.createElement(React29.Fragment, null, /* @__PURE__ */ React29.createElement("div", { className: cardClasses }, body, resourceSection), connector) : /* @__PURE__ */ React29.createElement(React29.Fragment, null, connector, /* @__PURE__ */ React29.createElement("div", { className: cardClasses }, body, resourceSection))
2953
3001
  );
2954
3002
  }
2955
3003
  function renderGroupEntry(entry) {
@@ -2960,7 +3008,7 @@ function Timeline({
2960
3008
  const wrapperStyle = { top: `${entry.progress * 100}%` };
2961
3009
  const isExpanded = expandedGroupIds.has(entry.id);
2962
3010
  const hasActivePoint = entry.points.some((point) => point.id === activeId);
2963
- const connector = /* @__PURE__ */ React28.createElement(
3011
+ const connector = /* @__PURE__ */ React29.createElement(
2964
3012
  TimelineConnector,
2965
3013
  {
2966
3014
  side: entry.side,
@@ -2974,7 +3022,7 @@ function Timeline({
2974
3022
  hasActivePoint ? "is-active" : ""
2975
3023
  ].filter(Boolean).join(" ");
2976
3024
  const countLabel = `${entry.count} event${entry.count > 1 ? "s" : ""}`;
2977
- const header = /* @__PURE__ */ React28.createElement("div", { className: "canopy-timeline__group-header" }, /* @__PURE__ */ React28.createElement("div", { className: "canopy-timeline__group-summary" }, /* @__PURE__ */ React28.createElement("span", { className: "canopy-timeline__point-date" }, entry.label), /* @__PURE__ */ React28.createElement("span", { className: "canopy-timeline__group-count" }, countLabel)), /* @__PURE__ */ React28.createElement(
3025
+ const header = /* @__PURE__ */ React29.createElement("div", { className: "canopy-timeline__group-header" }, /* @__PURE__ */ React29.createElement("div", { className: "canopy-timeline__group-summary" }, /* @__PURE__ */ React29.createElement("span", { className: "canopy-timeline__point-date" }, entry.label), /* @__PURE__ */ React29.createElement("span", { className: "canopy-timeline__group-count" }, countLabel)), /* @__PURE__ */ React29.createElement(
2978
3026
  "button",
2979
3027
  {
2980
3028
  type: "button",
@@ -2984,7 +3032,7 @@ function Timeline({
2984
3032
  },
2985
3033
  isExpanded ? "Hide details" : "Show details"
2986
3034
  ));
2987
- const groupPoints = isExpanded ? /* @__PURE__ */ React28.createElement("div", { className: "canopy-timeline__group-points" }, entry.points.map((point) => /* @__PURE__ */ React28.createElement(
3035
+ const groupPoints = isExpanded ? /* @__PURE__ */ React29.createElement("div", { className: "canopy-timeline__group-points" }, entry.points.map((point) => /* @__PURE__ */ React29.createElement(
2988
3036
  "button",
2989
3037
  {
2990
3038
  key: point.id,
@@ -2995,11 +3043,11 @@ function Timeline({
2995
3043
  ].filter(Boolean).join(" "),
2996
3044
  onClick: () => setActiveId(point.id)
2997
3045
  },
2998
- /* @__PURE__ */ React28.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label),
2999
- /* @__PURE__ */ React28.createElement("span", { className: "canopy-timeline__group-point-title" }, point.title)
3046
+ /* @__PURE__ */ React29.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label),
3047
+ /* @__PURE__ */ React29.createElement("span", { className: "canopy-timeline__group-point-title" }, point.title)
3000
3048
  ))) : null;
3001
- const groupCard = /* @__PURE__ */ React28.createElement("div", { className: groupClasses }, header, groupPoints);
3002
- return /* @__PURE__ */ React28.createElement(
3049
+ const groupCard = /* @__PURE__ */ React29.createElement("div", { className: groupClasses }, header, groupPoints);
3050
+ return /* @__PURE__ */ React29.createElement(
3003
3051
  "div",
3004
3052
  {
3005
3053
  key: entry.id,
@@ -3007,17 +3055,17 @@ function Timeline({
3007
3055
  style: wrapperStyle,
3008
3056
  role: "listitem"
3009
3057
  },
3010
- entry.side === "left" ? /* @__PURE__ */ React28.createElement(React28.Fragment, null, groupCard, connector) : /* @__PURE__ */ React28.createElement(React28.Fragment, null, connector, groupCard)
3058
+ entry.side === "left" ? /* @__PURE__ */ React29.createElement(React29.Fragment, null, groupCard, connector) : /* @__PURE__ */ React29.createElement(React29.Fragment, null, connector, groupCard)
3011
3059
  );
3012
3060
  }
3013
- return /* @__PURE__ */ React28.createElement("section", { className: containerClasses, ...rest }, title ? /* @__PURE__ */ React28.createElement("h2", { className: "canopy-timeline__title" }, title) : null, description ? /* @__PURE__ */ React28.createElement("p", { className: "canopy-timeline__description" }, description) : null, rangeLabel ? /* @__PURE__ */ React28.createElement("p", { className: "canopy-timeline__range", "aria-live": "polite" }, rangeLabel) : null, /* @__PURE__ */ React28.createElement("div", { className: "canopy-timeline__body" }, /* @__PURE__ */ React28.createElement(
3061
+ return /* @__PURE__ */ React29.createElement("section", { className: containerClasses, ...rest }, title ? /* @__PURE__ */ React29.createElement("h2", { className: "canopy-timeline__title" }, title) : null, description ? /* @__PURE__ */ React29.createElement("p", { className: "canopy-timeline__description" }, description) : null, rangeLabel ? /* @__PURE__ */ React29.createElement("p", { className: "canopy-timeline__range", "aria-live": "polite" }, rangeLabel) : null, /* @__PURE__ */ React29.createElement("div", { className: "canopy-timeline__body" }, /* @__PURE__ */ React29.createElement(
3014
3062
  "div",
3015
3063
  {
3016
3064
  className: "canopy-timeline__list",
3017
3065
  role: "list",
3018
3066
  style: { minHeight: trackHeight }
3019
3067
  },
3020
- /* @__PURE__ */ React28.createElement("div", { className: "canopy-timeline__spine", "aria-hidden": "true" }),
3068
+ /* @__PURE__ */ React29.createElement("div", { className: "canopy-timeline__spine", "aria-hidden": "true" }),
3021
3069
  renderSteps(stepsValue, effectiveRange),
3022
3070
  groupedEntries.map((entry) => {
3023
3071
  if (entry.type === "group") return renderGroupEntry(entry);
@@ -3032,7 +3080,7 @@ function renderSteps(stepSize, range) {
3032
3080
  const markers = [];
3033
3081
  if (startYear < endYear) {
3034
3082
  markers.push(
3035
- /* @__PURE__ */ React28.createElement(
3083
+ /* @__PURE__ */ React29.createElement(
3036
3084
  "span",
3037
3085
  {
3038
3086
  key: "timeline-step-start",
@@ -3040,12 +3088,12 @@ function renderSteps(stepSize, range) {
3040
3088
  style: { top: "0%" },
3041
3089
  "aria-hidden": "true"
3042
3090
  },
3043
- /* @__PURE__ */ React28.createElement("span", { className: "canopy-timeline__step-line" }),
3044
- /* @__PURE__ */ React28.createElement("span", { className: "canopy-timeline__step-label" }, startYear)
3091
+ /* @__PURE__ */ React29.createElement("span", { className: "canopy-timeline__step-line" }),
3092
+ /* @__PURE__ */ React29.createElement("span", { className: "canopy-timeline__step-label" }, startYear)
3045
3093
  )
3046
3094
  );
3047
3095
  markers.push(
3048
- /* @__PURE__ */ React28.createElement(
3096
+ /* @__PURE__ */ React29.createElement(
3049
3097
  "span",
3050
3098
  {
3051
3099
  key: "timeline-step-end",
@@ -3053,8 +3101,8 @@ function renderSteps(stepSize, range) {
3053
3101
  style: { top: "100%" },
3054
3102
  "aria-hidden": "true"
3055
3103
  },
3056
- /* @__PURE__ */ React28.createElement("span", { className: "canopy-timeline__step-line" }),
3057
- /* @__PURE__ */ React28.createElement("span", { className: "canopy-timeline__step-label" }, endYear)
3104
+ /* @__PURE__ */ React29.createElement("span", { className: "canopy-timeline__step-line" }),
3105
+ /* @__PURE__ */ React29.createElement("span", { className: "canopy-timeline__step-label" }, endYear)
3058
3106
  )
3059
3107
  );
3060
3108
  }
@@ -3064,7 +3112,7 @@ function renderSteps(stepSize, range) {
3064
3112
  const progress = (timestamp - range.startDate.getTime()) / range.span;
3065
3113
  if (progress <= 0 || progress >= 1) continue;
3066
3114
  markers.push(
3067
- /* @__PURE__ */ React28.createElement(
3115
+ /* @__PURE__ */ React29.createElement(
3068
3116
  "span",
3069
3117
  {
3070
3118
  key: `timeline-step-${year}`,
@@ -3072,8 +3120,8 @@ function renderSteps(stepSize, range) {
3072
3120
  style: { top: `calc(${progress * 100}% - 0.5px)` },
3073
3121
  "aria-hidden": "true"
3074
3122
  },
3075
- /* @__PURE__ */ React28.createElement("span", { className: "canopy-timeline__step-line" }),
3076
- /* @__PURE__ */ React28.createElement("span", { className: "canopy-timeline__step-label" }, year)
3123
+ /* @__PURE__ */ React29.createElement("span", { className: "canopy-timeline__step-line" }),
3124
+ /* @__PURE__ */ React29.createElement("span", { className: "canopy-timeline__step-label" }, year)
3077
3125
  )
3078
3126
  );
3079
3127
  }
@@ -3087,7 +3135,7 @@ function TimelinePoint() {
3087
3135
  TimelinePoint.displayName = "TimelinePoint";
3088
3136
 
3089
3137
  // ui/src/utils/manifestReferences.js
3090
- import React29 from "react";
3138
+ import React30 from "react";
3091
3139
  import navigationHelpers6 from "@canopy-iiif/app/lib/components/navigation.js";
3092
3140
  function normalizeManifestId(raw) {
3093
3141
  if (!raw) return "";
@@ -3104,13 +3152,13 @@ function normalizeManifestId(raw) {
3104
3152
  return String(raw || "").trim();
3105
3153
  }
3106
3154
  }
3107
- var PageContextFallback = React29.createContext(null);
3155
+ var PageContextFallback = React30.createContext(null);
3108
3156
  function useReferencedManifestMap() {
3109
3157
  var _a, _b;
3110
3158
  const PageContext = ((_b = (_a = navigationHelpers6) == null ? void 0 : _a.getPageContext) == null ? void 0 : _b.call(_a)) || PageContextFallback;
3111
- const pageContext = React29.useContext(PageContext);
3159
+ const pageContext = React30.useContext(PageContext);
3112
3160
  const referencedItems = pageContext && pageContext.page && Array.isArray(pageContext.page.referencedItems) ? pageContext.page.referencedItems : [];
3113
- return React29.useMemo(() => {
3161
+ return React30.useMemo(() => {
3114
3162
  const map = /* @__PURE__ */ new Map();
3115
3163
  referencedItems.forEach((item) => {
3116
3164
  if (!item) return;
@@ -3165,7 +3213,7 @@ function normalizeResource(resource, index) {
3165
3213
  }
3166
3214
  function normalizePoint(child, index, options) {
3167
3215
  var _a, _b, _c, _d, _e, _f;
3168
- if (!React30.isValidElement(child)) return null;
3216
+ if (!React31.isValidElement(child)) return null;
3169
3217
  if (child.type !== TimelinePoint && ((_a = child.type) == null ? void 0 : _a.displayName) !== "TimelinePoint")
3170
3218
  return null;
3171
3219
  const props = child.props || {};
@@ -3181,7 +3229,7 @@ function normalizePoint(child, index, options) {
3181
3229
  try {
3182
3230
  if (props.children) {
3183
3231
  detailsHtml = ReactDOMServer.renderToStaticMarkup(
3184
- React30.createElement(React30.Fragment, null, props.children)
3232
+ React31.createElement(React31.Fragment, null, props.children)
3185
3233
  );
3186
3234
  }
3187
3235
  } catch (_) {
@@ -3230,7 +3278,7 @@ function MdxTimeline({ children, ...rest }) {
3230
3278
  const localeObj = createLocale(localeValue);
3231
3279
  const localeBase = typeof localeObj === "string" ? localeObj : localeObj.baseName || "en-US";
3232
3280
  const manifestMap = useReferencedManifestMap();
3233
- const childArray = React30.Children.toArray(children);
3281
+ const childArray = React31.Children.toArray(children);
3234
3282
  const points = childArray.map(
3235
3283
  (child, index) => normalizePoint(child, index, {
3236
3284
  range: rest.range || {},
@@ -3246,7 +3294,7 @@ function MdxTimeline({ children, ...rest }) {
3246
3294
  steps: rest.steps != null ? rest.steps : null
3247
3295
  };
3248
3296
  const json = serializeForScript(serializeProps(rest, payload, localeBase));
3249
- return /* @__PURE__ */ React30.createElement("div", { "data-canopy-timeline": "1" }, /* @__PURE__ */ React30.createElement(Timeline, { ...rest, __canopyTimeline: payload }), /* @__PURE__ */ React30.createElement(
3297
+ return /* @__PURE__ */ React31.createElement("div", { "data-canopy-timeline": "1" }, /* @__PURE__ */ React31.createElement(Timeline, { ...rest, __canopyTimeline: payload }), /* @__PURE__ */ React31.createElement(
3250
3298
  "script",
3251
3299
  {
3252
3300
  type: "application/json",
@@ -3256,7 +3304,7 @@ function MdxTimeline({ children, ...rest }) {
3256
3304
  }
3257
3305
 
3258
3306
  // ui/src/content/map/MdxMap.jsx
3259
- import React31 from "react";
3307
+ import React32 from "react";
3260
3308
  import ReactDOMServer2 from "react-dom/server";
3261
3309
 
3262
3310
  // ui/src/content/map/MapPoint.jsx
@@ -3283,7 +3331,7 @@ function renderDetailsHtml(children) {
3283
3331
  if (!children) return "";
3284
3332
  try {
3285
3333
  return ReactDOMServer2.renderToStaticMarkup(
3286
- React31.createElement(React31.Fragment, null, children)
3334
+ React32.createElement(React32.Fragment, null, children)
3287
3335
  );
3288
3336
  } catch (_) {
3289
3337
  return "";
@@ -3291,7 +3339,7 @@ function renderDetailsHtml(children) {
3291
3339
  }
3292
3340
  function normalizeCustomPoint(child, index, manifestMap) {
3293
3341
  var _a;
3294
- if (!React31.isValidElement(child)) return null;
3342
+ if (!React32.isValidElement(child)) return null;
3295
3343
  if (child.type !== MapPoint && ((_a = child.type) == null ? void 0 : _a.displayName) !== "MapPoint") return null;
3296
3344
  const coords = normalizeCoordinates(child.props || {});
3297
3345
  if (!coords) return null;
@@ -3336,7 +3384,7 @@ function normalizeCustomPoint(child, index, manifestMap) {
3336
3384
  };
3337
3385
  }
3338
3386
  function normalizeCustomPoints(children, manifestMap) {
3339
- return React31.Children.toArray(children).map((child, index) => normalizeCustomPoint(child, index, manifestMap)).filter(Boolean);
3387
+ return React32.Children.toArray(children).map((child, index) => normalizeCustomPoint(child, index, manifestMap)).filter(Boolean);
3340
3388
  }
3341
3389
  function normalizeHeight(value) {
3342
3390
  if (value == null) return "600px";
@@ -3474,11 +3522,11 @@ function MdxMap({ children, ...rest }) {
3474
3522
  if (placeholderClass) placeholderProps.className = placeholderClass;
3475
3523
  if (rest.id) placeholderProps.id = rest.id;
3476
3524
  if (rest.style) placeholderProps.style = rest.style;
3477
- return /* @__PURE__ */ React31.createElement("div", { "data-canopy-map": "1" }, /* @__PURE__ */ React31.createElement("div", { ...placeholderProps, "aria-live": "polite" }, /* @__PURE__ */ React31.createElement("div", { className: "canopy-map__status" }, "Loading map\u2026")), /* @__PURE__ */ React31.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3525
+ return /* @__PURE__ */ React32.createElement("div", { "data-canopy-map": "1" }, /* @__PURE__ */ React32.createElement("div", { ...placeholderProps, "aria-live": "polite" }, /* @__PURE__ */ React32.createElement("div", { className: "canopy-map__status" }, "Loading map\u2026")), /* @__PURE__ */ React32.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3478
3526
  }
3479
3527
 
3480
3528
  // ui/src/search/MdxSearchResults.jsx
3481
- import React32 from "react";
3529
+ import React33 from "react";
3482
3530
  function MdxSearchResults(props) {
3483
3531
  let json = "{}";
3484
3532
  try {
@@ -3486,11 +3534,11 @@ function MdxSearchResults(props) {
3486
3534
  } catch (_) {
3487
3535
  json = "{}";
3488
3536
  }
3489
- return /* @__PURE__ */ React32.createElement("div", { "data-canopy-search-results": "1" }, /* @__PURE__ */ React32.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3537
+ return /* @__PURE__ */ React33.createElement("div", { "data-canopy-search-results": "1" }, /* @__PURE__ */ React33.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3490
3538
  }
3491
3539
 
3492
3540
  // ui/src/search/SearchSummary.jsx
3493
- import React33 from "react";
3541
+ import React34 from "react";
3494
3542
  function SearchSummary(props) {
3495
3543
  let json = "{}";
3496
3544
  try {
@@ -3498,11 +3546,11 @@ function SearchSummary(props) {
3498
3546
  } catch (_) {
3499
3547
  json = "{}";
3500
3548
  }
3501
- return /* @__PURE__ */ React33.createElement("div", { "data-canopy-search-summary": "1" }, /* @__PURE__ */ React33.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3549
+ return /* @__PURE__ */ React34.createElement("div", { "data-canopy-search-summary": "1" }, /* @__PURE__ */ React34.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3502
3550
  }
3503
3551
 
3504
3552
  // ui/src/search/MdxSearchTabs.jsx
3505
- import React34 from "react";
3553
+ import React35 from "react";
3506
3554
  function MdxSearchTabs(props) {
3507
3555
  let json = "{}";
3508
3556
  try {
@@ -3510,11 +3558,11 @@ function MdxSearchTabs(props) {
3510
3558
  } catch (_) {
3511
3559
  json = "{}";
3512
3560
  }
3513
- return /* @__PURE__ */ React34.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React34.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3561
+ return /* @__PURE__ */ React35.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React35.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3514
3562
  }
3515
3563
 
3516
3564
  // ui/src/search/MdxSearch.jsx
3517
- import React35 from "react";
3565
+ import React36 from "react";
3518
3566
  function MdxSearch(props = {}) {
3519
3567
  const {
3520
3568
  layout,
@@ -3532,11 +3580,11 @@ function MdxSearch(props = {}) {
3532
3580
  resultsPayload.layout = layout;
3533
3581
  }
3534
3582
  const classes = ["canopy-search", className].filter(Boolean).join(" ");
3535
- return /* @__PURE__ */ React35.createElement("section", { className: classes, "data-canopy-search": "1" }, showTabs ? /* @__PURE__ */ React35.createElement(MdxSearchTabs, { ...tabsProps }) : null, showSummary ? /* @__PURE__ */ React35.createElement(SearchSummary, { ...summaryProps }) : null, showResults ? /* @__PURE__ */ React35.createElement(MdxSearchResults, { ...resultsPayload }) : null, children || null);
3583
+ return /* @__PURE__ */ React36.createElement("section", { className: classes, "data-canopy-search": "1" }, showTabs ? /* @__PURE__ */ React36.createElement(MdxSearchTabs, { ...tabsProps }) : null, showSummary ? /* @__PURE__ */ React36.createElement(SearchSummary, { ...summaryProps }) : null, showResults ? /* @__PURE__ */ React36.createElement(MdxSearchResults, { ...resultsPayload }) : null, children || null);
3536
3584
  }
3537
3585
 
3538
3586
  // ui/src/search-form/MdxSearchFormModal.jsx
3539
- import React36 from "react";
3587
+ import React37 from "react";
3540
3588
  function MdxSearchFormModal(props = {}) {
3541
3589
  const {
3542
3590
  placeholder = "Search\u2026",
@@ -3552,12 +3600,12 @@ function MdxSearchFormModal(props = {}) {
3552
3600
  const text = typeof label === "string" && label.trim() ? label.trim() : buttonLabel;
3553
3601
  const resolvedSearchPath = resolveSearchPath(searchPath);
3554
3602
  const data = { placeholder, hotkey, maxResults, groupOrder, label: text, searchPath: resolvedSearchPath };
3555
- 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) } }));
3603
+ return /* @__PURE__ */ React37.createElement("div", { "data-canopy-search-form": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React37.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React37.createElement(SearchPanelForm, { placeholder, buttonLabel, label, searchPath: resolvedSearchPath }), /* @__PURE__ */ React37.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React37.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
3556
3604
  }
3557
3605
 
3558
3606
  // ui/src/iiif/ManifestPrimitives.jsx
3559
3607
  var import_slugify = __toESM(require_slugify());
3560
- import React37 from "react";
3608
+ import React38 from "react";
3561
3609
  import {
3562
3610
  Label as CloverLabel,
3563
3611
  Metadata as CloverMetadata,
@@ -3698,7 +3746,7 @@ function MetadataFacetLink(props) {
3698
3746
  const valueSlug = facetSlug ? toValueSlug(text) : "";
3699
3747
  const href = facetSlug && valueSlug ? buildFacetSearchHref(facetSlug, valueSlug) : "";
3700
3748
  if (!href) return text;
3701
- return /* @__PURE__ */ React37.createElement(
3749
+ return /* @__PURE__ */ React38.createElement(
3702
3750
  "a",
3703
3751
  {
3704
3752
  href,
@@ -3724,7 +3772,7 @@ function buildFacetCustomValueContent(items, manifest) {
3724
3772
  seen.add(normalized);
3725
3773
  custom.push({
3726
3774
  matchingLabel: item.label,
3727
- Content: /* @__PURE__ */ React37.createElement(MetadataFacetLink, { facetSlug: facet.slug })
3775
+ Content: /* @__PURE__ */ React38.createElement(MetadataFacetLink, { facetSlug: facet.slug })
3728
3776
  });
3729
3777
  }
3730
3778
  return custom;
@@ -3756,12 +3804,12 @@ function mergeCustomValueContent(userContent, autoContent) {
3756
3804
  function Label({ manifest, label, ...rest }) {
3757
3805
  const intl = label || manifest && manifest.label;
3758
3806
  if (!hasInternationalValue(intl)) return null;
3759
- return /* @__PURE__ */ React37.createElement(CloverLabel, { label: intl, ...rest });
3807
+ return /* @__PURE__ */ React38.createElement(CloverLabel, { label: intl, ...rest });
3760
3808
  }
3761
3809
  function Summary({ manifest, summary, ...rest }) {
3762
3810
  const intl = summary || manifest && manifest.summary;
3763
3811
  if (!hasInternationalValue(intl)) return null;
3764
- return /* @__PURE__ */ React37.createElement(CloverSummary, { summary: intl, ...rest });
3812
+ return /* @__PURE__ */ React38.createElement(CloverSummary, { summary: intl, ...rest });
3765
3813
  }
3766
3814
  function Metadata({ manifest, metadata, customValueContent, ...rest }) {
3767
3815
  const items = ensureMetadata(metadata || manifest && manifest.metadata);
@@ -3771,7 +3819,7 @@ function Metadata({ manifest, metadata, customValueContent, ...rest }) {
3771
3819
  customValueContent,
3772
3820
  autoCustomContent
3773
3821
  );
3774
- return /* @__PURE__ */ React37.createElement(
3822
+ return /* @__PURE__ */ React38.createElement(
3775
3823
  CloverMetadata,
3776
3824
  {
3777
3825
  metadata: items,
@@ -3785,11 +3833,11 @@ function RequiredStatement({ manifest, requiredStatement, ...rest }) {
3785
3833
  if (!stmt || !hasInternationalValue(stmt.label) || !hasInternationalValue(stmt.value)) {
3786
3834
  return null;
3787
3835
  }
3788
- return /* @__PURE__ */ React37.createElement(CloverRequiredStatement, { requiredStatement: stmt, ...rest });
3836
+ return /* @__PURE__ */ React38.createElement(CloverRequiredStatement, { requiredStatement: stmt, ...rest });
3789
3837
  }
3790
3838
 
3791
3839
  // ui/src/docs/CodeBlock.jsx
3792
- import React38 from "react";
3840
+ import React39 from "react";
3793
3841
  function parseHighlightAttr(attr) {
3794
3842
  if (!attr) return /* @__PURE__ */ new Set();
3795
3843
  const cleaned = String(attr || "").trim();
@@ -3835,10 +3883,10 @@ var highlightBaseStyle = {
3835
3883
  };
3836
3884
  function DocsCodeBlock(props = {}) {
3837
3885
  const { children, ...rest } = props;
3838
- const childArray = React38.Children.toArray(children);
3839
- const codeElement = childArray.find((el) => React38.isValidElement(el));
3886
+ const childArray = React39.Children.toArray(children);
3887
+ const codeElement = childArray.find((el) => React39.isValidElement(el));
3840
3888
  if (!codeElement || !codeElement.props) {
3841
- return React38.createElement("pre", props);
3889
+ return React39.createElement("pre", props);
3842
3890
  }
3843
3891
  const {
3844
3892
  className = "",
@@ -3853,8 +3901,8 @@ function DocsCodeBlock(props = {}) {
3853
3901
  const highlightSet = parseHighlightAttr(highlightAttr);
3854
3902
  const copyAttr = codeProps["data-copy"];
3855
3903
  const enableCopy = copyAttr !== void 0 ? copyAttr === true || copyAttr === "true" || copyAttr === "" : false;
3856
- const [copied, setCopied] = React38.useState(false);
3857
- const handleCopy = React38.useCallback(async () => {
3904
+ const [copied, setCopied] = React39.useState(false);
3905
+ const handleCopy = React39.useCallback(async () => {
3858
3906
  const text = rawCode;
3859
3907
  try {
3860
3908
  if (typeof navigator !== "undefined" && navigator.clipboard && navigator.clipboard.writeText) {
@@ -3919,20 +3967,20 @@ function DocsCodeBlock(props = {}) {
3919
3967
  const highlight = highlightSet.has(lineNumber);
3920
3968
  const style = highlight ? { ...baseLineStyle, ...highlightBaseStyle } : baseLineStyle;
3921
3969
  const displayLine = line === "" ? " " : line;
3922
- return React38.createElement(
3970
+ return React39.createElement(
3923
3971
  "span",
3924
3972
  { key: lineNumber, style },
3925
- React38.createElement("span", { style: lineContentStyle }, displayLine)
3973
+ React39.createElement("span", { style: lineContentStyle }, displayLine)
3926
3974
  );
3927
3975
  });
3928
- return React38.createElement(
3976
+ return React39.createElement(
3929
3977
  "div",
3930
3978
  { style: containerStyle },
3931
- showHeader ? React38.createElement(
3979
+ showHeader ? React39.createElement(
3932
3980
  "div",
3933
3981
  { style: headerStyle },
3934
- React38.createElement("span", null, showFilename ? filename : null),
3935
- enableCopy ? React38.createElement(
3982
+ React39.createElement("span", null, showFilename ? filename : null),
3983
+ enableCopy ? React39.createElement(
3936
3984
  "button",
3937
3985
  {
3938
3986
  type: "button",
@@ -3951,29 +3999,29 @@ function DocsCodeBlock(props = {}) {
3951
3999
  copied ? "Copied" : "Copy"
3952
4000
  ) : null
3953
4001
  ) : null,
3954
- React38.createElement(
4002
+ React39.createElement(
3955
4003
  "pre",
3956
4004
  { ...preRest, className: preClassName, style: mergedPreStyle },
3957
- React38.createElement("code", { style: codeStyle }, lineElements)
4005
+ React39.createElement("code", { style: codeStyle }, lineElements)
3958
4006
  )
3959
4007
  );
3960
4008
  }
3961
4009
 
3962
4010
  // ui/src/docs/MarkdownTable.jsx
3963
- import React39 from "react";
4011
+ import React40 from "react";
3964
4012
  function MarkdownTable({ className = "", ...rest }) {
3965
4013
  const merged = ["markdown-table", className].filter(Boolean).join(" ");
3966
- return /* @__PURE__ */ React39.createElement("div", { className: "markdown-table__frame" }, /* @__PURE__ */ React39.createElement("table", { className: merged, ...rest }));
4014
+ return /* @__PURE__ */ React40.createElement("div", { className: "markdown-table__frame" }, /* @__PURE__ */ React40.createElement("table", { className: merged, ...rest }));
3967
4015
  }
3968
4016
 
3969
4017
  // ui/src/docs/Diagram.jsx
3970
- import React40 from "react";
4018
+ import React41 from "react";
3971
4019
  function CanopyDiagram() {
3972
- return /* @__PURE__ */ React40.createElement("div", { className: "canopy-diagram" }, /* @__PURE__ */ React40.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--collections" }, /* @__PURE__ */ React40.createElement("h3", null, "IIIF Collection(s)"), /* @__PURE__ */ React40.createElement("span", { className: "canopy-diagram__section-summary" }, "Source collections contribute 105 total manifests that Canopy retrieves as-is via IIIF endpoints."), /* @__PURE__ */ React40.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React40.createElement("article", null, /* @__PURE__ */ React40.createElement("h4", null, "Collection A"), /* @__PURE__ */ React40.createElement("ul", null, /* @__PURE__ */ React40.createElement("li", null, "70 Manifests"), /* @__PURE__ */ React40.createElement("li", null, "IIIF Images + A/V"), /* @__PURE__ */ React40.createElement("li", null, "Textual Annotations"))), /* @__PURE__ */ React40.createElement("article", null, /* @__PURE__ */ React40.createElement("h4", null, "Collection B"), /* @__PURE__ */ React40.createElement("ul", null, /* @__PURE__ */ React40.createElement("li", null, "35 Manifests"), /* @__PURE__ */ React40.createElement("li", null, "IIIF Images + A/V"), /* @__PURE__ */ React40.createElement("li", null, "Textual Annotations"))))), /* @__PURE__ */ React40.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React40.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React40.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React40.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--build" }, /* @__PURE__ */ React40.createElement("h3", null, "Canopy Build Process"), /* @__PURE__ */ React40.createElement("span", { className: "canopy-diagram__section-summary" }, "Canopy syncs manifests, page content, and annotations before bundling the site."), /* @__PURE__ */ React40.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React40.createElement("article", null, /* @__PURE__ */ React40.createElement("h4", null, "Automated content"), /* @__PURE__ */ React40.createElement("ul", null, /* @__PURE__ */ React40.createElement("li", null, "105 manifests \u2192 105 work pages"), /* @__PURE__ */ React40.createElement("li", null, "One page per manifest"), /* @__PURE__ */ React40.createElement("li", null, "Customize page layout"))), /* @__PURE__ */ React40.createElement("article", null, /* @__PURE__ */ React40.createElement("h4", null, "Contextual content"), /* @__PURE__ */ React40.createElement("ul", null, /* @__PURE__ */ React40.createElement("li", null, "Markdown & MDX pages"), /* @__PURE__ */ React40.createElement("li", null, "Author narratives"), /* @__PURE__ */ React40.createElement("li", null, "Reference manifests inline"))), /* @__PURE__ */ React40.createElement("article", null, /* @__PURE__ */ React40.createElement("h4", null, "Search index"), /* @__PURE__ */ React40.createElement("ul", null, /* @__PURE__ */ React40.createElement("li", null, "Combines works + pages"), /* @__PURE__ */ React40.createElement("li", null, "Customize result layout"), /* @__PURE__ */ React40.createElement("li", null, "Optional annotations"))))), /* @__PURE__ */ React40.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React40.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React40.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React40.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--output" }, /* @__PURE__ */ React40.createElement("h3", null, "Static Digital Project"), /* @__PURE__ */ React40.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__ */ React40.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React40.createElement("article", null, /* @__PURE__ */ React40.createElement("h4", null, "Work pages"), /* @__PURE__ */ React40.createElement("ul", null, /* @__PURE__ */ React40.createElement("li", null, "105 generated HTML pages"), /* @__PURE__ */ React40.createElement("li", null, "Each links back to source manifests"), /* @__PURE__ */ React40.createElement("li", null, "Styled with Canopy components"))), /* @__PURE__ */ React40.createElement("article", null, /* @__PURE__ */ React40.createElement("h4", null, "Custom pages"), /* @__PURE__ */ React40.createElement("ul", null, /* @__PURE__ */ React40.createElement("li", null, "Markdown & MDX-authored content"), /* @__PURE__ */ React40.createElement("li", null, "Reusable layouts for narratives"), /* @__PURE__ */ React40.createElement("li", null, "Embed IIIF media & interstitials"))), /* @__PURE__ */ React40.createElement("article", null, /* @__PURE__ */ React40.createElement("h4", null, "Search bundle"), /* @__PURE__ */ React40.createElement("ul", null, /* @__PURE__ */ React40.createElement("li", null, "Static FlexSearch index"), /* @__PURE__ */ React40.createElement("li", null, "Works + pages share records"), /* @__PURE__ */ React40.createElement("li", null, "Optional annotation dataset"))))));
4020
+ return /* @__PURE__ */ React41.createElement("div", { className: "canopy-diagram" }, /* @__PURE__ */ React41.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--collections" }, /* @__PURE__ */ React41.createElement("h3", null, "IIIF Collection(s)"), /* @__PURE__ */ React41.createElement("span", { className: "canopy-diagram__section-summary" }, "Source collections contribute 105 total manifests that Canopy retrieves as-is via IIIF endpoints."), /* @__PURE__ */ React41.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React41.createElement("article", null, /* @__PURE__ */ React41.createElement("h4", null, "Collection A"), /* @__PURE__ */ React41.createElement("ul", null, /* @__PURE__ */ React41.createElement("li", null, "70 Manifests"), /* @__PURE__ */ React41.createElement("li", null, "IIIF Images + A/V"), /* @__PURE__ */ React41.createElement("li", null, "Textual Annotations"))), /* @__PURE__ */ React41.createElement("article", null, /* @__PURE__ */ React41.createElement("h4", null, "Collection B"), /* @__PURE__ */ React41.createElement("ul", null, /* @__PURE__ */ React41.createElement("li", null, "35 Manifests"), /* @__PURE__ */ React41.createElement("li", null, "IIIF Images + A/V"), /* @__PURE__ */ React41.createElement("li", null, "Textual Annotations"))))), /* @__PURE__ */ React41.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React41.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React41.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React41.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--build" }, /* @__PURE__ */ React41.createElement("h3", null, "Canopy Build Process"), /* @__PURE__ */ React41.createElement("span", { className: "canopy-diagram__section-summary" }, "Canopy syncs manifests, page content, and annotations before bundling the site."), /* @__PURE__ */ React41.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React41.createElement("article", null, /* @__PURE__ */ React41.createElement("h4", null, "Automated content"), /* @__PURE__ */ React41.createElement("ul", null, /* @__PURE__ */ React41.createElement("li", null, "105 manifests \u2192 105 work pages"), /* @__PURE__ */ React41.createElement("li", null, "One page per manifest"), /* @__PURE__ */ React41.createElement("li", null, "Customize page layout"))), /* @__PURE__ */ React41.createElement("article", null, /* @__PURE__ */ React41.createElement("h4", null, "Contextual content"), /* @__PURE__ */ React41.createElement("ul", null, /* @__PURE__ */ React41.createElement("li", null, "Markdown & MDX pages"), /* @__PURE__ */ React41.createElement("li", null, "Author narratives"), /* @__PURE__ */ React41.createElement("li", null, "Reference manifests inline"))), /* @__PURE__ */ React41.createElement("article", null, /* @__PURE__ */ React41.createElement("h4", null, "Search index"), /* @__PURE__ */ React41.createElement("ul", null, /* @__PURE__ */ React41.createElement("li", null, "Combines works + pages"), /* @__PURE__ */ React41.createElement("li", null, "Customize result layout"), /* @__PURE__ */ React41.createElement("li", null, "Optional annotations"))))), /* @__PURE__ */ React41.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React41.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React41.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React41.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--output" }, /* @__PURE__ */ React41.createElement("h3", null, "Static Digital Project"), /* @__PURE__ */ React41.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__ */ React41.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React41.createElement("article", null, /* @__PURE__ */ React41.createElement("h4", null, "Work pages"), /* @__PURE__ */ React41.createElement("ul", null, /* @__PURE__ */ React41.createElement("li", null, "105 generated HTML pages"), /* @__PURE__ */ React41.createElement("li", null, "Each links back to source manifests"), /* @__PURE__ */ React41.createElement("li", null, "Styled with Canopy components"))), /* @__PURE__ */ React41.createElement("article", null, /* @__PURE__ */ React41.createElement("h4", null, "Custom pages"), /* @__PURE__ */ React41.createElement("ul", null, /* @__PURE__ */ React41.createElement("li", null, "Markdown & MDX-authored content"), /* @__PURE__ */ React41.createElement("li", null, "Reusable layouts for narratives"), /* @__PURE__ */ React41.createElement("li", null, "Embed IIIF media & interstitials"))), /* @__PURE__ */ React41.createElement("article", null, /* @__PURE__ */ React41.createElement("h4", null, "Search bundle"), /* @__PURE__ */ React41.createElement("ul", null, /* @__PURE__ */ React41.createElement("li", null, "Static FlexSearch index"), /* @__PURE__ */ React41.createElement("li", null, "Works + pages share records"), /* @__PURE__ */ React41.createElement("li", null, "Optional annotation dataset"))))));
3973
4021
  }
3974
4022
 
3975
4023
  // ui/src/docs/ThemeShowcase.jsx
3976
- import React41 from "react";
4024
+ import React42 from "react";
3977
4025
 
3978
4026
  // ../../node_modules/@radix-ui/colors/index.mjs
3979
4027
  var colors_exports = {};
@@ -7825,21 +7873,21 @@ var STEP_MAP = {
7825
7873
  800: 11,
7826
7874
  900: 12
7827
7875
  };
7828
- var Section = ({ title, description, children }) => /* @__PURE__ */ React41.createElement("div", { className: "canopy-theme-showcase__section" }, /* @__PURE__ */ React41.createElement("h3", { className: "canopy-theme-showcase__section-title" }, title), description ? /* @__PURE__ */ React41.createElement("p", { className: "canopy-theme-showcase__section-description" }, description) : null, children);
7829
- var ColorScaleRow = ({ label, prefix }) => /* @__PURE__ */ React41.createElement("div", { className: "canopy-theme-showcase__scale-row" }, /* @__PURE__ */ React41.createElement("div", { className: "canopy-theme-showcase__scale-label" }, /* @__PURE__ */ React41.createElement("strong", null, label)), /* @__PURE__ */ React41.createElement("div", { className: "canopy-theme-showcase__scale-track" }, COLOR_STOPS.map((stop) => /* @__PURE__ */ React41.createElement(
7876
+ var Section = ({ title, description, children }) => /* @__PURE__ */ React42.createElement("div", { className: "canopy-theme-showcase__section" }, /* @__PURE__ */ React42.createElement("h3", { className: "canopy-theme-showcase__section-title" }, title), description ? /* @__PURE__ */ React42.createElement("p", { className: "canopy-theme-showcase__section-description" }, description) : null, children);
7877
+ var ColorScaleRow = ({ label, prefix }) => /* @__PURE__ */ React42.createElement("div", { className: "canopy-theme-showcase__scale-row" }, /* @__PURE__ */ React42.createElement("div", { className: "canopy-theme-showcase__scale-label" }, /* @__PURE__ */ React42.createElement("strong", null, label)), /* @__PURE__ */ React42.createElement("div", { className: "canopy-theme-showcase__scale-track" }, COLOR_STOPS.map((stop) => /* @__PURE__ */ React42.createElement(
7830
7878
  "div",
7831
7879
  {
7832
7880
  key: `${label}-${stop}`,
7833
7881
  className: "canopy-theme-showcase__scale-stop"
7834
7882
  },
7835
- /* @__PURE__ */ React41.createElement(
7883
+ /* @__PURE__ */ React42.createElement(
7836
7884
  "span",
7837
7885
  {
7838
7886
  className: "canopy-theme-showcase__scale-chip",
7839
7887
  style: { backgroundColor: `var(${prefix}-${stop})` }
7840
7888
  }
7841
7889
  ),
7842
- /* @__PURE__ */ React41.createElement("span", { className: "canopy-theme-showcase__scale-token" }, stop)
7890
+ /* @__PURE__ */ React42.createElement("span", { className: "canopy-theme-showcase__scale-token" }, stop)
7843
7891
  ))));
7844
7892
  var AVAILABLE = new Set(
7845
7893
  Object.keys(colors_exports).filter(
@@ -8021,9 +8069,9 @@ var PREVIEW_DATA = buildPreviewData();
8021
8069
  function encodeJson(value) {
8022
8070
  return JSON.stringify(value).replace(/</g, "\\u003c");
8023
8071
  }
8024
- var ColorsLabeled = ({ colors, type, getRadixSwatch }) => /* @__PURE__ */ React41.createElement("div", { className: "canopy-theme-showcase__swatch-grid" }, colors.map((name) => {
8072
+ var ColorsLabeled = ({ colors, type, getRadixSwatch }) => /* @__PURE__ */ React42.createElement("div", { className: "canopy-theme-showcase__swatch-grid" }, colors.map((name) => {
8025
8073
  const colorValue = getRadixSwatch(name);
8026
- return /* @__PURE__ */ React41.createElement(
8074
+ return /* @__PURE__ */ React42.createElement(
8027
8075
  "button",
8028
8076
  {
8029
8077
  key: `${type}-${name}`,
@@ -8034,14 +8082,14 @@ var ColorsLabeled = ({ colors, type, getRadixSwatch }) => /* @__PURE__ */ React4
8034
8082
  "data-theme-swatch-value": name,
8035
8083
  "aria-pressed": "false"
8036
8084
  },
8037
- /* @__PURE__ */ React41.createElement(
8085
+ /* @__PURE__ */ React42.createElement(
8038
8086
  "span",
8039
8087
  {
8040
8088
  className: "canopy-theme-showcase__swatch-chip",
8041
8089
  style: { background: colorValue || "var(--color-gray-200)" }
8042
8090
  }
8043
8091
  ),
8044
- /* @__PURE__ */ React41.createElement("span", { className: "canopy-theme-showcase__swatch-label" }, name)
8092
+ /* @__PURE__ */ React42.createElement("span", { className: "canopy-theme-showcase__swatch-label" }, name)
8045
8093
  );
8046
8094
  }));
8047
8095
  function ThemeShowcase() {
@@ -8198,18 +8246,18 @@ function ThemeShowcase() {
8198
8246
  .canopy-theme-showcase__swatch-controls { display: none; }
8199
8247
  .canopy-theme-showcase__clear-button { display: none; }
8200
8248
  `;
8201
- return /* @__PURE__ */ React41.createElement("div", { className: "canopy-theme-showcase", "data-theme-showcase": true }, /* @__PURE__ */ React41.createElement("style", { dangerouslySetInnerHTML: { __html: styles } }), /* @__PURE__ */ React41.createElement("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", gap: "1rem", marginBottom: "1rem" } }, /* @__PURE__ */ React41.createElement(
8249
+ return /* @__PURE__ */ React42.createElement("div", { className: "canopy-theme-showcase", "data-theme-showcase": true }, /* @__PURE__ */ React42.createElement("style", { dangerouslySetInnerHTML: { __html: styles } }), /* @__PURE__ */ React42.createElement("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", gap: "1rem", marginBottom: "1rem" } }, /* @__PURE__ */ React42.createElement(
8202
8250
  Section,
8203
8251
  {
8204
8252
  title: "Appearance",
8205
8253
  description: "Pick the base light or dark mode for the theme preview."
8206
8254
  },
8207
- /* @__PURE__ */ React41.createElement("div", { className: "canopy-theme-showcase__appearance-buttons" }, ["light", "dark"].map((mode) => {
8255
+ /* @__PURE__ */ React42.createElement("div", { className: "canopy-theme-showcase__appearance-buttons" }, ["light", "dark"].map((mode) => {
8208
8256
  const label = `${mode.charAt(0).toUpperCase()}${mode.slice(1)}`;
8209
8257
  const baseClass = "canopy-theme-showcase__appearance-button";
8210
8258
  const isDefault = mode === DEFAULTS.appearance;
8211
8259
  const className = isDefault ? `${baseClass} is-active` : baseClass;
8212
- return /* @__PURE__ */ React41.createElement(
8260
+ return /* @__PURE__ */ React42.createElement(
8213
8261
  "button",
8214
8262
  {
8215
8263
  key: mode,
@@ -8220,7 +8268,7 @@ function ThemeShowcase() {
8220
8268
  label
8221
8269
  );
8222
8270
  }))
8223
- ), /* @__PURE__ */ React41.createElement(
8271
+ ), /* @__PURE__ */ React42.createElement(
8224
8272
  "button",
8225
8273
  {
8226
8274
  type: "button",
@@ -8228,13 +8276,13 @@ function ThemeShowcase() {
8228
8276
  "data-theme-reset": true
8229
8277
  },
8230
8278
  "Reset"
8231
- )), /* @__PURE__ */ React41.createElement(
8279
+ )), /* @__PURE__ */ React42.createElement(
8232
8280
  Section,
8233
8281
  {
8234
8282
  title: "Color scales",
8235
8283
  description: "Accent and gray ramps from the active theme."
8236
8284
  },
8237
- /* @__PURE__ */ React41.createElement("div", { style: { display: "flex", flexDirection: "column", gap: "1.5rem" } }, COLOR_SCALES.map((scale) => /* @__PURE__ */ React41.createElement(
8285
+ /* @__PURE__ */ React42.createElement("div", { style: { display: "flex", flexDirection: "column", gap: "1.5rem" } }, COLOR_SCALES.map((scale) => /* @__PURE__ */ React42.createElement(
8238
8286
  ColorScaleRow,
8239
8287
  {
8240
8288
  key: scale.label,
@@ -8242,21 +8290,21 @@ function ThemeShowcase() {
8242
8290
  prefix: scale.prefix
8243
8291
  }
8244
8292
  )))
8245
- ), /* @__PURE__ */ React41.createElement(
8293
+ ), /* @__PURE__ */ React42.createElement(
8246
8294
  Section,
8247
8295
  {
8248
8296
  title: "Accent color palette options",
8249
8297
  description: "Click a swatch to temporarily override the accent palette."
8250
8298
  },
8251
- /* @__PURE__ */ React41.createElement(ColorsLabeled, { colors: accentColors, type: "accent", getRadixSwatch })
8252
- ), /* @__PURE__ */ React41.createElement(
8299
+ /* @__PURE__ */ React42.createElement(ColorsLabeled, { colors: accentColors, type: "accent", getRadixSwatch })
8300
+ ), /* @__PURE__ */ React42.createElement(
8253
8301
  Section,
8254
8302
  {
8255
8303
  title: "Gray color palette options",
8256
8304
  description: "Click a swatch to preview the neutral ramp for surfaces and text."
8257
8305
  },
8258
- /* @__PURE__ */ React41.createElement(ColorsLabeled, { colors: grayColors, type: "gray", getRadixSwatch })
8259
- ), /* @__PURE__ */ React41.createElement(
8306
+ /* @__PURE__ */ React42.createElement(ColorsLabeled, { colors: grayColors, type: "gray", getRadixSwatch })
8307
+ ), /* @__PURE__ */ React42.createElement(
8260
8308
  "script",
8261
8309
  {
8262
8310
  type: "application/json",
@@ -8266,6 +8314,7 @@ function ThemeShowcase() {
8266
8314
  ));
8267
8315
  }
8268
8316
  export {
8317
+ Biblography,
8269
8318
  Button,
8270
8319
  ButtonWrapper,
8271
8320
  CanopyBrand,