@canopy-iiif/app 0.12.5 → 0.12.6

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.
@@ -2489,6 +2489,8 @@ function clampProgress(value) {
2489
2489
 
2490
2490
  // ui/src/content/timeline/Timeline.jsx
2491
2491
  var DAY_MS = 24 * 60 * 60 * 1e3;
2492
+ var DEFAULT_TRACK_HEIGHT = 640;
2493
+ var MIN_HEIGHT_PER_POINT = 220;
2492
2494
  function getThresholdMs(threshold, granularity) {
2493
2495
  const value = Number(threshold);
2494
2496
  if (!Number.isFinite(value) || value <= 0) return 0;
@@ -2618,6 +2620,31 @@ function sanitizePoints(points) {
2618
2620
  };
2619
2621
  }).filter(Boolean);
2620
2622
  }
2623
+ function resolveTrackHeight(height, pointCount) {
2624
+ const minimumPx = Math.max(
2625
+ DEFAULT_TRACK_HEIGHT,
2626
+ pointCount * MIN_HEIGHT_PER_POINT
2627
+ );
2628
+ const fallback = `${minimumPx}px`;
2629
+ if (height == null) return fallback;
2630
+ if (typeof height === "number") {
2631
+ const numeric = Number(height);
2632
+ if (Number.isFinite(numeric)) {
2633
+ return `${Math.max(numeric, pointCount * MIN_HEIGHT_PER_POINT)}px`;
2634
+ }
2635
+ return fallback;
2636
+ }
2637
+ if (typeof height === "string") {
2638
+ const trimmed = height.trim();
2639
+ if (!trimmed) return fallback;
2640
+ const numeric = Number(trimmed);
2641
+ if (Number.isFinite(numeric)) {
2642
+ return `${Math.max(numeric, pointCount * MIN_HEIGHT_PER_POINT)}px`;
2643
+ }
2644
+ return trimmed;
2645
+ }
2646
+ return fallback;
2647
+ }
2621
2648
  function TimelineConnector({ side, isActive, highlight }) {
2622
2649
  const connectorClasses = [
2623
2650
  "canopy-timeline__connector",
@@ -2634,7 +2661,7 @@ function renderResourceSection(point) {
2634
2661
  const manifestCards = Array.isArray(point.manifests) ? point.manifests.filter(Boolean) : [];
2635
2662
  const legacyResources = Array.isArray(point.resources) ? point.resources.filter(Boolean) : [];
2636
2663
  if (!manifestCards.length && !legacyResources.length) return null;
2637
- return /* @__PURE__ */ React26.createElement("div", { className: "canopy-timeline__resources" }, /* @__PURE__ */ React26.createElement("ul", { className: "canopy-timeline__resources-list" }, manifestCards.map((manifest) => /* @__PURE__ */ React26.createElement("li", { key: manifest.id || manifest.href }, /* @__PURE__ */ React26.createElement(
2664
+ return /* @__PURE__ */ React26.createElement("div", { className: "canopy-timeline__resources" }, /* @__PURE__ */ React26.createElement("div", { className: "canopy-timeline__resources-list" }, manifestCards.map((manifest) => /* @__PURE__ */ React26.createElement("div", { key: manifest.id || manifest.href }, /* @__PURE__ */ React26.createElement(
2638
2665
  TeaserCard,
2639
2666
  {
2640
2667
  href: manifest.href,
@@ -2644,7 +2671,7 @@ function renderResourceSection(point) {
2644
2671
  thumbnail: manifest.thumbnail,
2645
2672
  type: manifest.type || "work"
2646
2673
  }
2647
- ))), legacyResources.map((resource, idx) => /* @__PURE__ */ React26.createElement("li", { key: resource.id || resource.href || `legacy-${idx}` }, /* @__PURE__ */ React26.createElement(
2674
+ ))), legacyResources.map((resource, idx) => /* @__PURE__ */ React26.createElement("div", { key: resource.id || resource.href || `legacy-${idx}` }, /* @__PURE__ */ React26.createElement(
2648
2675
  TeaserCard,
2649
2676
  {
2650
2677
  href: resource.href,
@@ -2661,7 +2688,7 @@ function Timeline({
2661
2688
  description,
2662
2689
  range: rangeProp,
2663
2690
  locale: localeProp = "en-US",
2664
- height = 640,
2691
+ height = DEFAULT_TRACK_HEIGHT,
2665
2692
  threshold: thresholdProp = null,
2666
2693
  steps = null,
2667
2694
  points: pointsProp,
@@ -2679,7 +2706,10 @@ function Timeline({
2679
2706
  [rawPoints]
2680
2707
  );
2681
2708
  const localeValue = payload && payload.locale ? payload.locale : localeProp;
2682
- const baseLocale = React26.useMemo(() => createLocale(localeValue), [localeValue]);
2709
+ const baseLocale = React26.useMemo(
2710
+ () => createLocale(localeValue),
2711
+ [localeValue]
2712
+ );
2683
2713
  const rangeInput = payload && payload.range ? payload.range : rangeProp || {};
2684
2714
  const rangeOverrides = React26.useMemo(
2685
2715
  () => deriveRangeOverrides(sanitizedPoints, rangeInput),
@@ -2727,7 +2757,9 @@ function Timeline({
2727
2757
  }),
2728
2758
  [pointsWithPosition, thresholdMs, effectiveRange.granularity, baseLocale]
2729
2759
  );
2730
- const [expandedGroupIds, setExpandedGroupIds] = React26.useState(() => /* @__PURE__ */ new Set());
2760
+ const [expandedGroupIds, setExpandedGroupIds] = React26.useState(
2761
+ () => /* @__PURE__ */ new Set()
2762
+ );
2731
2763
  React26.useEffect(() => {
2732
2764
  setExpandedGroupIds((prev) => {
2733
2765
  if (!prev || prev.size === 0) return prev;
@@ -2751,8 +2783,7 @@ function Timeline({
2751
2783
  return next;
2752
2784
  });
2753
2785
  }, []);
2754
- const resolvedHeight = Number.isFinite(Number(height)) ? Number(height) : 640;
2755
- const trackHeight = Math.max(resolvedHeight, pointsWithPosition.length * 220);
2786
+ const trackHeight = resolveTrackHeight(height, pointsWithPosition.length);
2756
2787
  const containerClasses = ["canopy-timeline", className].filter(Boolean).join(" ");
2757
2788
  const rangeLabel = formatRangeLabel(effectiveRange);
2758
2789
  function renderPointEntry(point) {
@@ -2761,7 +2792,7 @@ function Timeline({
2761
2792
  "canopy-timeline__point-wrapper",
2762
2793
  point.side === "left" ? "canopy-timeline__point-wrapper--left" : "canopy-timeline__point-wrapper--right"
2763
2794
  ].filter(Boolean).join(" ");
2764
- const wrapperStyle = { top: `calc(${point.progress * 100}% - 1rem)` };
2795
+ const wrapperStyle = { top: `${point.progress * 100}%` };
2765
2796
  const cardClasses = [
2766
2797
  "canopy-timeline__point",
2767
2798
  point.id === activeId ? "is-active" : "",
@@ -2793,7 +2824,7 @@ function Timeline({
2793
2824
  "canopy-timeline__point-wrapper",
2794
2825
  entry.side === "left" ? "canopy-timeline__point-wrapper--left" : "canopy-timeline__point-wrapper--right"
2795
2826
  ].filter(Boolean).join(" ");
2796
- const wrapperStyle = { top: `calc(${entry.progress * 100}% - 1rem)` };
2827
+ const wrapperStyle = { top: `${entry.progress * 100}%` };
2797
2828
  const isExpanded = expandedGroupIds.has(entry.id);
2798
2829
  const hasActivePoint = entry.points.some((point) => point.id === activeId);
2799
2830
  const connector = /* @__PURE__ */ React26.createElement(
@@ -2810,7 +2841,7 @@ function Timeline({
2810
2841
  hasActivePoint ? "is-active" : ""
2811
2842
  ].filter(Boolean).join(" ");
2812
2843
  const countLabel = `${entry.count} event${entry.count > 1 ? "s" : ""}`;
2813
- const header = /* @__PURE__ */ React26.createElement("div", { className: "canopy-timeline__group-header" }, /* @__PURE__ */ React26.createElement("div", { className: "canopy-timeline__group-summary" }, /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__group-count" }, countLabel), /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__group-range" }, entry.label)), /* @__PURE__ */ React26.createElement(
2844
+ const header = /* @__PURE__ */ React26.createElement("div", { className: "canopy-timeline__group-header" }, /* @__PURE__ */ React26.createElement("div", { className: "canopy-timeline__group-summary" }, /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__point-date" }, entry.label), /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__group-count" }, countLabel)), /* @__PURE__ */ React26.createElement(
2814
2845
  "button",
2815
2846
  {
2816
2847
  type: "button",
@@ -2831,7 +2862,7 @@ function Timeline({
2831
2862
  ].filter(Boolean).join(" "),
2832
2863
  onClick: () => setActiveId(point.id)
2833
2864
  },
2834
- /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__group-point-date" }, point.meta.label),
2865
+ /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label),
2835
2866
  /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__group-point-title" }, point.title)
2836
2867
  ))) : null;
2837
2868
  const groupCard = /* @__PURE__ */ React26.createElement("div", { className: groupClasses }, header, groupPoints);
@@ -2851,7 +2882,7 @@ function Timeline({
2851
2882
  {
2852
2883
  className: "canopy-timeline__list",
2853
2884
  role: "list",
2854
- style: { minHeight: `${trackHeight}px` }
2885
+ style: { minHeight: trackHeight }
2855
2886
  },
2856
2887
  /* @__PURE__ */ React26.createElement("div", { className: "canopy-timeline__spine", "aria-hidden": "true" }),
2857
2888
  renderSteps(stepsValue, effectiveRange),
@@ -2872,7 +2903,7 @@ function renderSteps(stepSize, range) {
2872
2903
  "span",
2873
2904
  {
2874
2905
  key: "timeline-step-start",
2875
- className: "canopy-timeline__step canopy-timeline__step--edge",
2906
+ className: "canopy-timeline__step canopy-timeline__step--start",
2876
2907
  style: { top: "0%" },
2877
2908
  "aria-hidden": "true"
2878
2909
  },
@@ -2885,8 +2916,8 @@ function renderSteps(stepSize, range) {
2885
2916
  "span",
2886
2917
  {
2887
2918
  key: "timeline-step-end",
2888
- className: "canopy-timeline__step canopy-timeline__step--edge",
2889
- style: { top: "calc(100% - 1px)" },
2919
+ className: "canopy-timeline__step canopy-timeline__step--end",
2920
+ style: { top: "100%" },
2890
2921
  "aria-hidden": "true"
2891
2922
  },
2892
2923
  /* @__PURE__ */ React26.createElement("span", { className: "canopy-timeline__step-line" }),