@canopy-iiif/app 1.3.6 → 1.4.1

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.
@@ -3212,8 +3212,208 @@ function MdxTimeline({ children, ...rest }) {
3212
3212
  ));
3213
3213
  }
3214
3214
 
3215
- // ui/src/search/MdxSearchResults.jsx
3215
+ // ui/src/content/map/MdxMap.jsx
3216
3216
  import React29 from "react";
3217
+ import ReactDOMServer2 from "react-dom/server";
3218
+
3219
+ // ui/src/content/map/MapPoint.jsx
3220
+ function MapPoint() {
3221
+ return null;
3222
+ }
3223
+ MapPoint.displayName = "MapPoint";
3224
+
3225
+ // ui/src/content/map/MdxMap.jsx
3226
+ import navPlaceHelpers from "@canopy-iiif/app/lib/components/nav-place.js";
3227
+ function normalizeNumber(value) {
3228
+ if (value == null) return null;
3229
+ const num = Number(value);
3230
+ return Number.isFinite(num) ? num : null;
3231
+ }
3232
+ function normalizeCoordinates(props = {}) {
3233
+ var _a, _b, _c, _d, _e, _f;
3234
+ const lat = (_b = (_a = normalizeNumber(props.lat)) != null ? _a : normalizeNumber(props.latitude)) != null ? _b : normalizeNumber(props.y);
3235
+ const lng = (_f = (_e = (_d = (_c = normalizeNumber(props.lng)) != null ? _c : normalizeNumber(props.lon)) != null ? _d : normalizeNumber(props.long)) != null ? _e : normalizeNumber(props.longitude)) != null ? _f : normalizeNumber(props.x);
3236
+ if (lat == null || lng == null) return null;
3237
+ return { lat, lng };
3238
+ }
3239
+ function renderDetailsHtml(children) {
3240
+ if (!children) return "";
3241
+ try {
3242
+ return ReactDOMServer2.renderToStaticMarkup(
3243
+ React29.createElement(React29.Fragment, null, children)
3244
+ );
3245
+ } catch (_) {
3246
+ return "";
3247
+ }
3248
+ }
3249
+ function normalizeCustomPoint(child, index) {
3250
+ var _a;
3251
+ if (!React29.isValidElement(child)) return null;
3252
+ if (child.type !== MapPoint && ((_a = child.type) == null ? void 0 : _a.displayName) !== "MapPoint") return null;
3253
+ const coords = normalizeCoordinates(child.props || {});
3254
+ if (!coords) return null;
3255
+ const props = child.props || {};
3256
+ const id = props.id || `map-point-${index + 1}`;
3257
+ const title = props.title || props.label || `Point ${index + 1}`;
3258
+ const summary = props.summary || props.description || "";
3259
+ const href = props.href || props.link || "";
3260
+ const thumbnail = props.thumbnail || props.image || "";
3261
+ const detailsHtml = renderDetailsHtml(props.children);
3262
+ return {
3263
+ id,
3264
+ title,
3265
+ summary,
3266
+ href,
3267
+ thumbnail,
3268
+ lat: coords.lat,
3269
+ lng: coords.lng,
3270
+ detailsHtml,
3271
+ type: "custom"
3272
+ };
3273
+ }
3274
+ function normalizeCustomPoints(children) {
3275
+ return React29.Children.toArray(children).map((child, index) => normalizeCustomPoint(child, index)).filter(Boolean);
3276
+ }
3277
+ function normalizeHeight(value) {
3278
+ if (value == null) return "600px";
3279
+ if (typeof value === "number") {
3280
+ return `${value}px`;
3281
+ }
3282
+ if (typeof value === "string") {
3283
+ const trimmed = value.trim();
3284
+ if (!trimmed) return "600px";
3285
+ if (/^[0-9.]+$/.test(trimmed)) {
3286
+ return `${trimmed}px`;
3287
+ }
3288
+ return trimmed;
3289
+ }
3290
+ return "600px";
3291
+ }
3292
+ function normalizeTileLayer(entry, index) {
3293
+ if (!entry) return null;
3294
+ if (typeof entry === "string") {
3295
+ const url = entry.trim();
3296
+ if (!url) return null;
3297
+ return {
3298
+ name: `Layer ${index + 1}`,
3299
+ url,
3300
+ attribution: ""
3301
+ };
3302
+ }
3303
+ if (typeof entry === "object") {
3304
+ const url = entry.url || entry.href;
3305
+ if (!url) return null;
3306
+ const layer = {
3307
+ name: entry.name || entry.title || `Layer ${index + 1}`,
3308
+ url: String(url),
3309
+ attribution: entry.attribution || entry.credit || ""
3310
+ };
3311
+ const minZoom = normalizeNumber(entry.minZoom);
3312
+ const maxZoom = normalizeNumber(entry.maxZoom);
3313
+ if (Number.isFinite(minZoom)) layer.minZoom = minZoom;
3314
+ if (Number.isFinite(maxZoom)) layer.maxZoom = maxZoom;
3315
+ if (entry.subdomains) layer.subdomains = entry.subdomains;
3316
+ return layer;
3317
+ }
3318
+ return null;
3319
+ }
3320
+ function normalizeTileLayers(value) {
3321
+ const list = Array.isArray(value) ? value : value ? [value] : [];
3322
+ return list.map((entry, index) => normalizeTileLayer(entry, index)).filter(Boolean);
3323
+ }
3324
+ function parseBoolean(value, fallback) {
3325
+ if (value === void 0) return fallback;
3326
+ if (typeof value === "boolean") return value;
3327
+ const normalized = String(value).trim().toLowerCase();
3328
+ if (!normalized) return fallback;
3329
+ if (["false", "0", "no", "off"].includes(normalized)) return false;
3330
+ if (["true", "1", "yes", "on"].includes(normalized)) return true;
3331
+ return fallback;
3332
+ }
3333
+ function normalizeCenter(value) {
3334
+ if (!value) return null;
3335
+ if (typeof value === "string") {
3336
+ const parts = value.split(/[,\s]+/).filter(Boolean);
3337
+ if (parts.length >= 2) {
3338
+ const coords = normalizeCoordinates({ lat: parts[0], lng: parts[1] });
3339
+ if (coords) return coords;
3340
+ }
3341
+ return null;
3342
+ }
3343
+ if (typeof value === "object") {
3344
+ const coords = normalizeCoordinates(value);
3345
+ if (coords) return coords;
3346
+ }
3347
+ return null;
3348
+ }
3349
+ function serializeProps2(props, payload) {
3350
+ const clone = {};
3351
+ Object.keys(props || {}).forEach((key) => {
3352
+ if (key === "children") return;
3353
+ const value = props[key];
3354
+ if (typeof value === "function" || typeof value === "symbol") return;
3355
+ clone[key] = value;
3356
+ });
3357
+ return { ...clone, ...payload };
3358
+ }
3359
+ function serializeForScript2(data) {
3360
+ try {
3361
+ return JSON.stringify(data).replace(/</g, "\\u003c");
3362
+ } catch (_) {
3363
+ return "{}";
3364
+ }
3365
+ }
3366
+ function getDatasetInfo() {
3367
+ if (!navPlaceHelpers) {
3368
+ return { hasFeatures: false, version: null, href: "/api/navplace.json" };
3369
+ }
3370
+ try {
3371
+ return navPlaceHelpers.getNavPlaceDatasetInfo();
3372
+ } catch (_) {
3373
+ return {
3374
+ hasFeatures: false,
3375
+ version: null,
3376
+ href: navPlaceHelpers.NAVPLACE_PUBLIC_HREF || "/api/navplace.json"
3377
+ };
3378
+ }
3379
+ }
3380
+ function MdxMap({ children, ...rest }) {
3381
+ const customPoints = normalizeCustomPoints(children);
3382
+ const datasetInfo = getDatasetInfo();
3383
+ const navDataset = {
3384
+ hasFeatures: Boolean(datasetInfo && datasetInfo.hasFeatures),
3385
+ href: datasetInfo && datasetInfo.href || "/api/navplace.json",
3386
+ version: datasetInfo && datasetInfo.version ? datasetInfo.version : null
3387
+ };
3388
+ const height = normalizeHeight(rest.height);
3389
+ const tileLayers = normalizeTileLayers(rest.tileLayers || rest.tileLayer);
3390
+ const scrollWheelZoom = parseBoolean(rest.scrollWheelZoom, false);
3391
+ const cluster = parseBoolean(rest.cluster, true);
3392
+ const defaultCenter = normalizeCenter(rest.defaultCenter || rest.center);
3393
+ const defaultZoom = normalizeNumber(rest.defaultZoom || rest.zoom);
3394
+ const payload = serializeProps2(rest, {
3395
+ className: rest.className || "",
3396
+ id: rest.id || null,
3397
+ height,
3398
+ tileLayers,
3399
+ scrollWheelZoom,
3400
+ cluster,
3401
+ customPoints,
3402
+ navDataset,
3403
+ defaultCenter,
3404
+ defaultZoom: Number.isFinite(defaultZoom) ? defaultZoom : null
3405
+ });
3406
+ const json = serializeForScript2(payload);
3407
+ const placeholderClass = ["canopy-map", rest.className].filter(Boolean).join(" ");
3408
+ const placeholderProps = {};
3409
+ if (placeholderClass) placeholderProps.className = placeholderClass;
3410
+ if (rest.id) placeholderProps.id = rest.id;
3411
+ if (rest.style) placeholderProps.style = rest.style;
3412
+ return /* @__PURE__ */ React29.createElement("div", { "data-canopy-map": "1" }, /* @__PURE__ */ React29.createElement("div", { ...placeholderProps, "aria-live": "polite" }, /* @__PURE__ */ React29.createElement("div", { className: "canopy-map__status" }, "Loading map\u2026")), /* @__PURE__ */ React29.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3413
+ }
3414
+
3415
+ // ui/src/search/MdxSearchResults.jsx
3416
+ import React30 from "react";
3217
3417
  function MdxSearchResults(props) {
3218
3418
  let json = "{}";
3219
3419
  try {
@@ -3221,11 +3421,11 @@ function MdxSearchResults(props) {
3221
3421
  } catch (_) {
3222
3422
  json = "{}";
3223
3423
  }
3224
- return /* @__PURE__ */ React29.createElement("div", { "data-canopy-search-results": "1" }, /* @__PURE__ */ React29.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3424
+ return /* @__PURE__ */ React30.createElement("div", { "data-canopy-search-results": "1" }, /* @__PURE__ */ React30.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3225
3425
  }
3226
3426
 
3227
3427
  // ui/src/search/SearchSummary.jsx
3228
- import React30 from "react";
3428
+ import React31 from "react";
3229
3429
  function SearchSummary(props) {
3230
3430
  let json = "{}";
3231
3431
  try {
@@ -3233,11 +3433,11 @@ function SearchSummary(props) {
3233
3433
  } catch (_) {
3234
3434
  json = "{}";
3235
3435
  }
3236
- return /* @__PURE__ */ React30.createElement("div", { "data-canopy-search-summary": "1" }, /* @__PURE__ */ React30.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3436
+ return /* @__PURE__ */ React31.createElement("div", { "data-canopy-search-summary": "1" }, /* @__PURE__ */ React31.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3237
3437
  }
3238
3438
 
3239
3439
  // ui/src/search/MdxSearchTabs.jsx
3240
- import React31 from "react";
3440
+ import React32 from "react";
3241
3441
  function MdxSearchTabs(props) {
3242
3442
  let json = "{}";
3243
3443
  try {
@@ -3245,11 +3445,11 @@ function MdxSearchTabs(props) {
3245
3445
  } catch (_) {
3246
3446
  json = "{}";
3247
3447
  }
3248
- return /* @__PURE__ */ React31.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React31.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3448
+ return /* @__PURE__ */ React32.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React32.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
3249
3449
  }
3250
3450
 
3251
3451
  // ui/src/search/MdxSearch.jsx
3252
- import React32 from "react";
3452
+ import React33 from "react";
3253
3453
  function MdxSearch(props = {}) {
3254
3454
  const {
3255
3455
  layout,
@@ -3267,11 +3467,11 @@ function MdxSearch(props = {}) {
3267
3467
  resultsPayload.layout = layout;
3268
3468
  }
3269
3469
  const classes = ["canopy-search", className].filter(Boolean).join(" ");
3270
- 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);
3470
+ return /* @__PURE__ */ React33.createElement("section", { className: classes, "data-canopy-search": "1" }, showTabs ? /* @__PURE__ */ React33.createElement(MdxSearchTabs, { ...tabsProps }) : null, showSummary ? /* @__PURE__ */ React33.createElement(SearchSummary, { ...summaryProps }) : null, showResults ? /* @__PURE__ */ React33.createElement(MdxSearchResults, { ...resultsPayload }) : null, children || null);
3271
3471
  }
3272
3472
 
3273
3473
  // ui/src/search-form/MdxSearchFormModal.jsx
3274
- import React33 from "react";
3474
+ import React34 from "react";
3275
3475
  function MdxSearchFormModal(props = {}) {
3276
3476
  const {
3277
3477
  placeholder = "Search\u2026",
@@ -3287,12 +3487,12 @@ function MdxSearchFormModal(props = {}) {
3287
3487
  const text = typeof label === "string" && label.trim() ? label.trim() : buttonLabel;
3288
3488
  const resolvedSearchPath = resolveSearchPath(searchPath);
3289
3489
  const data = { placeholder, hotkey, maxResults, groupOrder, label: text, searchPath: resolvedSearchPath };
3290
- 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) } }));
3490
+ return /* @__PURE__ */ React34.createElement("div", { "data-canopy-search-form": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React34.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React34.createElement(SearchPanelForm, { placeholder, buttonLabel, label, searchPath: resolvedSearchPath }), /* @__PURE__ */ React34.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React34.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
3291
3491
  }
3292
3492
 
3293
3493
  // ui/src/iiif/ManifestPrimitives.jsx
3294
3494
  var import_slugify = __toESM(require_slugify());
3295
- import React34 from "react";
3495
+ import React35 from "react";
3296
3496
  import {
3297
3497
  Label as CloverLabel,
3298
3498
  Metadata as CloverMetadata,
@@ -3433,7 +3633,7 @@ function MetadataFacetLink(props) {
3433
3633
  const valueSlug = facetSlug ? toValueSlug(text) : "";
3434
3634
  const href = facetSlug && valueSlug ? buildFacetSearchHref(facetSlug, valueSlug) : "";
3435
3635
  if (!href) return text;
3436
- return /* @__PURE__ */ React34.createElement(
3636
+ return /* @__PURE__ */ React35.createElement(
3437
3637
  "a",
3438
3638
  {
3439
3639
  href,
@@ -3459,7 +3659,7 @@ function buildFacetCustomValueContent(items, manifest) {
3459
3659
  seen.add(normalized);
3460
3660
  custom.push({
3461
3661
  matchingLabel: item.label,
3462
- Content: /* @__PURE__ */ React34.createElement(MetadataFacetLink, { facetSlug: facet.slug })
3662
+ Content: /* @__PURE__ */ React35.createElement(MetadataFacetLink, { facetSlug: facet.slug })
3463
3663
  });
3464
3664
  }
3465
3665
  return custom;
@@ -3491,12 +3691,12 @@ function mergeCustomValueContent(userContent, autoContent) {
3491
3691
  function Label({ manifest, label, ...rest }) {
3492
3692
  const intl = label || manifest && manifest.label;
3493
3693
  if (!hasInternationalValue(intl)) return null;
3494
- return /* @__PURE__ */ React34.createElement(CloverLabel, { label: intl, ...rest });
3694
+ return /* @__PURE__ */ React35.createElement(CloverLabel, { label: intl, ...rest });
3495
3695
  }
3496
3696
  function Summary({ manifest, summary, ...rest }) {
3497
3697
  const intl = summary || manifest && manifest.summary;
3498
3698
  if (!hasInternationalValue(intl)) return null;
3499
- return /* @__PURE__ */ React34.createElement(CloverSummary, { summary: intl, ...rest });
3699
+ return /* @__PURE__ */ React35.createElement(CloverSummary, { summary: intl, ...rest });
3500
3700
  }
3501
3701
  function Metadata({ manifest, metadata, customValueContent, ...rest }) {
3502
3702
  const items = ensureMetadata(metadata || manifest && manifest.metadata);
@@ -3506,7 +3706,7 @@ function Metadata({ manifest, metadata, customValueContent, ...rest }) {
3506
3706
  customValueContent,
3507
3707
  autoCustomContent
3508
3708
  );
3509
- return /* @__PURE__ */ React34.createElement(
3709
+ return /* @__PURE__ */ React35.createElement(
3510
3710
  CloverMetadata,
3511
3711
  {
3512
3712
  metadata: items,
@@ -3520,11 +3720,11 @@ function RequiredStatement({ manifest, requiredStatement, ...rest }) {
3520
3720
  if (!stmt || !hasInternationalValue(stmt.label) || !hasInternationalValue(stmt.value)) {
3521
3721
  return null;
3522
3722
  }
3523
- return /* @__PURE__ */ React34.createElement(CloverRequiredStatement, { requiredStatement: stmt, ...rest });
3723
+ return /* @__PURE__ */ React35.createElement(CloverRequiredStatement, { requiredStatement: stmt, ...rest });
3524
3724
  }
3525
3725
 
3526
3726
  // ui/src/docs/CodeBlock.jsx
3527
- import React35 from "react";
3727
+ import React36 from "react";
3528
3728
  function parseHighlightAttr(attr) {
3529
3729
  if (!attr) return /* @__PURE__ */ new Set();
3530
3730
  const cleaned = String(attr || "").trim();
@@ -3570,10 +3770,10 @@ var highlightBaseStyle = {
3570
3770
  };
3571
3771
  function DocsCodeBlock(props = {}) {
3572
3772
  const { children, ...rest } = props;
3573
- const childArray = React35.Children.toArray(children);
3574
- const codeElement = childArray.find((el) => React35.isValidElement(el));
3773
+ const childArray = React36.Children.toArray(children);
3774
+ const codeElement = childArray.find((el) => React36.isValidElement(el));
3575
3775
  if (!codeElement || !codeElement.props) {
3576
- return React35.createElement("pre", props);
3776
+ return React36.createElement("pre", props);
3577
3777
  }
3578
3778
  const {
3579
3779
  className = "",
@@ -3588,8 +3788,8 @@ function DocsCodeBlock(props = {}) {
3588
3788
  const highlightSet = parseHighlightAttr(highlightAttr);
3589
3789
  const copyAttr = codeProps["data-copy"];
3590
3790
  const enableCopy = copyAttr !== void 0 ? copyAttr === true || copyAttr === "true" || copyAttr === "" : false;
3591
- const [copied, setCopied] = React35.useState(false);
3592
- const handleCopy = React35.useCallback(async () => {
3791
+ const [copied, setCopied] = React36.useState(false);
3792
+ const handleCopy = React36.useCallback(async () => {
3593
3793
  const text = rawCode;
3594
3794
  try {
3595
3795
  if (typeof navigator !== "undefined" && navigator.clipboard && navigator.clipboard.writeText) {
@@ -3654,20 +3854,20 @@ function DocsCodeBlock(props = {}) {
3654
3854
  const highlight = highlightSet.has(lineNumber);
3655
3855
  const style = highlight ? { ...baseLineStyle, ...highlightBaseStyle } : baseLineStyle;
3656
3856
  const displayLine = line === "" ? " " : line;
3657
- return React35.createElement(
3857
+ return React36.createElement(
3658
3858
  "span",
3659
3859
  { key: lineNumber, style },
3660
- React35.createElement("span", { style: lineContentStyle }, displayLine)
3860
+ React36.createElement("span", { style: lineContentStyle }, displayLine)
3661
3861
  );
3662
3862
  });
3663
- return React35.createElement(
3863
+ return React36.createElement(
3664
3864
  "div",
3665
3865
  { style: containerStyle },
3666
- showHeader ? React35.createElement(
3866
+ showHeader ? React36.createElement(
3667
3867
  "div",
3668
3868
  { style: headerStyle },
3669
- React35.createElement("span", null, showFilename ? filename : null),
3670
- enableCopy ? React35.createElement(
3869
+ React36.createElement("span", null, showFilename ? filename : null),
3870
+ enableCopy ? React36.createElement(
3671
3871
  "button",
3672
3872
  {
3673
3873
  type: "button",
@@ -3686,29 +3886,29 @@ function DocsCodeBlock(props = {}) {
3686
3886
  copied ? "Copied" : "Copy"
3687
3887
  ) : null
3688
3888
  ) : null,
3689
- React35.createElement(
3889
+ React36.createElement(
3690
3890
  "pre",
3691
3891
  { ...preRest, className: preClassName, style: mergedPreStyle },
3692
- React35.createElement("code", { style: codeStyle }, lineElements)
3892
+ React36.createElement("code", { style: codeStyle }, lineElements)
3693
3893
  )
3694
3894
  );
3695
3895
  }
3696
3896
 
3697
3897
  // ui/src/docs/MarkdownTable.jsx
3698
- import React36 from "react";
3898
+ import React37 from "react";
3699
3899
  function MarkdownTable({ className = "", ...rest }) {
3700
3900
  const merged = ["markdown-table", className].filter(Boolean).join(" ");
3701
- return /* @__PURE__ */ React36.createElement("div", { className: "markdown-table__frame" }, /* @__PURE__ */ React36.createElement("table", { className: merged, ...rest }));
3901
+ return /* @__PURE__ */ React37.createElement("div", { className: "markdown-table__frame" }, /* @__PURE__ */ React37.createElement("table", { className: merged, ...rest }));
3702
3902
  }
3703
3903
 
3704
3904
  // ui/src/docs/Diagram.jsx
3705
- import React37 from "react";
3905
+ import React38 from "react";
3706
3906
  function CanopyDiagram() {
3707
- 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"))))));
3907
+ return /* @__PURE__ */ React38.createElement("div", { className: "canopy-diagram" }, /* @__PURE__ */ React38.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--collections" }, /* @__PURE__ */ React38.createElement("h3", null, "IIIF Collection(s)"), /* @__PURE__ */ React38.createElement("span", { className: "canopy-diagram__section-summary" }, "Source collections contribute 105 total manifests that Canopy retrieves as-is via IIIF endpoints."), /* @__PURE__ */ React38.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React38.createElement("article", null, /* @__PURE__ */ React38.createElement("h4", null, "Collection A"), /* @__PURE__ */ React38.createElement("ul", null, /* @__PURE__ */ React38.createElement("li", null, "70 Manifests"), /* @__PURE__ */ React38.createElement("li", null, "IIIF Images + A/V"), /* @__PURE__ */ React38.createElement("li", null, "Textual Annotations"))), /* @__PURE__ */ React38.createElement("article", null, /* @__PURE__ */ React38.createElement("h4", null, "Collection B"), /* @__PURE__ */ React38.createElement("ul", null, /* @__PURE__ */ React38.createElement("li", null, "35 Manifests"), /* @__PURE__ */ React38.createElement("li", null, "IIIF Images + A/V"), /* @__PURE__ */ React38.createElement("li", null, "Textual Annotations"))))), /* @__PURE__ */ React38.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React38.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React38.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React38.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--build" }, /* @__PURE__ */ React38.createElement("h3", null, "Canopy Build Process"), /* @__PURE__ */ React38.createElement("span", { className: "canopy-diagram__section-summary" }, "Canopy syncs manifests, page content, and annotations before bundling the site."), /* @__PURE__ */ React38.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React38.createElement("article", null, /* @__PURE__ */ React38.createElement("h4", null, "Automated content"), /* @__PURE__ */ React38.createElement("ul", null, /* @__PURE__ */ React38.createElement("li", null, "105 manifests \u2192 105 work pages"), /* @__PURE__ */ React38.createElement("li", null, "One page per manifest"), /* @__PURE__ */ React38.createElement("li", null, "Customize page layout"))), /* @__PURE__ */ React38.createElement("article", null, /* @__PURE__ */ React38.createElement("h4", null, "Contextual content"), /* @__PURE__ */ React38.createElement("ul", null, /* @__PURE__ */ React38.createElement("li", null, "Markdown & MDX pages"), /* @__PURE__ */ React38.createElement("li", null, "Author narratives & tours"), /* @__PURE__ */ React38.createElement("li", null, "Reference manifests inline"))), /* @__PURE__ */ React38.createElement("article", null, /* @__PURE__ */ React38.createElement("h4", null, "Search index"), /* @__PURE__ */ React38.createElement("ul", null, /* @__PURE__ */ React38.createElement("li", null, "Combines works + pages"), /* @__PURE__ */ React38.createElement("li", null, "Customize result layout"), /* @__PURE__ */ React38.createElement("li", null, "Optional annotations"))))), /* @__PURE__ */ React38.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React38.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React38.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React38.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--output" }, /* @__PURE__ */ React38.createElement("h3", null, "Static Digital Project"), /* @__PURE__ */ React38.createElement("span", { className: "canopy-diagram__section-summary" }, "The output is a lightweight bundle of HTML, CSS, JS, and JSON assets that can deploy anywhere."), /* @__PURE__ */ React38.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React38.createElement("article", null, /* @__PURE__ */ React38.createElement("h4", null, "Work pages"), /* @__PURE__ */ React38.createElement("ul", null, /* @__PURE__ */ React38.createElement("li", null, "105 generated HTML pages"), /* @__PURE__ */ React38.createElement("li", null, "Each links back to source manifests"), /* @__PURE__ */ React38.createElement("li", null, "Styled with Canopy components"))), /* @__PURE__ */ React38.createElement("article", null, /* @__PURE__ */ React38.createElement("h4", null, "Custom pages"), /* @__PURE__ */ React38.createElement("ul", null, /* @__PURE__ */ React38.createElement("li", null, "Markdown & MDX-authored content"), /* @__PURE__ */ React38.createElement("li", null, "Reusable layouts for narratives"), /* @__PURE__ */ React38.createElement("li", null, "Embed IIIF media & interstitials"))), /* @__PURE__ */ React38.createElement("article", null, /* @__PURE__ */ React38.createElement("h4", null, "Search bundle"), /* @__PURE__ */ React38.createElement("ul", null, /* @__PURE__ */ React38.createElement("li", null, "Static FlexSearch index"), /* @__PURE__ */ React38.createElement("li", null, "Works + pages share records"), /* @__PURE__ */ React38.createElement("li", null, "Optional annotation dataset"))))));
3708
3908
  }
3709
3909
 
3710
3910
  // ui/src/docs/ThemeShowcase.jsx
3711
- import React38 from "react";
3911
+ import React39 from "react";
3712
3912
 
3713
3913
  // ../../node_modules/@radix-ui/colors/index.mjs
3714
3914
  var colors_exports = {};
@@ -7541,21 +7741,21 @@ var ACCENT_COLOR_NAMES = [
7541
7741
  "sky"
7542
7742
  ];
7543
7743
  var GRAY_COLOR_NAMES = ["gray", "mauve", "slate", "sage", "olive", "sand"];
7544
- 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);
7545
- 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(
7744
+ var Section = ({ title, description, children }) => /* @__PURE__ */ React39.createElement("div", { className: "canopy-theme-showcase__section" }, /* @__PURE__ */ React39.createElement("h3", { className: "canopy-theme-showcase__section-title" }, title), description ? /* @__PURE__ */ React39.createElement("p", { className: "canopy-theme-showcase__section-description" }, description) : null, children);
7745
+ var ColorScaleRow = ({ label, prefix }) => /* @__PURE__ */ React39.createElement("div", { className: "canopy-theme-showcase__scale-row" }, /* @__PURE__ */ React39.createElement("div", { className: "canopy-theme-showcase__scale-label" }, /* @__PURE__ */ React39.createElement("strong", null, label)), /* @__PURE__ */ React39.createElement("div", { className: "canopy-theme-showcase__scale-track" }, COLOR_STOPS.map((stop) => /* @__PURE__ */ React39.createElement(
7546
7746
  "div",
7547
7747
  {
7548
7748
  key: `${label}-${stop}`,
7549
7749
  className: "canopy-theme-showcase__scale-stop"
7550
7750
  },
7551
- /* @__PURE__ */ React38.createElement(
7751
+ /* @__PURE__ */ React39.createElement(
7552
7752
  "span",
7553
7753
  {
7554
7754
  className: "canopy-theme-showcase__scale-chip",
7555
7755
  style: { backgroundColor: `var(${prefix}-${stop})` }
7556
7756
  }
7557
7757
  ),
7558
- /* @__PURE__ */ React38.createElement("span", { className: "canopy-theme-showcase__scale-token" }, stop)
7758
+ /* @__PURE__ */ React39.createElement("span", { className: "canopy-theme-showcase__scale-token" }, stop)
7559
7759
  ))));
7560
7760
  function ThemeShowcase() {
7561
7761
  const accentColors = ACCENT_COLOR_NAMES;
@@ -7566,15 +7766,15 @@ function ThemeShowcase() {
7566
7766
  if (!scale) return null;
7567
7767
  return scale[`${name}9`] || Object.values(scale)[8];
7568
7768
  };
7569
- const ColorsLabeled = ({ colors }) => /* @__PURE__ */ React38.createElement("div", { className: "canopy-theme-showcase__swatch-grid" }, colors.map((name) => {
7769
+ const ColorsLabeled = ({ colors }) => /* @__PURE__ */ React39.createElement("div", { className: "canopy-theme-showcase__swatch-grid" }, colors.map((name) => {
7570
7770
  const colorValue = getRadixSwatch(name);
7571
- return /* @__PURE__ */ React38.createElement("div", { key: name, className: "canopy-theme-showcase__swatch" }, /* @__PURE__ */ React38.createElement(
7771
+ return /* @__PURE__ */ React39.createElement("div", { key: name, className: "canopy-theme-showcase__swatch" }, /* @__PURE__ */ React39.createElement(
7572
7772
  "div",
7573
7773
  {
7574
7774
  className: "canopy-theme-showcase__swatch-chip",
7575
7775
  style: { background: colorValue || "var(--color-gray-200)" }
7576
7776
  }
7577
- ), /* @__PURE__ */ React38.createElement("div", { className: "canopy-theme-showcase__swatch-label" }, name));
7777
+ ), /* @__PURE__ */ React39.createElement("div", { className: "canopy-theme-showcase__swatch-label" }, name));
7578
7778
  }));
7579
7779
  const styles = `
7580
7780
  .canopy-theme-showcase__section {
@@ -7658,13 +7858,13 @@ function ThemeShowcase() {
7658
7858
  font-weight: 300;
7659
7859
  }
7660
7860
  `;
7661
- return /* @__PURE__ */ React38.createElement("div", { className: "canopy-theme-showcase" }, /* @__PURE__ */ React38.createElement("style", { dangerouslySetInnerHTML: { __html: styles } }), /* @__PURE__ */ React38.createElement(
7861
+ return /* @__PURE__ */ React39.createElement("div", { className: "canopy-theme-showcase" }, /* @__PURE__ */ React39.createElement("style", { dangerouslySetInnerHTML: { __html: styles } }), /* @__PURE__ */ React39.createElement(
7662
7862
  Section,
7663
7863
  {
7664
7864
  title: "Color scales",
7665
7865
  description: "Accent and gray ramps from the active theme."
7666
7866
  },
7667
- /* @__PURE__ */ React38.createElement("div", { style: { display: "flex", flexDirection: "column", gap: "1.5rem" } }, COLOR_SCALES.map((scale) => /* @__PURE__ */ React38.createElement(
7867
+ /* @__PURE__ */ React39.createElement("div", { style: { display: "flex", flexDirection: "column", gap: "1.5rem" } }, COLOR_SCALES.map((scale) => /* @__PURE__ */ React39.createElement(
7668
7868
  ColorScaleRow,
7669
7869
  {
7670
7870
  key: scale.label,
@@ -7672,20 +7872,20 @@ function ThemeShowcase() {
7672
7872
  prefix: scale.prefix
7673
7873
  }
7674
7874
  )))
7675
- ), /* @__PURE__ */ React38.createElement(
7875
+ ), /* @__PURE__ */ React39.createElement(
7676
7876
  Section,
7677
7877
  {
7678
7878
  title: "Accent color palette options",
7679
7879
  description: "Primary color steps used for buttons, links, and highlights."
7680
7880
  },
7681
- /* @__PURE__ */ React38.createElement(ColorsLabeled, { colors: accentColors })
7682
- ), /* @__PURE__ */ React38.createElement(
7881
+ /* @__PURE__ */ React39.createElement(ColorsLabeled, { colors: accentColors })
7882
+ ), /* @__PURE__ */ React39.createElement(
7683
7883
  Section,
7684
7884
  {
7685
7885
  title: "Gray color palette options",
7686
7886
  description: "Neutral color steps used for backgrounds, borders, and text."
7687
7887
  },
7688
- /* @__PURE__ */ React38.createElement(ColorsLabeled, { colors: grayColors })
7888
+ /* @__PURE__ */ React39.createElement(ColorsLabeled, { colors: grayColors })
7689
7889
  ));
7690
7890
  }
7691
7891
  export {
@@ -7706,6 +7906,8 @@ export {
7706
7906
  interstitials_exports as Interstitials,
7707
7907
  Label,
7708
7908
  Layout,
7909
+ MdxMap as Map,
7910
+ MapPoint,
7709
7911
  Metadata,
7710
7912
  ReferencedItems,
7711
7913
  References,