@canopy-iiif/app 0.12.2 → 0.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canopy-iiif/app",
3
- "version": "0.12.2",
3
+ "version": "0.12.3",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "author": "Mat Jordan <mat@northwestern.edu>",
@@ -358,6 +358,7 @@ __export(interstitials_exports, {
358
358
  // ui/src/interstitials/Hero.jsx
359
359
  import React9 from "react";
360
360
  import helpers from "@canopy-iiif/app/lib/components/featured.js";
361
+ import navigationHelpers from "@canopy-iiif/app/lib/components/navigation.js";
361
362
 
362
363
  // ui/src/interstitials/hero-utils.js
363
364
  function computeHeroHeightStyle(height) {
@@ -520,11 +521,26 @@ function normalizeBackground(value) {
520
521
  return "theme";
521
522
  }
522
523
  }
524
+ function findNodePathBySlug(node, targetSlug) {
525
+ if (!node || !targetSlug) return null;
526
+ const normalizedTarget = String(targetSlug || "");
527
+ if (!normalizedTarget) return null;
528
+ if (node.slug === normalizedTarget) return [node];
529
+ const children = Array.isArray(node.children) ? node.children : [];
530
+ for (const child of children) {
531
+ const path = findNodePathBySlug(child, normalizedTarget);
532
+ if (path && path.length) {
533
+ return [node, ...path];
534
+ }
535
+ }
536
+ return null;
537
+ }
523
538
  function normalizeVariant(value) {
524
539
  try {
525
540
  const raw = value == null ? "" : String(value);
526
541
  const normalized = raw.trim().toLowerCase();
527
- return normalized === "text" ? "text" : "featured";
542
+ if (normalized === "breadcrumb" || normalized === "text") return "breadcrumb";
543
+ return "featured";
528
544
  } catch (_) {
529
545
  return "featured";
530
546
  }
@@ -542,12 +558,15 @@ function Hero({
542
558
  style = {},
543
559
  background = "theme",
544
560
  variant = "featured",
561
+ homeLabel = "Home",
545
562
  ...rest
546
563
  }) {
547
564
  const normalizedVariant = normalizeVariant(variant);
548
- const isTextVariant = normalizedVariant === "text";
565
+ const isBreadcrumbVariant = normalizedVariant === "breadcrumb";
566
+ const PageContext = navigationHelpers && typeof navigationHelpers.getPageContext === "function" ? navigationHelpers.getPageContext() : null;
567
+ const pageContext = PageContext ? React9.useContext(PageContext) : null;
549
568
  let orderedSlides = [];
550
- if (!isTextVariant) {
569
+ if (!isBreadcrumbVariant) {
551
570
  const resolved = resolveFeaturedItem({ item, index, random });
552
571
  const helpersList = helpers && helpers.readFeaturedFromCacheSync ? helpers.readFeaturedFromCacheSync() : [];
553
572
  const slides = [];
@@ -582,15 +601,15 @@ function Hero({
582
601
  }
583
602
  const heroHeight = computeHeroHeightStyle(height);
584
603
  const heroStyles = { ...style || {} };
585
- if (heroHeight && heroHeight.height && !isTextVariant) {
604
+ if (heroHeight && heroHeight.height && !isBreadcrumbVariant) {
586
605
  heroStyles["--hero-height"] = heroHeight.height;
587
606
  }
588
- if (isTextVariant) {
607
+ if (isBreadcrumbVariant) {
589
608
  heroStyles["--hero-height"] = "auto";
590
609
  }
591
610
  const derivedDescription = description ? String(description) : "";
592
611
  const normalizedLinks = normalizeLinks(links);
593
- const primarySlide = !isTextVariant ? orderedSlides[0] || null : null;
612
+ const primarySlide = !isBreadcrumbVariant ? orderedSlides[0] || null : null;
594
613
  const overlayTitle = headline || primarySlide && primarySlide.title || "";
595
614
  const defaultLinkHref = applyBasePath(
596
615
  primarySlide && primarySlide.href ? primarySlide.href : "#"
@@ -602,10 +621,46 @@ function Hero({
602
621
  type: "primary"
603
622
  }
604
623
  ].filter(Boolean);
605
- const finalOverlayLinks = isTextVariant ? normalizedLinks : overlayLinks;
624
+ const finalOverlayLinks = isBreadcrumbVariant ? normalizedLinks : overlayLinks;
625
+ const breadcrumbItems = React9.useMemo(() => {
626
+ if (!isBreadcrumbVariant) return [];
627
+ const items = [];
628
+ const label = typeof homeLabel === "string" ? homeLabel.trim() : "";
629
+ if (label) {
630
+ items.push({ title: label, href: applyBasePath("/") });
631
+ }
632
+ const navigation = pageContext && pageContext.navigation ? pageContext.navigation : null;
633
+ const page = pageContext && pageContext.page ? pageContext.page : null;
634
+ const slug = page && page.slug || navigation && navigation.currentSlug || "";
635
+ const rootNode = navigation && navigation.root ? navigation.root : null;
636
+ if (!slug || !rootNode) return items;
637
+ const path = findNodePathBySlug(rootNode, slug);
638
+ if (!path || !path.length) return items;
639
+ path.forEach((node) => {
640
+ if (!node) return;
641
+ const title = node.title || node.slug || "";
642
+ if (!title) return;
643
+ const href = node.href ? applyBasePath(node.href) : null;
644
+ items.push({ title, href });
645
+ });
646
+ return items;
647
+ }, [isBreadcrumbVariant, pageContext, homeLabel]);
648
+ const breadcrumbNode = isBreadcrumbVariant && breadcrumbItems.length ? /* @__PURE__ */ React9.createElement("nav", { className: "canopy-interstitial__breadcrumb", "aria-label": "Breadcrumb" }, breadcrumbItems.map((item2, idx) => {
649
+ const isLast = idx === breadcrumbItems.length - 1;
650
+ const key = `${item2.title || idx}-${idx}`;
651
+ const content = !isLast && item2.href ? /* @__PURE__ */ React9.createElement("a", { href: item2.href }, item2.title) : /* @__PURE__ */ React9.createElement("span", { className: "canopy-interstitial__breadcrumb-current" }, item2.title);
652
+ return /* @__PURE__ */ React9.createElement(React9.Fragment, { key }, idx > 0 ? /* @__PURE__ */ React9.createElement(
653
+ "span",
654
+ {
655
+ className: "canopy-interstitial__breadcrumb-separator",
656
+ "aria-hidden": "true"
657
+ },
658
+ ">"
659
+ ) : null, content);
660
+ })) : null;
606
661
  const normalizedBackground = normalizeBackground(background);
607
662
  const backgroundClassName = normalizedBackground === "transparent" ? "canopy-interstitial--bg-transparent" : "";
608
- const variantClassName = isTextVariant ? "canopy-interstitial--hero-text" : "canopy-interstitial--hero-featured";
663
+ const variantClassName = isBreadcrumbVariant ? "canopy-interstitial--hero-breadcrumb" : "canopy-interstitial--hero-featured";
609
664
  const containerClassName = [
610
665
  "canopy-interstitial",
611
666
  "canopy-interstitial--hero",
@@ -704,18 +759,18 @@ function Hero({
704
759
  style: heroStyles,
705
760
  ...cleanedProps
706
761
  };
707
- if (!isTextVariant) {
762
+ if (!isBreadcrumbVariant) {
708
763
  sectionProps["data-canopy-hero-slider"] = "1";
709
764
  sectionProps["data-transition"] = normalizedTransition;
710
765
  } else {
711
- sectionProps["data-canopy-hero-variant"] = "text";
766
+ sectionProps["data-canopy-hero-variant"] = "breadcrumb";
712
767
  }
713
- return /* @__PURE__ */ React9.createElement("section", { ...sectionProps }, isTextVariant ? /* @__PURE__ */ React9.createElement("div", { className: "canopy-interstitial__layout canopy-interstitial__layout--text" }, /* @__PURE__ */ React9.createElement("div", { className: "canopy-interstitial__panel" }, /* @__PURE__ */ React9.createElement("div", { className: "canopy-interstitial__body" }, overlayContent))) : /* @__PURE__ */ React9.createElement("div", { className: "canopy-interstitial__layout" }, /* @__PURE__ */ React9.createElement("div", { className: "canopy-interstitial__panel" }, /* @__PURE__ */ React9.createElement("div", { className: "canopy-interstitial__body" }, overlayContent)), /* @__PURE__ */ React9.createElement("div", { className: "canopy-interstitial__media-group" }, renderSlider({ showVeil: false, captionVariant: "static" }))));
768
+ return /* @__PURE__ */ React9.createElement("section", { ...sectionProps }, isBreadcrumbVariant ? /* @__PURE__ */ React9.createElement("div", { className: "canopy-interstitial__layout canopy-interstitial__layout--breadcrumb" }, /* @__PURE__ */ React9.createElement("div", { className: "canopy-interstitial__panel" }, /* @__PURE__ */ React9.createElement("div", { className: "canopy-interstitial__body" }, breadcrumbNode, overlayContent))) : /* @__PURE__ */ React9.createElement("div", { className: "canopy-interstitial__layout" }, /* @__PURE__ */ React9.createElement("div", { className: "canopy-interstitial__panel" }, /* @__PURE__ */ React9.createElement("div", { className: "canopy-interstitial__body" }, overlayContent)), /* @__PURE__ */ React9.createElement("div", { className: "canopy-interstitial__media-group" }, renderSlider({ showVeil: false, captionVariant: "static" }))));
714
769
  }
715
770
 
716
771
  // ui/src/layout/SubNavigation.jsx
717
772
  import React10 from "react";
718
- import navigationHelpers from "@canopy-iiif/app/lib/components/navigation.js";
773
+ import navigationHelpers2 from "@canopy-iiif/app/lib/components/navigation.js";
719
774
  function resolveRelativeCandidate(page, current) {
720
775
  if (page && typeof page.relativePath === "string" && page.relativePath)
721
776
  return page.relativePath;
@@ -770,7 +825,7 @@ function SubNavigation({
770
825
  heading,
771
826
  ariaLabel
772
827
  }) {
773
- const PageContext = navigationHelpers && navigationHelpers.getPageContext ? navigationHelpers.getPageContext() : null;
828
+ const PageContext = navigationHelpers2 && navigationHelpers2.getPageContext ? navigationHelpers2.getPageContext() : null;
774
829
  const context = PageContext ? React10.useContext(PageContext) : null;
775
830
  const contextNavigation = context && context.navigation ? context.navigation : null;
776
831
  const contextPage = context && context.page ? context.page : null;
@@ -781,10 +836,10 @@ function SubNavigation({
781
836
  return effectiveNavigation;
782
837
  const candidate = resolveRelativeCandidate(effectivePage, current);
783
838
  if (!candidate) return effectiveNavigation || null;
784
- const helpers2 = navigationHelpers && navigationHelpers.buildNavigationForFile ? navigationHelpers : null;
839
+ const helpers2 = navigationHelpers2 && navigationHelpers2.buildNavigationForFile ? navigationHelpers2 : null;
785
840
  if (!helpers2) return effectiveNavigation || null;
786
841
  try {
787
- const normalized = navigationHelpers.normalizeRelativePath ? navigationHelpers.normalizeRelativePath(candidate) : candidate;
842
+ const normalized = navigationHelpers2.normalizeRelativePath ? navigationHelpers2.normalizeRelativePath(candidate) : candidate;
788
843
  const built = helpers2.buildNavigationForFile(normalized);
789
844
  if (built) return built;
790
845
  } catch (_) {
@@ -815,7 +870,7 @@ function SubNavigation({
815
870
 
816
871
  // ui/src/layout/Layout.jsx
817
872
  import React12 from "react";
818
- import navigationHelpers2 from "@canopy-iiif/app/lib/components/navigation.js";
873
+ import navigationHelpers3 from "@canopy-iiif/app/lib/components/navigation.js";
819
874
 
820
875
  // ui/src/layout/ContentNavigation.jsx
821
876
  import React11 from "react";
@@ -1215,7 +1270,7 @@ function Layout({
1215
1270
  contentNavigationClassName = "",
1216
1271
  ...rest
1217
1272
  }) {
1218
- const PageContext = navigationHelpers2 && typeof navigationHelpers2.getPageContext === "function" ? navigationHelpers2.getPageContext() : null;
1273
+ const PageContext = navigationHelpers3 && typeof navigationHelpers3.getPageContext === "function" ? navigationHelpers3.getPageContext() : null;
1219
1274
  const context = PageContext ? React12.useContext(PageContext) : null;
1220
1275
  const pageHeadings = React12.useMemo(() => {
1221
1276
  const headings = context && context.page ? context.page.headings : null;
@@ -2030,7 +2085,7 @@ function Container({
2030
2085
 
2031
2086
  // ui/src/content/ReferencedItems.jsx
2032
2087
  import React23 from "react";
2033
- import navigationHelpers3 from "@canopy-iiif/app/lib/components/navigation.js";
2088
+ import navigationHelpers4 from "@canopy-iiif/app/lib/components/navigation.js";
2034
2089
 
2035
2090
  // ui/src/layout/Card.jsx
2036
2091
  import React22, { useEffect as useEffect5, useRef, useState as useState5 } from "react";
@@ -2137,7 +2192,7 @@ function Card({
2137
2192
  // ui/src/content/ReferencedItems.jsx
2138
2193
  function useReferencedItems(itemsProp) {
2139
2194
  if (Array.isArray(itemsProp)) return itemsProp;
2140
- const PageContext = navigationHelpers3 && typeof navigationHelpers3.getPageContext === "function" ? navigationHelpers3.getPageContext() : null;
2195
+ const PageContext = navigationHelpers4 && typeof navigationHelpers4.getPageContext === "function" ? navigationHelpers4.getPageContext() : null;
2141
2196
  if (!PageContext) return [];
2142
2197
  const context = React23.useContext(PageContext);
2143
2198
  const items = context && context.page ? context.page.referencedItems : null;
@@ -2183,13 +2238,13 @@ function ReferencedItems({
2183
2238
 
2184
2239
  // ui/src/content/References.jsx
2185
2240
  import React24 from "react";
2186
- import navigationHelpers4 from "@canopy-iiif/app/lib/components/navigation.js";
2241
+ import navigationHelpers5 from "@canopy-iiif/app/lib/components/navigation.js";
2187
2242
  function getPageContext() {
2188
- if (!navigationHelpers4 || typeof navigationHelpers4.getPageContext !== "function") {
2243
+ if (!navigationHelpers5 || typeof navigationHelpers5.getPageContext !== "function") {
2189
2244
  return null;
2190
2245
  }
2191
2246
  try {
2192
- return navigationHelpers4.getPageContext();
2247
+ return navigationHelpers5.getPageContext();
2193
2248
  } catch (_) {
2194
2249
  return null;
2195
2250
  }