@canopy-iiif/app 1.5.8 → 1.5.10
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/lib/build/iiif.js +7 -2
- package/lib/build/pages.js +20 -2
- package/lib/components/navigation.js +21 -0
- package/package.json +1 -1
- package/ui/dist/index.mjs +540 -201
- package/ui/dist/index.mjs.map +4 -4
- package/ui/dist/server.mjs +624 -306
- package/ui/dist/server.mjs.map +4 -4
- package/ui/styles/components/_diagram.scss +1 -1
- package/ui/styles/components/_footer.scss +1 -1
- package/ui/styles/components/_layout.scss +16 -2
- package/ui/styles/components/_nav-tree.scss +67 -0
- package/ui/styles/components/_sub-navigation.scss +38 -17
- package/ui/styles/components/_work.scss +1 -1
- package/ui/styles/components/header/_header.scss +3 -1
- package/ui/styles/components/header/_navbar.scss +65 -50
- package/ui/styles/components/iiif/_image.scss +1 -1
- package/ui/styles/components/index.scss +1 -0
- package/ui/styles/components/search/_form.scss +1 -1
- package/ui/styles/components/search/_results.scss +1 -1
- package/ui/styles/index.css +174 -73
- package/ui/styles/settings/_breakpoints.scss +7 -0
package/ui/dist/index.mjs
CHANGED
|
@@ -93,6 +93,7 @@ function Card({
|
|
|
93
93
|
{
|
|
94
94
|
src,
|
|
95
95
|
alt: alt || title || "",
|
|
96
|
+
"aria-hidden": !alt && !title ? "true" : void 0,
|
|
96
97
|
loading: "lazy",
|
|
97
98
|
onLoad: () => setImageLoaded(true),
|
|
98
99
|
onError: () => setImageLoaded(true)
|
|
@@ -103,6 +104,7 @@ function Card({
|
|
|
103
104
|
{
|
|
104
105
|
src,
|
|
105
106
|
alt: alt || title || "",
|
|
107
|
+
"aria-hidden": !alt && !title ? "true" : void 0,
|
|
106
108
|
loading: "lazy",
|
|
107
109
|
onLoad: () => setImageLoaded(true),
|
|
108
110
|
onError: () => setImageLoaded(true),
|
|
@@ -269,7 +271,7 @@ function renderMarkdownTokens(tokens, query, keyPrefix = "token") {
|
|
|
269
271
|
case "code":
|
|
270
272
|
return /* @__PURE__ */ React3.createElement("code", { key }, token.value);
|
|
271
273
|
case "link":
|
|
272
|
-
return /* @__PURE__ */ React3.createElement("a", { key, href: token.href, target: "_blank", rel: "noreferrer" }, renderMarkdownTokens(token.children || [], query, key));
|
|
274
|
+
return /* @__PURE__ */ React3.createElement("a", { key, href: token.href, target: "_blank", rel: "noreferrer" }, renderMarkdownTokens(token.children || [], query, key), /* @__PURE__ */ React3.createElement("span", { className: "sr-only" }, " (opens in new tab)"));
|
|
273
275
|
case "break":
|
|
274
276
|
return /* @__PURE__ */ React3.createElement("br", { key });
|
|
275
277
|
case "text":
|
|
@@ -449,14 +451,14 @@ function ButtonWrapper({
|
|
|
449
451
|
}
|
|
450
452
|
|
|
451
453
|
// ui/src/layout/CanopyHeader.jsx
|
|
452
|
-
import
|
|
454
|
+
import React15 from "react";
|
|
453
455
|
|
|
454
456
|
// ui/src/search/SearchPanel.jsx
|
|
455
457
|
import React11 from "react";
|
|
456
458
|
|
|
457
459
|
// ui/src/Icons.jsx
|
|
458
460
|
import React8 from "react";
|
|
459
|
-
var MagnifyingGlassIcon = (props) => /* @__PURE__ */ React8.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512", ...props }, /* @__PURE__ */ React8.createElement("path", { d: "M456.69 421.39L362.6 327.3a173.81 173.81 0 0034.84-104.58C397.44 126.38 319.06 48 222.72 48S48 126.38 48 222.72s78.38 174.72 174.72 174.72A173.81 173.81 0 00327.3 362.6l94.09 94.09a25 25 0 0035.3-35.3zM97.92 222.72a124.8 124.8 0 11124.8 124.8 124.95 124.95 0 01-124.8-124.8z" }));
|
|
461
|
+
var MagnifyingGlassIcon = (props) => /* @__PURE__ */ React8.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512", "aria-hidden": "true", focusable: "false", ...props }, /* @__PURE__ */ React8.createElement("path", { d: "M456.69 421.39L362.6 327.3a173.81 173.81 0 0034.84-104.58C397.44 126.38 319.06 48 222.72 48S48 126.38 48 222.72s78.38 174.72 174.72 174.72A173.81 173.81 0 00327.3 362.6l94.09 94.09a25 25 0 0035.3-35.3zM97.92 222.72a124.8 124.8 0 11124.8 124.8 124.95 124.95 0 01-124.8-124.8z" }));
|
|
460
462
|
|
|
461
463
|
// ui/src/search/SearchPanelForm.jsx
|
|
462
464
|
import React9 from "react";
|
|
@@ -595,7 +597,7 @@ function SearchPanelForm(props = {}) {
|
|
|
595
597
|
onPointerDown: handlePointerDown,
|
|
596
598
|
"data-has-value": hasValue ? "1" : "0"
|
|
597
599
|
},
|
|
598
|
-
/* @__PURE__ */ React9.createElement("label", { htmlFor: inputId, className: "canopy-search-form__label" }, /* @__PURE__ */ React9.createElement(MagnifyingGlassIcon, { className: "canopy-search-form__icon" }), /* @__PURE__ */ React9.createElement(
|
|
600
|
+
/* @__PURE__ */ React9.createElement("label", { htmlFor: inputId, className: "canopy-search-form__label" }, /* @__PURE__ */ React9.createElement(MagnifyingGlassIcon, { className: "canopy-search-form__icon" }), /* @__PURE__ */ React9.createElement("span", { className: "sr-only" }, "Search"), /* @__PURE__ */ React9.createElement(
|
|
599
601
|
"input",
|
|
600
602
|
{
|
|
601
603
|
id: inputId,
|
|
@@ -605,7 +607,6 @@ function SearchPanelForm(props = {}) {
|
|
|
605
607
|
"data-canopy-search-form-input": true,
|
|
606
608
|
placeholder,
|
|
607
609
|
className: "canopy-search-form__input",
|
|
608
|
-
"aria-label": "Search",
|
|
609
610
|
ref: inputRef,
|
|
610
611
|
onChange: handleInputChange,
|
|
611
612
|
onInput: handleInputChange
|
|
@@ -763,6 +764,130 @@ function CanopyModal(props = {}) {
|
|
|
763
764
|
)) : null, children)));
|
|
764
765
|
}
|
|
765
766
|
|
|
767
|
+
// ui/src/layout/NavigationTree.jsx
|
|
768
|
+
import React14 from "react";
|
|
769
|
+
function normalizeDepth(depth) {
|
|
770
|
+
if (typeof depth !== "number") return 0;
|
|
771
|
+
return Math.max(0, Math.min(5, depth));
|
|
772
|
+
}
|
|
773
|
+
function NavigationTreeList({ nodes, depth, parentKey }) {
|
|
774
|
+
if (!Array.isArray(nodes) || !nodes.length) return null;
|
|
775
|
+
const listClasses = ["canopy-nav-tree__list"];
|
|
776
|
+
if (depth > 0) listClasses.push("canopy-nav-tree__list--nested");
|
|
777
|
+
return /* @__PURE__ */ React14.createElement("ul", { className: listClasses.join(" "), role: "list" }, nodes.map((node, index) => /* @__PURE__ */ React14.createElement(
|
|
778
|
+
NavigationTreeItem,
|
|
779
|
+
{
|
|
780
|
+
key: node.slug || node.href || node.title || `${parentKey}-${index}`,
|
|
781
|
+
node,
|
|
782
|
+
depth,
|
|
783
|
+
nodeKey: `${parentKey}-${index}`
|
|
784
|
+
}
|
|
785
|
+
)));
|
|
786
|
+
}
|
|
787
|
+
function NavigationTreeItem({ node, depth, nodeKey }) {
|
|
788
|
+
if (!node) return null;
|
|
789
|
+
const hasChildren = Array.isArray(node.children) && node.children.length > 0;
|
|
790
|
+
const isRoadmap = !!node.isRoadmap;
|
|
791
|
+
const isInteractive = !!(node.href && !isRoadmap);
|
|
792
|
+
const Tag = isInteractive ? "a" : "span";
|
|
793
|
+
const depthClass = `depth-${normalizeDepth(depth + 1)}`;
|
|
794
|
+
const classes = ["canopy-nav-tree__link", depthClass];
|
|
795
|
+
if (!isInteractive && !isRoadmap) classes.push("is-label");
|
|
796
|
+
if (isRoadmap) classes.push("is-disabled");
|
|
797
|
+
if (node.isActive) classes.push("is-active");
|
|
798
|
+
const isRootLevel = depth < 0;
|
|
799
|
+
const panelId = hasChildren ? `canopy-section-${nodeKey}` : null;
|
|
800
|
+
const allowToggle = hasChildren && !isRootLevel;
|
|
801
|
+
const defaultExpanded = allowToggle ? !!node.isExpanded : true;
|
|
802
|
+
const toggleLabel = node.title ? `Toggle ${node.title} menu` : "Toggle section menu";
|
|
803
|
+
return /* @__PURE__ */ React14.createElement(
|
|
804
|
+
"li",
|
|
805
|
+
{
|
|
806
|
+
className: "canopy-nav-tree__item",
|
|
807
|
+
"data-depth": depth,
|
|
808
|
+
"data-canopy-nav-item": allowToggle ? "true" : void 0,
|
|
809
|
+
"data-expanded": allowToggle ? defaultExpanded ? "true" : "false" : void 0,
|
|
810
|
+
"data-default-expanded": allowToggle && defaultExpanded ? "true" : void 0
|
|
811
|
+
},
|
|
812
|
+
/* @__PURE__ */ React14.createElement("div", { className: "canopy-nav-tree__row" }, /* @__PURE__ */ React14.createElement(
|
|
813
|
+
Tag,
|
|
814
|
+
{
|
|
815
|
+
className: classes.join(" "),
|
|
816
|
+
href: isInteractive ? node.href : void 0,
|
|
817
|
+
"aria-current": node.isActive ? "page" : void 0,
|
|
818
|
+
tabIndex: isInteractive ? void 0 : -1
|
|
819
|
+
},
|
|
820
|
+
node.title || node.slug,
|
|
821
|
+
isRoadmap ? /* @__PURE__ */ React14.createElement("span", { className: "canopy-nav-tree__badge" }, "Roadmap") : null
|
|
822
|
+
), allowToggle ? /* @__PURE__ */ React14.createElement(
|
|
823
|
+
"button",
|
|
824
|
+
{
|
|
825
|
+
type: "button",
|
|
826
|
+
className: "canopy-nav-tree__toggle",
|
|
827
|
+
"aria-expanded": defaultExpanded ? "true" : "false",
|
|
828
|
+
"aria-controls": panelId || void 0,
|
|
829
|
+
"aria-label": toggleLabel,
|
|
830
|
+
"data-canopy-nav-item-toggle": panelId || void 0
|
|
831
|
+
},
|
|
832
|
+
/* @__PURE__ */ React14.createElement(
|
|
833
|
+
"svg",
|
|
834
|
+
{
|
|
835
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
836
|
+
viewBox: "0 0 24 24",
|
|
837
|
+
fill: "none",
|
|
838
|
+
stroke: "currentColor",
|
|
839
|
+
strokeWidth: "1.5",
|
|
840
|
+
className: "canopy-nav-tree__toggle-icon"
|
|
841
|
+
},
|
|
842
|
+
/* @__PURE__ */ React14.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 9l7 7 7-7" })
|
|
843
|
+
),
|
|
844
|
+
/* @__PURE__ */ React14.createElement("span", { className: "sr-only" }, toggleLabel)
|
|
845
|
+
) : null),
|
|
846
|
+
hasChildren ? /* @__PURE__ */ React14.createElement(
|
|
847
|
+
"div",
|
|
848
|
+
{
|
|
849
|
+
id: panelId || void 0,
|
|
850
|
+
className: "canopy-nav-tree__children",
|
|
851
|
+
"aria-hidden": allowToggle ? defaultExpanded ? "false" : "true" : "false",
|
|
852
|
+
hidden: allowToggle ? !defaultExpanded : void 0
|
|
853
|
+
},
|
|
854
|
+
/* @__PURE__ */ React14.createElement(
|
|
855
|
+
NavigationTreeList,
|
|
856
|
+
{
|
|
857
|
+
nodes: node.children,
|
|
858
|
+
depth: depth + 1,
|
|
859
|
+
parentKey: nodeKey
|
|
860
|
+
}
|
|
861
|
+
)
|
|
862
|
+
) : null
|
|
863
|
+
);
|
|
864
|
+
}
|
|
865
|
+
function NavigationTree({
|
|
866
|
+
root,
|
|
867
|
+
className = "",
|
|
868
|
+
parentKey = "nav",
|
|
869
|
+
includeRoot = false,
|
|
870
|
+
heading,
|
|
871
|
+
headingClassName = "canopy-nav-tree__heading",
|
|
872
|
+
component: Component = "div",
|
|
873
|
+
...rest
|
|
874
|
+
}) {
|
|
875
|
+
if (!root) return null;
|
|
876
|
+
const nodes = includeRoot ? [root] : root.children;
|
|
877
|
+
if (!Array.isArray(nodes) || !nodes.length) return null;
|
|
878
|
+
const combinedClassName = ["canopy-nav-tree", className].filter(Boolean).join(" ");
|
|
879
|
+
return /* @__PURE__ */ React14.createElement(
|
|
880
|
+
Component,
|
|
881
|
+
{
|
|
882
|
+
className: combinedClassName,
|
|
883
|
+
"data-canopy-nav-tree": "true",
|
|
884
|
+
...rest
|
|
885
|
+
},
|
|
886
|
+
heading ? /* @__PURE__ */ React14.createElement("div", { className: headingClassName }, heading) : null,
|
|
887
|
+
/* @__PURE__ */ React14.createElement(NavigationTreeList, { nodes, depth: includeRoot ? -1 : 0, parentKey })
|
|
888
|
+
);
|
|
889
|
+
}
|
|
890
|
+
|
|
766
891
|
// ui/src/layout/CanopyHeader.jsx
|
|
767
892
|
function HeaderScript() {
|
|
768
893
|
const code = `
|
|
@@ -773,11 +898,24 @@ function HeaderScript() {
|
|
|
773
898
|
var body = doc.body;
|
|
774
899
|
var root = doc.documentElement;
|
|
775
900
|
|
|
901
|
+
function desktopBreakpointQuery() {
|
|
902
|
+
if (typeof window === 'undefined') return '(min-width: 70rem)';
|
|
903
|
+
try {
|
|
904
|
+
var styles = window.getComputedStyle ? window.getComputedStyle(root) : null;
|
|
905
|
+
var value = styles ? styles.getPropertyValue('--canopy-desktop-breakpoint') : '';
|
|
906
|
+
if (typeof value === 'string') value = value.trim();
|
|
907
|
+
if (!value) value = '70rem';
|
|
908
|
+
return '(min-width: ' + value + ')';
|
|
909
|
+
} catch (error) {
|
|
910
|
+
return '(min-width: 70rem)';
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
|
|
776
914
|
function ready(fn) {
|
|
777
915
|
if (doc.readyState === 'loading') {
|
|
778
916
|
doc.addEventListener('DOMContentLoaded', fn, { once: true });
|
|
779
917
|
} else {
|
|
780
|
-
fn();
|
|
918
|
+
fn();
|
|
781
919
|
}
|
|
782
920
|
}
|
|
783
921
|
|
|
@@ -787,6 +925,8 @@ function HeaderScript() {
|
|
|
787
925
|
|
|
788
926
|
var NAV_ATTR = 'data-mobile-nav';
|
|
789
927
|
var SEARCH_ATTR = 'data-mobile-search';
|
|
928
|
+
var NAV_ITEM_ATTR = 'data-canopy-nav-item';
|
|
929
|
+
var NAV_ITEM_TOGGLE_ATTR = 'data-canopy-nav-item-toggle';
|
|
790
930
|
|
|
791
931
|
function modalFor(type) {
|
|
792
932
|
return doc.querySelector('[data-canopy-modal="' + type + '"]');
|
|
@@ -868,6 +1008,51 @@ function HeaderScript() {
|
|
|
868
1008
|
});
|
|
869
1009
|
}
|
|
870
1010
|
|
|
1011
|
+
function forEachNavTree(scope, fn) {
|
|
1012
|
+
if (typeof fn !== 'function') return;
|
|
1013
|
+
var rootNode = scope || doc;
|
|
1014
|
+
var trees = rootNode.querySelectorAll('[data-canopy-nav-tree]');
|
|
1015
|
+
each(trees, function (tree) {
|
|
1016
|
+
fn(tree);
|
|
1017
|
+
});
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
function resetNavItemToggles(scope) {
|
|
1021
|
+
forEachNavTree(scope, function (tree) {
|
|
1022
|
+
var toggles = tree.querySelectorAll('[' + NAV_ITEM_TOGGLE_ATTR + ']');
|
|
1023
|
+
each(toggles, function (btn) {
|
|
1024
|
+
btn.setAttribute('aria-expanded', 'false');
|
|
1025
|
+
var targetId = btn.getAttribute(NAV_ITEM_TOGGLE_ATTR);
|
|
1026
|
+
var panel = targetId ? doc.getElementById(targetId) : null;
|
|
1027
|
+
var parent = btn.closest('[' + NAV_ITEM_ATTR + ']');
|
|
1028
|
+
if (panel) {
|
|
1029
|
+
panel.hidden = true;
|
|
1030
|
+
panel.setAttribute('aria-hidden', 'true');
|
|
1031
|
+
panel.setAttribute('hidden', '');
|
|
1032
|
+
}
|
|
1033
|
+
if (parent) parent.setAttribute('data-expanded', 'false');
|
|
1034
|
+
});
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
function applyDefaultNavItemState(scope) {
|
|
1039
|
+
forEachNavTree(scope, function (tree) {
|
|
1040
|
+
var defaults = tree.querySelectorAll('[data-default-expanded="true"]');
|
|
1041
|
+
each(defaults, function (item) {
|
|
1042
|
+
var toggle = item.querySelector('[' + NAV_ITEM_TOGGLE_ATTR + ']');
|
|
1043
|
+
var targetId = toggle ? toggle.getAttribute(NAV_ITEM_TOGGLE_ATTR) : null;
|
|
1044
|
+
var panel = targetId ? doc.getElementById(targetId) : null;
|
|
1045
|
+
item.setAttribute('data-expanded', 'true');
|
|
1046
|
+
if (toggle) toggle.setAttribute('aria-expanded', 'true');
|
|
1047
|
+
if (panel) {
|
|
1048
|
+
panel.hidden = false;
|
|
1049
|
+
panel.removeAttribute('hidden');
|
|
1050
|
+
panel.setAttribute('aria-hidden', 'false');
|
|
1051
|
+
}
|
|
1052
|
+
});
|
|
1053
|
+
});
|
|
1054
|
+
}
|
|
1055
|
+
|
|
871
1056
|
function setState(type, next) {
|
|
872
1057
|
if (type === 'nav') header.setAttribute(NAV_ATTR, next);
|
|
873
1058
|
if (type === 'search') header.setAttribute(SEARCH_ATTR, next);
|
|
@@ -875,6 +1060,13 @@ function HeaderScript() {
|
|
|
875
1060
|
var navOpen = header.getAttribute(NAV_ATTR) === 'open';
|
|
876
1061
|
var searchOpen = header.getAttribute(SEARCH_ATTR) === 'open';
|
|
877
1062
|
lockScroll(navOpen || searchOpen);
|
|
1063
|
+
if (type === 'nav') {
|
|
1064
|
+
if (next !== 'open') {
|
|
1065
|
+
resetNavItemToggles(modalFor('nav'));
|
|
1066
|
+
} else {
|
|
1067
|
+
applyDefaultNavItemState(modalFor('nav'));
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
878
1070
|
}
|
|
879
1071
|
|
|
880
1072
|
function toggle(type, force) {
|
|
@@ -887,6 +1079,35 @@ function HeaderScript() {
|
|
|
887
1079
|
if (type === 'nav' && shouldOpen) focusNavMenu();
|
|
888
1080
|
}
|
|
889
1081
|
|
|
1082
|
+
function setupNavItemToggles() {
|
|
1083
|
+
var toggles = doc.querySelectorAll('[' + NAV_ITEM_TOGGLE_ATTR + ']');
|
|
1084
|
+
each(toggles, function (btn) {
|
|
1085
|
+
if (btn.__canopyNavReady) return;
|
|
1086
|
+
btn.__canopyNavReady = true;
|
|
1087
|
+
btn.addEventListener('click', function (event) {
|
|
1088
|
+
event.preventDefault();
|
|
1089
|
+
event.stopPropagation();
|
|
1090
|
+
var targetId = btn.getAttribute(NAV_ITEM_TOGGLE_ATTR);
|
|
1091
|
+
if (!targetId) return;
|
|
1092
|
+
var panel = doc.getElementById(targetId);
|
|
1093
|
+
var parent = btn.closest('[' + NAV_ITEM_ATTR + ']');
|
|
1094
|
+
var expanded = btn.getAttribute('aria-expanded') === 'true';
|
|
1095
|
+
var next = !expanded;
|
|
1096
|
+
btn.setAttribute('aria-expanded', next ? 'true' : 'false');
|
|
1097
|
+
if (panel) {
|
|
1098
|
+
panel.hidden = !next;
|
|
1099
|
+
panel.setAttribute('aria-hidden', next ? 'false' : 'true');
|
|
1100
|
+
if (next) {
|
|
1101
|
+
panel.removeAttribute('hidden');
|
|
1102
|
+
} else {
|
|
1103
|
+
panel.setAttribute('hidden', '');
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
if (parent) parent.setAttribute('data-expanded', next ? 'true' : 'false');
|
|
1107
|
+
});
|
|
1108
|
+
});
|
|
1109
|
+
}
|
|
1110
|
+
|
|
890
1111
|
each(header.querySelectorAll('[data-canopy-header-toggle]'), function (btn) {
|
|
891
1112
|
btn.addEventListener('click', function (event) {
|
|
892
1113
|
event.preventDefault();
|
|
@@ -934,7 +1155,7 @@ function HeaderScript() {
|
|
|
934
1155
|
toggle('search', false);
|
|
935
1156
|
});
|
|
936
1157
|
|
|
937
|
-
var mq = window.matchMedia(
|
|
1158
|
+
var mq = window.matchMedia(desktopBreakpointQuery());
|
|
938
1159
|
function syncDesktopState() {
|
|
939
1160
|
if (mq.matches) {
|
|
940
1161
|
setState('nav', 'closed');
|
|
@@ -951,11 +1172,13 @@ function HeaderScript() {
|
|
|
951
1172
|
mq.addListener(syncDesktopState);
|
|
952
1173
|
}
|
|
953
1174
|
|
|
1175
|
+
setupNavItemToggles();
|
|
1176
|
+
applyDefaultNavItemState(null);
|
|
954
1177
|
syncDesktopState();
|
|
955
1178
|
});
|
|
956
1179
|
})();
|
|
957
1180
|
`;
|
|
958
|
-
return /* @__PURE__ */
|
|
1181
|
+
return /* @__PURE__ */ React15.createElement(
|
|
959
1182
|
"script",
|
|
960
1183
|
{
|
|
961
1184
|
dangerouslySetInnerHTML: {
|
|
@@ -974,7 +1197,7 @@ function getSharedRoot() {
|
|
|
974
1197
|
function getSafePageContext() {
|
|
975
1198
|
const root = getSharedRoot();
|
|
976
1199
|
if (root && root[CONTEXT_KEY]) return root[CONTEXT_KEY];
|
|
977
|
-
const ctx =
|
|
1200
|
+
const ctx = React15.createContext({ navigation: null, page: null });
|
|
978
1201
|
if (root) root[CONTEXT_KEY] = ctx;
|
|
979
1202
|
return ctx;
|
|
980
1203
|
}
|
|
@@ -984,29 +1207,55 @@ function ensureArray(navLinks) {
|
|
|
984
1207
|
(link) => link && typeof link === "object" && typeof link.href === "string"
|
|
985
1208
|
);
|
|
986
1209
|
}
|
|
987
|
-
function
|
|
988
|
-
if (
|
|
989
|
-
|
|
1210
|
+
function normalizeHref(href) {
|
|
1211
|
+
if (typeof href !== "string") return "";
|
|
1212
|
+
let next = href.trim();
|
|
1213
|
+
if (!next) return "";
|
|
1214
|
+
try {
|
|
1215
|
+
const parsed = new URL(next, "https://canopy.local");
|
|
1216
|
+
next = parsed.pathname || "/";
|
|
1217
|
+
} catch (_) {
|
|
1218
|
+
next = next.replace(/[?#].*$/, "");
|
|
1219
|
+
}
|
|
1220
|
+
next = next.replace(/[?#].*$/, "");
|
|
1221
|
+
if (next.length > 1) {
|
|
1222
|
+
next = next.replace(/\/+$/, "");
|
|
1223
|
+
}
|
|
1224
|
+
if (!next) return "/";
|
|
1225
|
+
return next;
|
|
990
1226
|
}
|
|
991
|
-
function
|
|
992
|
-
if (!
|
|
993
|
-
const
|
|
994
|
-
|
|
995
|
-
const
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
if (
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1227
|
+
function doesLinkMatchSection(linkHref, sectionNavigation) {
|
|
1228
|
+
if (!sectionNavigation || !sectionNavigation.root || !linkHref) return false;
|
|
1229
|
+
const normalizedLink = normalizeHref(linkHref);
|
|
1230
|
+
if (!normalizedLink) return false;
|
|
1231
|
+
const root = sectionNavigation.root;
|
|
1232
|
+
if (typeof root.href === "string" && normalizeHref(root.href) === normalizedLink) {
|
|
1233
|
+
return true;
|
|
1234
|
+
}
|
|
1235
|
+
if (root.slug) {
|
|
1236
|
+
const slugPath = normalizeHref(`/${root.slug}`);
|
|
1237
|
+
if (slugPath && normalizedLink === slugPath) {
|
|
1238
|
+
return true;
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
return false;
|
|
1242
|
+
}
|
|
1243
|
+
function rootSegmentFromHref(href) {
|
|
1244
|
+
const normalized = normalizeHref(href);
|
|
1245
|
+
if (!normalized || normalized === "/") return "";
|
|
1246
|
+
const trimmed = normalized.replace(/^\/+/, "");
|
|
1247
|
+
return trimmed.split("/")[0] || "";
|
|
1248
|
+
}
|
|
1249
|
+
function getLinkNavigationData(link, navigationRoots, sectionNavigation) {
|
|
1250
|
+
if (!link || typeof link.href !== "string") return null;
|
|
1251
|
+
const segment = rootSegmentFromHref(link.href);
|
|
1252
|
+
if (navigationRoots && segment && navigationRoots[segment]) {
|
|
1253
|
+
return navigationRoots[segment];
|
|
1254
|
+
}
|
|
1255
|
+
if (sectionNavigation && doesLinkMatchSection(link.href, sectionNavigation)) {
|
|
1256
|
+
return sectionNavigation;
|
|
1257
|
+
}
|
|
1258
|
+
return null;
|
|
1010
1259
|
}
|
|
1011
1260
|
function CanopyHeader(props = {}) {
|
|
1012
1261
|
const {
|
|
@@ -1020,20 +1269,34 @@ function CanopyHeader(props = {}) {
|
|
|
1020
1269
|
} = props;
|
|
1021
1270
|
const navLinks = ensureArray(navLinksProp);
|
|
1022
1271
|
const PageContext = getSafePageContext();
|
|
1023
|
-
const context =
|
|
1024
|
-
const
|
|
1272
|
+
const context = React15.useContext(PageContext);
|
|
1273
|
+
const contextNavigation = context && context.navigation ? context.navigation : null;
|
|
1274
|
+
const sectionNavigation = contextNavigation && contextNavigation.root ? contextNavigation : null;
|
|
1275
|
+
const navigationRoots = contextNavigation && contextNavigation.allRoots ? contextNavigation.allRoots : null;
|
|
1025
1276
|
const sectionHeading = sectionNavigation && sectionNavigation.title || (sectionNavigation && sectionNavigation.root ? sectionNavigation.root.title : "");
|
|
1026
1277
|
const hasSectionNav = !!(sectionNavigation && sectionNavigation.root && Array.isArray(sectionNavigation.root.children) && sectionNavigation.root.children.length);
|
|
1027
1278
|
const sectionLabel = sectionHeading ? `More in ${sectionHeading}` : "More in this section";
|
|
1028
1279
|
const sectionAriaLabel = sectionHeading ? `${sectionHeading} section navigation` : "Section navigation";
|
|
1029
|
-
|
|
1280
|
+
const defaultSectionLabel = sectionLabel;
|
|
1281
|
+
const defaultSectionAriaLabel = sectionAriaLabel;
|
|
1282
|
+
const shouldAttachSectionNav = (link) => {
|
|
1283
|
+
const navData = getLinkNavigationData(
|
|
1284
|
+
link,
|
|
1285
|
+
navigationRoots,
|
|
1286
|
+
sectionNavigation
|
|
1287
|
+
);
|
|
1288
|
+
const rootNode = navData && navData.root;
|
|
1289
|
+
return !!(rootNode && Array.isArray(rootNode.children) && rootNode.children.length);
|
|
1290
|
+
};
|
|
1291
|
+
const hasIntegratedSectionNav = navLinks.some(shouldAttachSectionNav);
|
|
1292
|
+
return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(
|
|
1030
1293
|
"header",
|
|
1031
1294
|
{
|
|
1032
1295
|
className: "canopy-header",
|
|
1033
1296
|
"data-mobile-nav": "closed",
|
|
1034
1297
|
"data-mobile-search": "closed"
|
|
1035
1298
|
},
|
|
1036
|
-
/* @__PURE__ */
|
|
1299
|
+
/* @__PURE__ */ React15.createElement("div", { className: "canopy-header__brand" }, /* @__PURE__ */ React15.createElement(
|
|
1037
1300
|
CanopyBrand,
|
|
1038
1301
|
{
|
|
1039
1302
|
label: title,
|
|
@@ -1042,7 +1305,7 @@ function CanopyHeader(props = {}) {
|
|
|
1042
1305
|
Logo: SiteLogo
|
|
1043
1306
|
}
|
|
1044
1307
|
)),
|
|
1045
|
-
/* @__PURE__ */
|
|
1308
|
+
/* @__PURE__ */ React15.createElement("div", { className: "canopy-header__desktop-search" }, /* @__PURE__ */ React15.createElement(
|
|
1046
1309
|
SearchPanel,
|
|
1047
1310
|
{
|
|
1048
1311
|
label: searchLabel,
|
|
@@ -1050,15 +1313,23 @@ function CanopyHeader(props = {}) {
|
|
|
1050
1313
|
placeholder: searchPlaceholder
|
|
1051
1314
|
}
|
|
1052
1315
|
)),
|
|
1053
|
-
/* @__PURE__ */
|
|
1316
|
+
/* @__PURE__ */ React15.createElement(
|
|
1054
1317
|
"nav",
|
|
1055
1318
|
{
|
|
1056
1319
|
className: "canopy-nav-links canopy-header__desktop-nav",
|
|
1057
1320
|
"aria-label": "Primary navigation"
|
|
1058
1321
|
},
|
|
1059
|
-
navLinks.map((link) => /* @__PURE__ */
|
|
1322
|
+
navLinks.map((link) => /* @__PURE__ */ React15.createElement(
|
|
1323
|
+
"a",
|
|
1324
|
+
{
|
|
1325
|
+
key: link.href,
|
|
1326
|
+
href: link.href,
|
|
1327
|
+
"aria-current": link.isActive ? "page" : void 0
|
|
1328
|
+
},
|
|
1329
|
+
link.label || link.href
|
|
1330
|
+
))
|
|
1060
1331
|
),
|
|
1061
|
-
/* @__PURE__ */
|
|
1332
|
+
/* @__PURE__ */ React15.createElement("div", { className: "canopy-header__actions" }, /* @__PURE__ */ React15.createElement(
|
|
1062
1333
|
"button",
|
|
1063
1334
|
{
|
|
1064
1335
|
type: "button",
|
|
@@ -1068,7 +1339,7 @@ function CanopyHeader(props = {}) {
|
|
|
1068
1339
|
"aria-expanded": "false",
|
|
1069
1340
|
"data-canopy-header-toggle": "search"
|
|
1070
1341
|
},
|
|
1071
|
-
/* @__PURE__ */
|
|
1342
|
+
/* @__PURE__ */ React15.createElement(
|
|
1072
1343
|
"svg",
|
|
1073
1344
|
{
|
|
1074
1345
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -1078,7 +1349,7 @@ function CanopyHeader(props = {}) {
|
|
|
1078
1349
|
strokeWidth: "1.5",
|
|
1079
1350
|
className: "canopy-header__search-icon"
|
|
1080
1351
|
},
|
|
1081
|
-
/* @__PURE__ */
|
|
1352
|
+
/* @__PURE__ */ React15.createElement(
|
|
1082
1353
|
"path",
|
|
1083
1354
|
{
|
|
1084
1355
|
strokeLinecap: "round",
|
|
@@ -1087,7 +1358,7 @@ function CanopyHeader(props = {}) {
|
|
|
1087
1358
|
}
|
|
1088
1359
|
)
|
|
1089
1360
|
)
|
|
1090
|
-
), /* @__PURE__ */
|
|
1361
|
+
), /* @__PURE__ */ React15.createElement(
|
|
1091
1362
|
"button",
|
|
1092
1363
|
{
|
|
1093
1364
|
type: "button",
|
|
@@ -1097,7 +1368,7 @@ function CanopyHeader(props = {}) {
|
|
|
1097
1368
|
"aria-expanded": "false",
|
|
1098
1369
|
"data-canopy-header-toggle": "nav"
|
|
1099
1370
|
},
|
|
1100
|
-
/* @__PURE__ */
|
|
1371
|
+
/* @__PURE__ */ React15.createElement(
|
|
1101
1372
|
"svg",
|
|
1102
1373
|
{
|
|
1103
1374
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -1107,7 +1378,7 @@ function CanopyHeader(props = {}) {
|
|
|
1107
1378
|
stroke: "currentColor",
|
|
1108
1379
|
className: "canopy-header__menu-icon"
|
|
1109
1380
|
},
|
|
1110
|
-
/* @__PURE__ */
|
|
1381
|
+
/* @__PURE__ */ React15.createElement(
|
|
1111
1382
|
"path",
|
|
1112
1383
|
{
|
|
1113
1384
|
strokeLinecap: "round",
|
|
@@ -1117,7 +1388,7 @@ function CanopyHeader(props = {}) {
|
|
|
1117
1388
|
)
|
|
1118
1389
|
)
|
|
1119
1390
|
))
|
|
1120
|
-
), /* @__PURE__ */
|
|
1391
|
+
), /* @__PURE__ */ React15.createElement(
|
|
1121
1392
|
CanopyModal,
|
|
1122
1393
|
{
|
|
1123
1394
|
id: "canopy-modal-nav",
|
|
@@ -1129,24 +1400,90 @@ function CanopyHeader(props = {}) {
|
|
|
1129
1400
|
closeLabel: "Close navigation",
|
|
1130
1401
|
closeDataAttr: "nav"
|
|
1131
1402
|
},
|
|
1132
|
-
/* @__PURE__ */
|
|
1403
|
+
/* @__PURE__ */ React15.createElement(
|
|
1133
1404
|
"nav",
|
|
1134
1405
|
{
|
|
1135
1406
|
className: "canopy-nav-links canopy-modal__nav",
|
|
1136
1407
|
"aria-label": "Primary navigation"
|
|
1137
1408
|
},
|
|
1138
|
-
|
|
1409
|
+
/* @__PURE__ */ React15.createElement("ul", { className: "canopy-modal__nav-list", role: "list" }, navLinks.map((link, index) => {
|
|
1410
|
+
const navData = getLinkNavigationData(
|
|
1411
|
+
link,
|
|
1412
|
+
navigationRoots,
|
|
1413
|
+
sectionNavigation
|
|
1414
|
+
);
|
|
1415
|
+
const navRoot = navData && navData.root ? navData.root : null;
|
|
1416
|
+
const hasChildren = !!(navRoot && Array.isArray(navRoot.children) && navRoot.children.length);
|
|
1417
|
+
const nestedId = hasChildren ? `canopy-modal-section-${index}` : null;
|
|
1418
|
+
const toggleLabel = link.label ? `Toggle ${link.label} menu` : "Toggle section menu";
|
|
1419
|
+
const defaultExpanded = hasChildren && !!navRoot.isExpanded;
|
|
1420
|
+
return /* @__PURE__ */ React15.createElement(
|
|
1421
|
+
"li",
|
|
1422
|
+
{
|
|
1423
|
+
className: "canopy-modal__nav-item",
|
|
1424
|
+
key: link.href,
|
|
1425
|
+
"data-canopy-nav-item": hasChildren ? "true" : void 0,
|
|
1426
|
+
"data-expanded": defaultExpanded ? "true" : "false",
|
|
1427
|
+
"data-default-expanded": defaultExpanded ? "true" : void 0
|
|
1428
|
+
},
|
|
1429
|
+
/* @__PURE__ */ React15.createElement("div", { className: "canopy-modal__nav-row" }, /* @__PURE__ */ React15.createElement("a", { href: link.href }, link.label || link.href), hasChildren ? /* @__PURE__ */ React15.createElement(
|
|
1430
|
+
"button",
|
|
1431
|
+
{
|
|
1432
|
+
type: "button",
|
|
1433
|
+
className: "canopy-modal__nav-toggle",
|
|
1434
|
+
"aria-expanded": defaultExpanded ? "true" : "false",
|
|
1435
|
+
"aria-controls": nestedId || void 0,
|
|
1436
|
+
"aria-label": toggleLabel,
|
|
1437
|
+
"data-canopy-nav-item-toggle": nestedId || void 0
|
|
1438
|
+
},
|
|
1439
|
+
/* @__PURE__ */ React15.createElement(
|
|
1440
|
+
"svg",
|
|
1441
|
+
{
|
|
1442
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1443
|
+
viewBox: "0 0 24 24",
|
|
1444
|
+
fill: "none",
|
|
1445
|
+
stroke: "currentColor",
|
|
1446
|
+
strokeWidth: "1.5",
|
|
1447
|
+
className: "canopy-modal__nav-toggle-icon"
|
|
1448
|
+
},
|
|
1449
|
+
/* @__PURE__ */ React15.createElement(
|
|
1450
|
+
"path",
|
|
1451
|
+
{
|
|
1452
|
+
strokeLinecap: "round",
|
|
1453
|
+
strokeLinejoin: "round",
|
|
1454
|
+
d: "M5 9l7 7 7-7"
|
|
1455
|
+
}
|
|
1456
|
+
)
|
|
1457
|
+
),
|
|
1458
|
+
/* @__PURE__ */ React15.createElement("span", { className: "sr-only" }, toggleLabel)
|
|
1459
|
+
) : null),
|
|
1460
|
+
hasChildren ? /* @__PURE__ */ React15.createElement(
|
|
1461
|
+
NavigationTree,
|
|
1462
|
+
{
|
|
1463
|
+
root: navRoot,
|
|
1464
|
+
parentKey: navData && navData.rootSegment ? navData.rootSegment : `root-${index}`,
|
|
1465
|
+
component: "div",
|
|
1466
|
+
className: "canopy-modal__section-nav canopy-modal__section-nav--nested",
|
|
1467
|
+
"aria-label": navData && navData.title ? `${navData.title} section navigation` : defaultSectionAriaLabel,
|
|
1468
|
+
"aria-hidden": defaultExpanded ? "false" : "true",
|
|
1469
|
+
hidden: !defaultExpanded,
|
|
1470
|
+
id: nestedId || void 0
|
|
1471
|
+
}
|
|
1472
|
+
) : null
|
|
1473
|
+
);
|
|
1474
|
+
}))
|
|
1139
1475
|
),
|
|
1140
|
-
hasSectionNav ? /* @__PURE__ */
|
|
1141
|
-
|
|
1476
|
+
hasSectionNav && !hasIntegratedSectionNav ? /* @__PURE__ */ React15.createElement(
|
|
1477
|
+
NavigationTree,
|
|
1142
1478
|
{
|
|
1479
|
+
root: sectionNavigation.root,
|
|
1480
|
+
component: "nav",
|
|
1143
1481
|
className: "canopy-modal__section-nav",
|
|
1144
|
-
"aria-label":
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
/* @__PURE__ */ React14.createElement(SectionNavList, { root: sectionNavigation.root })
|
|
1482
|
+
"aria-label": defaultSectionAriaLabel,
|
|
1483
|
+
parentKey: "fallback-nav"
|
|
1484
|
+
}
|
|
1148
1485
|
) : null
|
|
1149
|
-
), /* @__PURE__ */
|
|
1486
|
+
), /* @__PURE__ */ React15.createElement(
|
|
1150
1487
|
CanopyModal,
|
|
1151
1488
|
{
|
|
1152
1489
|
id: "canopy-modal-search",
|
|
@@ -1159,7 +1496,7 @@ function CanopyHeader(props = {}) {
|
|
|
1159
1496
|
closeDataAttr: "search",
|
|
1160
1497
|
bodyClassName: "canopy-modal__body--search"
|
|
1161
1498
|
},
|
|
1162
|
-
/* @__PURE__ */
|
|
1499
|
+
/* @__PURE__ */ React15.createElement(
|
|
1163
1500
|
SearchPanel,
|
|
1164
1501
|
{
|
|
1165
1502
|
label: searchLabel,
|
|
@@ -1167,18 +1504,18 @@ function CanopyHeader(props = {}) {
|
|
|
1167
1504
|
placeholder: searchPlaceholder
|
|
1168
1505
|
}
|
|
1169
1506
|
)
|
|
1170
|
-
), /* @__PURE__ */
|
|
1507
|
+
), /* @__PURE__ */ React15.createElement(HeaderScript, null));
|
|
1171
1508
|
}
|
|
1172
1509
|
|
|
1173
1510
|
// ui/src/layout/CanopyFooter.jsx
|
|
1174
|
-
import
|
|
1511
|
+
import React16 from "react";
|
|
1175
1512
|
function CanopyFooter({ className = "", children }) {
|
|
1176
1513
|
const footerClassName = ["canopy-footer", className].filter(Boolean).join(" ");
|
|
1177
|
-
return /* @__PURE__ */
|
|
1514
|
+
return /* @__PURE__ */ React16.createElement("footer", { className: footerClassName }, /* @__PURE__ */ React16.createElement("div", { className: "canopy-footer__inner" }, children));
|
|
1178
1515
|
}
|
|
1179
1516
|
|
|
1180
1517
|
// ui/src/layout/TeaserCard.jsx
|
|
1181
|
-
import
|
|
1518
|
+
import React17 from "react";
|
|
1182
1519
|
function TeaserCard({
|
|
1183
1520
|
href = "",
|
|
1184
1521
|
title = "",
|
|
@@ -1199,7 +1536,7 @@ function TeaserCard({
|
|
|
1199
1536
|
].filter(Boolean).join(" ");
|
|
1200
1537
|
const showThumb = type === "work" && thumbnail;
|
|
1201
1538
|
const metaLine = (Array.isArray(metadata) && metadata.length ? metadata.filter(Boolean) : summary ? [summary] : []).filter(Boolean).slice(0, 2).join(" \u2022 ");
|
|
1202
|
-
return /* @__PURE__ */
|
|
1539
|
+
return /* @__PURE__ */ React17.createElement(
|
|
1203
1540
|
Tag,
|
|
1204
1541
|
{
|
|
1205
1542
|
className: classes,
|
|
@@ -1207,21 +1544,22 @@ function TeaserCard({
|
|
|
1207
1544
|
"data-canopy-item": href ? "" : void 0,
|
|
1208
1545
|
...rest
|
|
1209
1546
|
},
|
|
1210
|
-
showThumb ? /* @__PURE__ */
|
|
1547
|
+
showThumb ? /* @__PURE__ */ React17.createElement("div", { className: "canopy-search-teaser__thumb" }, /* @__PURE__ */ React17.createElement(
|
|
1211
1548
|
"img",
|
|
1212
1549
|
{
|
|
1213
1550
|
src: thumbnail,
|
|
1214
1551
|
alt: "",
|
|
1552
|
+
"aria-hidden": "true",
|
|
1215
1553
|
loading: "lazy",
|
|
1216
1554
|
className: "canopy-search-teaser__thumb-img"
|
|
1217
1555
|
}
|
|
1218
1556
|
)) : null,
|
|
1219
|
-
/* @__PURE__ */
|
|
1557
|
+
/* @__PURE__ */ React17.createElement("div", { className: "canopy-search-teaser__text" }, /* @__PURE__ */ React17.createElement("span", { className: "canopy-search-teaser__title" }, title || href || "Untitled"), metaLine ? /* @__PURE__ */ React17.createElement("span", { className: "canopy-search-teaser__meta" }, metaLine) : null)
|
|
1220
1558
|
);
|
|
1221
1559
|
}
|
|
1222
1560
|
|
|
1223
1561
|
// ui/src/layout/GoogleAnalytics.jsx
|
|
1224
|
-
import
|
|
1562
|
+
import React18 from "react";
|
|
1225
1563
|
var GA_HOST = "https://www.googletagmanager.com/gtag/js";
|
|
1226
1564
|
function GoogleAnalytics({ id }) {
|
|
1227
1565
|
if (!id) return null;
|
|
@@ -1231,11 +1569,11 @@ function GoogleAnalytics({ id }) {
|
|
|
1231
1569
|
gtag('js', new Date());
|
|
1232
1570
|
gtag('config', '${id}');
|
|
1233
1571
|
`;
|
|
1234
|
-
return /* @__PURE__ */
|
|
1572
|
+
return /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement("script", { async: true, src: `${GA_HOST}?id=${encodeURIComponent(id)}` }), /* @__PURE__ */ React18.createElement("script", { dangerouslySetInnerHTML: { __html: inlineConfig } }));
|
|
1235
1573
|
}
|
|
1236
1574
|
|
|
1237
1575
|
// ui/src/iiif/Viewer.jsx
|
|
1238
|
-
import
|
|
1576
|
+
import React19, { useEffect as useEffect2, useState as useState2 } from "react";
|
|
1239
1577
|
var DEFAULT_VIEWER_OPTIONS = {
|
|
1240
1578
|
showDownload: false,
|
|
1241
1579
|
showIIIFBadge: false,
|
|
@@ -1291,7 +1629,7 @@ var Viewer = (props) => {
|
|
|
1291
1629
|
} catch (_) {
|
|
1292
1630
|
json = "{}";
|
|
1293
1631
|
}
|
|
1294
|
-
return /* @__PURE__ */
|
|
1632
|
+
return /* @__PURE__ */ React19.createElement("div", { "data-canopy-viewer": "1", className: "not-prose" }, /* @__PURE__ */ React19.createElement(
|
|
1295
1633
|
"script",
|
|
1296
1634
|
{
|
|
1297
1635
|
type: "application/json",
|
|
@@ -1299,11 +1637,11 @@ var Viewer = (props) => {
|
|
|
1299
1637
|
}
|
|
1300
1638
|
));
|
|
1301
1639
|
}
|
|
1302
|
-
return /* @__PURE__ */
|
|
1640
|
+
return /* @__PURE__ */ React19.createElement(CloverViewer, { ...props, options: mergedOptions });
|
|
1303
1641
|
};
|
|
1304
1642
|
|
|
1305
1643
|
// ui/src/iiif/Slider.jsx
|
|
1306
|
-
import
|
|
1644
|
+
import React20, { useEffect as useEffect3, useState as useState3 } from "react";
|
|
1307
1645
|
|
|
1308
1646
|
// ui/src/iiif/sliderOptions.js
|
|
1309
1647
|
var UNIT_TOKEN = "__canopySliderUnit";
|
|
@@ -1450,7 +1788,7 @@ var Slider = (props = {}) => {
|
|
|
1450
1788
|
} catch (_) {
|
|
1451
1789
|
json = "{}";
|
|
1452
1790
|
}
|
|
1453
|
-
return /* @__PURE__ */
|
|
1791
|
+
return /* @__PURE__ */ React20.createElement("div", { className: sliderClassName, "data-canopy-slider": "1" }, /* @__PURE__ */ React20.createElement(
|
|
1454
1792
|
"script",
|
|
1455
1793
|
{
|
|
1456
1794
|
type: "application/json",
|
|
@@ -1458,11 +1796,11 @@ var Slider = (props = {}) => {
|
|
|
1458
1796
|
}
|
|
1459
1797
|
));
|
|
1460
1798
|
}
|
|
1461
|
-
return /* @__PURE__ */
|
|
1799
|
+
return /* @__PURE__ */ React20.createElement(CloverSlider, { ...resolvedProps });
|
|
1462
1800
|
};
|
|
1463
1801
|
|
|
1464
1802
|
// ui/src/iiif/Scroll.jsx
|
|
1465
|
-
import
|
|
1803
|
+
import React21, { useEffect as useEffect4, useState as useState4 } from "react";
|
|
1466
1804
|
var Scroll = (props) => {
|
|
1467
1805
|
const [CloverScroll, setCloverScroll] = useState4(null);
|
|
1468
1806
|
useEffect4(() => {
|
|
@@ -1487,7 +1825,7 @@ var Scroll = (props) => {
|
|
|
1487
1825
|
} catch (_) {
|
|
1488
1826
|
json = "{}";
|
|
1489
1827
|
}
|
|
1490
|
-
return /* @__PURE__ */
|
|
1828
|
+
return /* @__PURE__ */ React21.createElement("div", { "data-canopy-scroll": "1", className: "not-prose" }, /* @__PURE__ */ React21.createElement(
|
|
1491
1829
|
"script",
|
|
1492
1830
|
{
|
|
1493
1831
|
type: "application/json",
|
|
@@ -1495,11 +1833,11 @@ var Scroll = (props) => {
|
|
|
1495
1833
|
}
|
|
1496
1834
|
));
|
|
1497
1835
|
}
|
|
1498
|
-
return /* @__PURE__ */
|
|
1836
|
+
return /* @__PURE__ */ React21.createElement(CloverScroll, { ...props });
|
|
1499
1837
|
};
|
|
1500
1838
|
|
|
1501
1839
|
// ui/src/iiif/Image.jsx
|
|
1502
|
-
import
|
|
1840
|
+
import React22, { useEffect as useEffect5, useState as useState5 } from "react";
|
|
1503
1841
|
var Image = (props = {}) => {
|
|
1504
1842
|
const [CloverImage, setCloverImage] = useState5(null);
|
|
1505
1843
|
const baseClass = "canopy-iiif-image";
|
|
@@ -1532,7 +1870,7 @@ var Image = (props = {}) => {
|
|
|
1532
1870
|
} catch (_) {
|
|
1533
1871
|
json = "{}";
|
|
1534
1872
|
}
|
|
1535
|
-
return /* @__PURE__ */
|
|
1873
|
+
return /* @__PURE__ */ React22.createElement("figure", { className: rootClassName }, /* @__PURE__ */ React22.createElement(
|
|
1536
1874
|
"div",
|
|
1537
1875
|
{
|
|
1538
1876
|
className: `${baseClass}__placeholder`,
|
|
@@ -1542,26 +1880,26 @@ var Image = (props = {}) => {
|
|
|
1542
1880
|
"--canopy-iiif-image-bg": backgroundColor
|
|
1543
1881
|
}
|
|
1544
1882
|
},
|
|
1545
|
-
/* @__PURE__ */
|
|
1883
|
+
/* @__PURE__ */ React22.createElement(
|
|
1546
1884
|
"script",
|
|
1547
1885
|
{
|
|
1548
1886
|
type: "application/json",
|
|
1549
1887
|
dangerouslySetInnerHTML: { __html: json }
|
|
1550
1888
|
}
|
|
1551
1889
|
)
|
|
1552
|
-
), caption && /* @__PURE__ */
|
|
1890
|
+
), caption && /* @__PURE__ */ React22.createElement("figcaption", { className: `${baseClass}__caption` }, caption));
|
|
1553
1891
|
}
|
|
1554
|
-
return /* @__PURE__ */
|
|
1892
|
+
return /* @__PURE__ */ React22.createElement(CloverImage, { ...props, className: rootClassName });
|
|
1555
1893
|
};
|
|
1556
1894
|
|
|
1557
1895
|
// ui/src/iiif/Properties/Id.jsx
|
|
1558
|
-
import
|
|
1896
|
+
import React23 from "react";
|
|
1559
1897
|
function Id({ title = "IIIF Manifest", id, ...props }) {
|
|
1560
|
-
return /* @__PURE__ */
|
|
1898
|
+
return /* @__PURE__ */ React23.createElement("dl", null, /* @__PURE__ */ React23.createElement("dt", null, title), /* @__PURE__ */ React23.createElement("dd", null, /* @__PURE__ */ React23.createElement("a", { href: id }, id)));
|
|
1561
1899
|
}
|
|
1562
1900
|
|
|
1563
1901
|
// ui/src/iiif/MdxRelatedItems.jsx
|
|
1564
|
-
import
|
|
1902
|
+
import React24 from "react";
|
|
1565
1903
|
function MdxRelatedItems(props) {
|
|
1566
1904
|
let json = "{}";
|
|
1567
1905
|
try {
|
|
@@ -1569,7 +1907,7 @@ function MdxRelatedItems(props) {
|
|
|
1569
1907
|
} catch (_) {
|
|
1570
1908
|
json = "{}";
|
|
1571
1909
|
}
|
|
1572
|
-
return /* @__PURE__ */
|
|
1910
|
+
return /* @__PURE__ */ React24.createElement("div", { "data-canopy-related-items": "1" }, /* @__PURE__ */ React24.createElement(
|
|
1573
1911
|
"script",
|
|
1574
1912
|
{
|
|
1575
1913
|
type: "application/json",
|
|
@@ -1579,7 +1917,7 @@ function MdxRelatedItems(props) {
|
|
|
1579
1917
|
}
|
|
1580
1918
|
|
|
1581
1919
|
// ui/src/search/MdxSearchResults.jsx
|
|
1582
|
-
import
|
|
1920
|
+
import React25 from "react";
|
|
1583
1921
|
function MdxSearchResults(props) {
|
|
1584
1922
|
let json = "{}";
|
|
1585
1923
|
try {
|
|
@@ -1587,11 +1925,11 @@ function MdxSearchResults(props) {
|
|
|
1587
1925
|
} catch (_) {
|
|
1588
1926
|
json = "{}";
|
|
1589
1927
|
}
|
|
1590
|
-
return /* @__PURE__ */
|
|
1928
|
+
return /* @__PURE__ */ React25.createElement("div", { "data-canopy-search-results": "1" }, /* @__PURE__ */ React25.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
1591
1929
|
}
|
|
1592
1930
|
|
|
1593
1931
|
// ui/src/search/SearchSummary.jsx
|
|
1594
|
-
import
|
|
1932
|
+
import React26 from "react";
|
|
1595
1933
|
function SearchSummary(props) {
|
|
1596
1934
|
let json = "{}";
|
|
1597
1935
|
try {
|
|
@@ -1599,11 +1937,11 @@ function SearchSummary(props) {
|
|
|
1599
1937
|
} catch (_) {
|
|
1600
1938
|
json = "{}";
|
|
1601
1939
|
}
|
|
1602
|
-
return /* @__PURE__ */
|
|
1940
|
+
return /* @__PURE__ */ React26.createElement("div", { "data-canopy-search-summary": "1" }, /* @__PURE__ */ React26.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
1603
1941
|
}
|
|
1604
1942
|
|
|
1605
1943
|
// ui/src/search/MdxSearchTabs.jsx
|
|
1606
|
-
import
|
|
1944
|
+
import React27 from "react";
|
|
1607
1945
|
function MdxSearchTabs(props) {
|
|
1608
1946
|
let json = "{}";
|
|
1609
1947
|
try {
|
|
@@ -1611,11 +1949,11 @@ function MdxSearchTabs(props) {
|
|
|
1611
1949
|
} catch (_) {
|
|
1612
1950
|
json = "{}";
|
|
1613
1951
|
}
|
|
1614
|
-
return /* @__PURE__ */
|
|
1952
|
+
return /* @__PURE__ */ React27.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React27.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
1615
1953
|
}
|
|
1616
1954
|
|
|
1617
1955
|
// ui/src/search/MdxSearch.jsx
|
|
1618
|
-
import
|
|
1956
|
+
import React28 from "react";
|
|
1619
1957
|
function MdxSearch(props = {}) {
|
|
1620
1958
|
const {
|
|
1621
1959
|
layout,
|
|
@@ -1633,15 +1971,15 @@ function MdxSearch(props = {}) {
|
|
|
1633
1971
|
resultsPayload.layout = layout;
|
|
1634
1972
|
}
|
|
1635
1973
|
const classes = ["canopy-search", className].filter(Boolean).join(" ");
|
|
1636
|
-
return /* @__PURE__ */
|
|
1974
|
+
return /* @__PURE__ */ React28.createElement("section", { className: classes, "data-canopy-search": "1" }, showTabs ? /* @__PURE__ */ React28.createElement(MdxSearchTabs, { ...tabsProps }) : null, showSummary ? /* @__PURE__ */ React28.createElement(SearchSummary, { ...summaryProps }) : null, showResults ? /* @__PURE__ */ React28.createElement(MdxSearchResults, { ...resultsPayload }) : null, children || null);
|
|
1637
1975
|
}
|
|
1638
1976
|
|
|
1639
1977
|
// ui/src/search/SearchResults.jsx
|
|
1640
|
-
import
|
|
1978
|
+
import React29 from "react";
|
|
1641
1979
|
function DefaultArticleTemplate({ record, query }) {
|
|
1642
1980
|
if (!record) return null;
|
|
1643
1981
|
const metadata = Array.isArray(record.metadata) ? record.metadata : [];
|
|
1644
|
-
return /* @__PURE__ */
|
|
1982
|
+
return /* @__PURE__ */ React29.createElement(
|
|
1645
1983
|
ArticleCard,
|
|
1646
1984
|
{
|
|
1647
1985
|
href: record.href,
|
|
@@ -1659,7 +1997,7 @@ function DefaultFigureTemplate({ record, thumbnailAspectRatio }) {
|
|
|
1659
1997
|
if (!record) return null;
|
|
1660
1998
|
const hasDims = Number.isFinite(Number(record.thumbnailWidth)) && Number(record.thumbnailWidth) > 0 && Number.isFinite(Number(record.thumbnailHeight)) && Number(record.thumbnailHeight) > 0;
|
|
1661
1999
|
const aspect = Number.isFinite(Number(thumbnailAspectRatio)) && Number(thumbnailAspectRatio) > 0 ? Number(thumbnailAspectRatio) : hasDims ? Number(record.thumbnailWidth) / Number(record.thumbnailHeight) : void 0;
|
|
1662
|
-
return /* @__PURE__ */
|
|
2000
|
+
return /* @__PURE__ */ React29.createElement(
|
|
1663
2001
|
Card,
|
|
1664
2002
|
{
|
|
1665
2003
|
href: record.href,
|
|
@@ -1680,7 +2018,7 @@ function SearchResults({
|
|
|
1680
2018
|
variant = "auto"
|
|
1681
2019
|
}) {
|
|
1682
2020
|
if (!results.length) {
|
|
1683
|
-
return /* @__PURE__ */
|
|
2021
|
+
return /* @__PURE__ */ React29.createElement("div", { className: "text-slate-600" }, /* @__PURE__ */ React29.createElement("em", null, "No results"));
|
|
1684
2022
|
}
|
|
1685
2023
|
const normalizedType = String(type || "all").toLowerCase();
|
|
1686
2024
|
const normalizedVariant = variant === "figure" || variant === "article" ? variant : "auto";
|
|
@@ -1688,9 +2026,9 @@ function SearchResults({
|
|
|
1688
2026
|
const FigureTemplate = templates && templates.figure ? templates.figure : DefaultFigureTemplate;
|
|
1689
2027
|
const ArticleTemplate = templates && templates.article ? templates.article : DefaultArticleTemplate;
|
|
1690
2028
|
if (isAnnotationView) {
|
|
1691
|
-
return /* @__PURE__ */
|
|
2029
|
+
return /* @__PURE__ */ React29.createElement("div", { id: "search-results", className: "space-y-4", role: "region", "aria-label": "Search results" }, results.map((r, i) => {
|
|
1692
2030
|
if (!r) return null;
|
|
1693
|
-
return /* @__PURE__ */
|
|
2031
|
+
return /* @__PURE__ */ React29.createElement(
|
|
1694
2032
|
ArticleTemplate,
|
|
1695
2033
|
{
|
|
1696
2034
|
key: r.id || i,
|
|
@@ -1708,20 +2046,20 @@ function SearchResults({
|
|
|
1708
2046
|
return !isWorkRecord(record) || normalizedType !== "work";
|
|
1709
2047
|
};
|
|
1710
2048
|
if (layout === "list") {
|
|
1711
|
-
return /* @__PURE__ */
|
|
2049
|
+
return /* @__PURE__ */ React29.createElement("div", { id: "search-results", className: "space-y-6", role: "region", "aria-label": "Search results" }, results.map((r, i) => {
|
|
1712
2050
|
if (shouldRenderAsArticle(r)) {
|
|
1713
|
-
return /* @__PURE__ */
|
|
2051
|
+
return /* @__PURE__ */ React29.createElement("div", { key: i, className: `search-result ${r && r.type}` }, /* @__PURE__ */ React29.createElement(ArticleTemplate, { record: r, query, layout }));
|
|
1714
2052
|
}
|
|
1715
2053
|
const hasDims = Number.isFinite(Number(r.thumbnailWidth)) && Number(r.thumbnailWidth) > 0 && Number.isFinite(Number(r.thumbnailHeight)) && Number(r.thumbnailHeight) > 0;
|
|
1716
2054
|
const aspect = hasDims ? Number(r.thumbnailWidth) / Number(r.thumbnailHeight) : void 0;
|
|
1717
|
-
return /* @__PURE__ */
|
|
2055
|
+
return /* @__PURE__ */ React29.createElement(
|
|
1718
2056
|
"div",
|
|
1719
2057
|
{
|
|
1720
2058
|
key: i,
|
|
1721
2059
|
className: `search-result ${r.type}`,
|
|
1722
2060
|
"data-thumbnail-aspect-ratio": aspect
|
|
1723
2061
|
},
|
|
1724
|
-
/* @__PURE__ */
|
|
2062
|
+
/* @__PURE__ */ React29.createElement(
|
|
1725
2063
|
FigureTemplate,
|
|
1726
2064
|
{
|
|
1727
2065
|
record: r,
|
|
@@ -1733,20 +2071,20 @@ function SearchResults({
|
|
|
1733
2071
|
);
|
|
1734
2072
|
}));
|
|
1735
2073
|
}
|
|
1736
|
-
return /* @__PURE__ */
|
|
2074
|
+
return /* @__PURE__ */ React29.createElement("div", { id: "search-results", role: "region", "aria-label": "Search results" }, /* @__PURE__ */ React29.createElement(Grid, null, results.map((r, i) => {
|
|
1737
2075
|
if (shouldRenderAsArticle(r)) {
|
|
1738
|
-
return /* @__PURE__ */
|
|
2076
|
+
return /* @__PURE__ */ React29.createElement(GridItem, { key: i, className: `search-result ${r && r.type}` }, /* @__PURE__ */ React29.createElement(ArticleTemplate, { record: r, query, layout }));
|
|
1739
2077
|
}
|
|
1740
2078
|
const hasDims = Number.isFinite(Number(r.thumbnailWidth)) && Number(r.thumbnailWidth) > 0 && Number.isFinite(Number(r.thumbnailHeight)) && Number(r.thumbnailHeight) > 0;
|
|
1741
2079
|
const aspect = hasDims ? Number(r.thumbnailWidth) / Number(r.thumbnailHeight) : void 0;
|
|
1742
|
-
return /* @__PURE__ */
|
|
2080
|
+
return /* @__PURE__ */ React29.createElement(
|
|
1743
2081
|
GridItem,
|
|
1744
2082
|
{
|
|
1745
2083
|
key: i,
|
|
1746
2084
|
className: `search-result ${r.type}`,
|
|
1747
2085
|
"data-thumbnail-aspect-ratio": aspect
|
|
1748
2086
|
},
|
|
1749
|
-
/* @__PURE__ */
|
|
2087
|
+
/* @__PURE__ */ React29.createElement(
|
|
1750
2088
|
FigureTemplate,
|
|
1751
2089
|
{
|
|
1752
2090
|
record: r,
|
|
@@ -1760,7 +2098,7 @@ function SearchResults({
|
|
|
1760
2098
|
}
|
|
1761
2099
|
|
|
1762
2100
|
// ui/src/search/SearchTabs.jsx
|
|
1763
|
-
import
|
|
2101
|
+
import React30, { useRef as useRef2, useState as useState6, useEffect as useEffect6 } from "react";
|
|
1764
2102
|
function SearchTabs({
|
|
1765
2103
|
type = "all",
|
|
1766
2104
|
onTypeChange,
|
|
@@ -1814,7 +2152,7 @@ function SearchTabs({
|
|
|
1814
2152
|
width: `${itemBoundingBox.width}px`
|
|
1815
2153
|
};
|
|
1816
2154
|
}
|
|
1817
|
-
return /* @__PURE__ */
|
|
2155
|
+
return /* @__PURE__ */ React30.createElement("div", { className: "canopy-search-tabs-wrapper" }, /* @__PURE__ */ React30.createElement(
|
|
1818
2156
|
"div",
|
|
1819
2157
|
{
|
|
1820
2158
|
role: "tablist",
|
|
@@ -1823,7 +2161,7 @@ function SearchTabs({
|
|
|
1823
2161
|
ref: wrapperRef,
|
|
1824
2162
|
onMouseLeave: resetHighlight
|
|
1825
2163
|
},
|
|
1826
|
-
/* @__PURE__ */
|
|
2164
|
+
/* @__PURE__ */ React30.createElement(
|
|
1827
2165
|
"div",
|
|
1828
2166
|
{
|
|
1829
2167
|
ref: highlightRef,
|
|
@@ -1835,7 +2173,7 @@ function SearchTabs({
|
|
|
1835
2173
|
const active = String(type).toLowerCase() === String(t).toLowerCase();
|
|
1836
2174
|
const cRaw = counts && Object.prototype.hasOwnProperty.call(counts, t) ? counts[t] : void 0;
|
|
1837
2175
|
const c = Number.isFinite(Number(cRaw)) ? Number(cRaw) : 0;
|
|
1838
|
-
return /* @__PURE__ */
|
|
2176
|
+
return /* @__PURE__ */ React30.createElement(
|
|
1839
2177
|
"button",
|
|
1840
2178
|
{
|
|
1841
2179
|
key: t,
|
|
@@ -1853,7 +2191,7 @@ function SearchTabs({
|
|
|
1853
2191
|
")"
|
|
1854
2192
|
);
|
|
1855
2193
|
})
|
|
1856
|
-
), hasFilters ? /* @__PURE__ */
|
|
2194
|
+
), hasFilters ? /* @__PURE__ */ React30.createElement(
|
|
1857
2195
|
"button",
|
|
1858
2196
|
{
|
|
1859
2197
|
type: "button",
|
|
@@ -1861,12 +2199,12 @@ function SearchTabs({
|
|
|
1861
2199
|
"aria-expanded": filtersOpen ? "true" : "false",
|
|
1862
2200
|
className: "inline-flex items-center gap-2 rounded-md border border-slate-200 bg-white px-3 py-1.5 text-sm font-medium text-slate-700 shadow-sm transition hover:border-brand-200 hover:bg-brand-50 hover:text-brand-700"
|
|
1863
2201
|
},
|
|
1864
|
-
/* @__PURE__ */
|
|
2202
|
+
/* @__PURE__ */ React30.createElement("span", null, filtersLabel, filterBadge)
|
|
1865
2203
|
) : null);
|
|
1866
2204
|
}
|
|
1867
2205
|
|
|
1868
2206
|
// ui/src/search/SearchFiltersDialog.jsx
|
|
1869
|
-
import
|
|
2207
|
+
import React31 from "react";
|
|
1870
2208
|
function toArray(input) {
|
|
1871
2209
|
if (!input) return [];
|
|
1872
2210
|
if (Array.isArray(input)) return input;
|
|
@@ -1905,20 +2243,20 @@ function FacetSection({ facet, selected, onToggle }) {
|
|
|
1905
2243
|
const selectedValues = selected.get(String(slug)) || /* @__PURE__ */ new Set();
|
|
1906
2244
|
const checkboxId = (valueSlug) => `filter-${slug}-${valueSlug}`;
|
|
1907
2245
|
const hasSelection = selectedValues.size > 0;
|
|
1908
|
-
const [quickQuery, setQuickQuery] =
|
|
2246
|
+
const [quickQuery, setQuickQuery] = React31.useState("");
|
|
1909
2247
|
const hasQuery = quickQuery.trim().length > 0;
|
|
1910
|
-
const filteredValues =
|
|
2248
|
+
const filteredValues = React31.useMemo(
|
|
1911
2249
|
() => facetMatches(values, quickQuery),
|
|
1912
2250
|
[values, quickQuery]
|
|
1913
2251
|
);
|
|
1914
|
-
return /* @__PURE__ */
|
|
2252
|
+
return /* @__PURE__ */ React31.createElement(
|
|
1915
2253
|
"details",
|
|
1916
2254
|
{
|
|
1917
2255
|
className: "canopy-search-filters__facet",
|
|
1918
2256
|
open: hasSelection
|
|
1919
2257
|
},
|
|
1920
|
-
/* @__PURE__ */
|
|
1921
|
-
/* @__PURE__ */
|
|
2258
|
+
/* @__PURE__ */ React31.createElement("summary", { className: "canopy-search-filters__facet-summary" }, /* @__PURE__ */ React31.createElement("span", null, label), /* @__PURE__ */ React31.createElement("span", { className: "canopy-search-filters__facet-count" }, values.length)),
|
|
2259
|
+
/* @__PURE__ */ React31.createElement("div", { className: "canopy-search-filters__facet-content" }, /* @__PURE__ */ React31.createElement("div", { className: "canopy-search-filters__quick" }, /* @__PURE__ */ React31.createElement(
|
|
1922
2260
|
"input",
|
|
1923
2261
|
{
|
|
1924
2262
|
type: "search",
|
|
@@ -1928,19 +2266,20 @@ function FacetSection({ facet, selected, onToggle }) {
|
|
|
1928
2266
|
className: "canopy-search-filters__quick-input",
|
|
1929
2267
|
"aria-label": `Filter ${label} values`
|
|
1930
2268
|
}
|
|
1931
|
-
), quickQuery ? /* @__PURE__ */
|
|
2269
|
+
), quickQuery ? /* @__PURE__ */ React31.createElement(
|
|
1932
2270
|
"button",
|
|
1933
2271
|
{
|
|
1934
2272
|
type: "button",
|
|
1935
2273
|
onClick: () => setQuickQuery(""),
|
|
1936
|
-
className: "canopy-search-filters__quick-clear"
|
|
2274
|
+
className: "canopy-search-filters__quick-clear",
|
|
2275
|
+
"aria-label": `Clear ${label} filter search`
|
|
1937
2276
|
},
|
|
1938
2277
|
"Clear"
|
|
1939
|
-
) : null), hasQuery && !filteredValues.length ? /* @__PURE__ */
|
|
2278
|
+
) : null), hasQuery && !filteredValues.length ? /* @__PURE__ */ React31.createElement("p", { className: "canopy-search-filters__facet-notice" }, "No matches found.") : null, /* @__PURE__ */ React31.createElement("ul", { className: "canopy-search-filters__facet-list" }, filteredValues.map((entry) => {
|
|
1940
2279
|
const valueSlug = String(entry.slug || entry.value || "");
|
|
1941
2280
|
const isChecked = selectedValues.has(valueSlug);
|
|
1942
2281
|
const inputId = checkboxId(valueSlug);
|
|
1943
|
-
return /* @__PURE__ */
|
|
2282
|
+
return /* @__PURE__ */ React31.createElement("li", { key: valueSlug, className: "canopy-search-filters__facet-item" }, /* @__PURE__ */ React31.createElement(
|
|
1944
2283
|
"input",
|
|
1945
2284
|
{
|
|
1946
2285
|
id: inputId,
|
|
@@ -1952,15 +2291,15 @@ function FacetSection({ facet, selected, onToggle }) {
|
|
|
1952
2291
|
if (onToggle) onToggle(slug, valueSlug, nextChecked);
|
|
1953
2292
|
}
|
|
1954
2293
|
}
|
|
1955
|
-
), /* @__PURE__ */
|
|
2294
|
+
), /* @__PURE__ */ React31.createElement(
|
|
1956
2295
|
"label",
|
|
1957
2296
|
{
|
|
1958
2297
|
htmlFor: inputId,
|
|
1959
2298
|
className: "canopy-search-filters__facet-label"
|
|
1960
2299
|
},
|
|
1961
|
-
/* @__PURE__ */
|
|
2300
|
+
/* @__PURE__ */ React31.createElement("span", null, entry.value, " ", Number.isFinite(entry.doc_count) ? /* @__PURE__ */ React31.createElement("span", { className: "canopy-search-filters__facet-count" }, "(", entry.doc_count, ")") : null)
|
|
1962
2301
|
));
|
|
1963
|
-
}), !filteredValues.length && !hasQuery ? /* @__PURE__ */
|
|
2302
|
+
}), !filteredValues.length && !hasQuery ? /* @__PURE__ */ React31.createElement("li", { className: "canopy-search-filters__facet-empty" }, "No values available.") : null))
|
|
1964
2303
|
);
|
|
1965
2304
|
}
|
|
1966
2305
|
function SearchFiltersDialog(props = {}) {
|
|
@@ -1982,7 +2321,7 @@ function SearchFiltersDialog(props = {}) {
|
|
|
1982
2321
|
(total, set) => total + set.size,
|
|
1983
2322
|
0
|
|
1984
2323
|
);
|
|
1985
|
-
|
|
2324
|
+
React31.useEffect(() => {
|
|
1986
2325
|
if (!open) return void 0;
|
|
1987
2326
|
if (typeof document === "undefined") return void 0;
|
|
1988
2327
|
const body = document.body;
|
|
@@ -1999,7 +2338,7 @@ function SearchFiltersDialog(props = {}) {
|
|
|
1999
2338
|
if (!open) return null;
|
|
2000
2339
|
const brandId = "canopy-modal-filters-label";
|
|
2001
2340
|
const subtitleText = subtitle != null ? subtitle : title;
|
|
2002
|
-
return /* @__PURE__ */
|
|
2341
|
+
return /* @__PURE__ */ React31.createElement(
|
|
2003
2342
|
CanopyModal,
|
|
2004
2343
|
{
|
|
2005
2344
|
id: "canopy-modal-filters",
|
|
@@ -2014,8 +2353,8 @@ function SearchFiltersDialog(props = {}) {
|
|
|
2014
2353
|
onBackgroundClick: () => onOpenChange && onOpenChange(false),
|
|
2015
2354
|
bodyClassName: "canopy-modal__body--filters"
|
|
2016
2355
|
},
|
|
2017
|
-
subtitleText ? /* @__PURE__ */
|
|
2018
|
-
/* @__PURE__ */
|
|
2356
|
+
subtitleText ? /* @__PURE__ */ React31.createElement("p", { className: "canopy-search-filters__subtitle" }, subtitleText) : null,
|
|
2357
|
+
/* @__PURE__ */ React31.createElement("div", { className: "canopy-search-filters__body" }, Array.isArray(facets) && facets.length ? /* @__PURE__ */ React31.createElement("div", { className: "canopy-search-filters__facets" }, facets.map((facet) => /* @__PURE__ */ React31.createElement(
|
|
2019
2358
|
FacetSection,
|
|
2020
2359
|
{
|
|
2021
2360
|
key: facet.slug || facet.label,
|
|
@@ -2023,8 +2362,8 @@ function SearchFiltersDialog(props = {}) {
|
|
|
2023
2362
|
selected: selectedMap,
|
|
2024
2363
|
onToggle
|
|
2025
2364
|
}
|
|
2026
|
-
))) : /* @__PURE__ */
|
|
2027
|
-
/* @__PURE__ */
|
|
2365
|
+
))) : /* @__PURE__ */ React31.createElement("p", { className: "canopy-search-filters__empty" }, "No filters are available for this collection.")),
|
|
2366
|
+
/* @__PURE__ */ React31.createElement("footer", { className: "canopy-search-filters__footer" }, /* @__PURE__ */ React31.createElement("div", null, activeCount ? `${activeCount} filter${activeCount === 1 ? "" : "s"} applied` : "No filters applied"), /* @__PURE__ */ React31.createElement("div", { className: "canopy-search-filters__footer-actions" }, /* @__PURE__ */ React31.createElement(
|
|
2028
2367
|
"button",
|
|
2029
2368
|
{
|
|
2030
2369
|
type: "button",
|
|
@@ -2035,7 +2374,7 @@ function SearchFiltersDialog(props = {}) {
|
|
|
2035
2374
|
className: "canopy-search-filters__button canopy-search-filters__button--secondary"
|
|
2036
2375
|
},
|
|
2037
2376
|
"Clear all"
|
|
2038
|
-
), /* @__PURE__ */
|
|
2377
|
+
), /* @__PURE__ */ React31.createElement(
|
|
2039
2378
|
"button",
|
|
2040
2379
|
{
|
|
2041
2380
|
type: "button",
|
|
@@ -2048,7 +2387,7 @@ function SearchFiltersDialog(props = {}) {
|
|
|
2048
2387
|
}
|
|
2049
2388
|
|
|
2050
2389
|
// ui/src/search-form/MdxSearchFormModal.jsx
|
|
2051
|
-
import
|
|
2390
|
+
import React32 from "react";
|
|
2052
2391
|
function MdxSearchFormModal(props = {}) {
|
|
2053
2392
|
const {
|
|
2054
2393
|
placeholder = "Search\u2026",
|
|
@@ -2064,24 +2403,24 @@ function MdxSearchFormModal(props = {}) {
|
|
|
2064
2403
|
const text = typeof label === "string" && label.trim() ? label.trim() : buttonLabel;
|
|
2065
2404
|
const resolvedSearchPath = resolveSearchPath(searchPath);
|
|
2066
2405
|
const data = { placeholder, hotkey, maxResults, groupOrder, label: text, searchPath: resolvedSearchPath };
|
|
2067
|
-
return /* @__PURE__ */
|
|
2406
|
+
return /* @__PURE__ */ React32.createElement("div", { "data-canopy-search-form": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React32.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React32.createElement(SearchPanelForm, { placeholder, buttonLabel, label, searchPath: resolvedSearchPath }), /* @__PURE__ */ React32.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React32.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
|
|
2068
2407
|
}
|
|
2069
2408
|
|
|
2070
2409
|
// ui/src/docs/MarkdownTable.jsx
|
|
2071
|
-
import
|
|
2410
|
+
import React33 from "react";
|
|
2072
2411
|
function MarkdownTable({ className = "", ...rest }) {
|
|
2073
2412
|
const merged = ["markdown-table", className].filter(Boolean).join(" ");
|
|
2074
|
-
return /* @__PURE__ */
|
|
2413
|
+
return /* @__PURE__ */ React33.createElement("div", { className: "markdown-table__frame" }, /* @__PURE__ */ React33.createElement("table", { className: merged, ...rest }));
|
|
2075
2414
|
}
|
|
2076
2415
|
|
|
2077
2416
|
// ui/src/docs/Diagram.jsx
|
|
2078
|
-
import
|
|
2417
|
+
import React34 from "react";
|
|
2079
2418
|
function CanopyDiagram() {
|
|
2080
|
-
return /* @__PURE__ */
|
|
2419
|
+
return /* @__PURE__ */ React34.createElement("div", { className: "canopy-diagram" }, /* @__PURE__ */ React34.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--collections" }, /* @__PURE__ */ React34.createElement("h3", null, "IIIF Collection(s)"), /* @__PURE__ */ React34.createElement("span", { className: "canopy-diagram__section-summary" }, "Source collections contribute 105 total manifests that Canopy retrieves as-is via IIIF endpoints."), /* @__PURE__ */ React34.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React34.createElement("article", null, /* @__PURE__ */ React34.createElement("h4", null, "Collection A"), /* @__PURE__ */ React34.createElement("ul", null, /* @__PURE__ */ React34.createElement("li", null, "70 Manifests"), /* @__PURE__ */ React34.createElement("li", null, "IIIF Images + A/V"), /* @__PURE__ */ React34.createElement("li", null, "Textual Annotations"))), /* @__PURE__ */ React34.createElement("article", null, /* @__PURE__ */ React34.createElement("h4", null, "Collection B"), /* @__PURE__ */ React34.createElement("ul", null, /* @__PURE__ */ React34.createElement("li", null, "35 Manifests"), /* @__PURE__ */ React34.createElement("li", null, "IIIF Images + A/V"), /* @__PURE__ */ React34.createElement("li", null, "Textual Annotations"))))), /* @__PURE__ */ React34.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React34.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React34.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React34.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--build" }, /* @__PURE__ */ React34.createElement("h3", null, "Canopy Build Process"), /* @__PURE__ */ React34.createElement("span", { className: "canopy-diagram__section-summary" }, "Canopy syncs manifests, page content, and annotations before bundling the site."), /* @__PURE__ */ React34.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React34.createElement("article", null, /* @__PURE__ */ React34.createElement("h4", null, "Automated content"), /* @__PURE__ */ React34.createElement("ul", null, /* @__PURE__ */ React34.createElement("li", null, "105 manifests \u2192 105 work pages"), /* @__PURE__ */ React34.createElement("li", null, "One page per manifest"), /* @__PURE__ */ React34.createElement("li", null, "Customize page layout"))), /* @__PURE__ */ React34.createElement("article", null, /* @__PURE__ */ React34.createElement("h4", null, "Contextual content"), /* @__PURE__ */ React34.createElement("ul", null, /* @__PURE__ */ React34.createElement("li", null, "Markdown & MDX pages"), /* @__PURE__ */ React34.createElement("li", null, "Author narratives"), /* @__PURE__ */ React34.createElement("li", null, "Reference manifests inline"))), /* @__PURE__ */ React34.createElement("article", null, /* @__PURE__ */ React34.createElement("h4", null, "Search index"), /* @__PURE__ */ React34.createElement("ul", null, /* @__PURE__ */ React34.createElement("li", null, "Combines works + pages"), /* @__PURE__ */ React34.createElement("li", null, "Customize result layout"), /* @__PURE__ */ React34.createElement("li", null, "Optional annotations"))))), /* @__PURE__ */ React34.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React34.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React34.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React34.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--output" }, /* @__PURE__ */ React34.createElement("h3", null, "Static Digital Project"), /* @__PURE__ */ React34.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__ */ React34.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React34.createElement("article", null, /* @__PURE__ */ React34.createElement("h4", null, "Work pages"), /* @__PURE__ */ React34.createElement("ul", null, /* @__PURE__ */ React34.createElement("li", null, "105 generated HTML pages"), /* @__PURE__ */ React34.createElement("li", null, "Each links back to source manifests"), /* @__PURE__ */ React34.createElement("li", null, "Styled with Canopy components"))), /* @__PURE__ */ React34.createElement("article", null, /* @__PURE__ */ React34.createElement("h4", null, "Custom pages"), /* @__PURE__ */ React34.createElement("ul", null, /* @__PURE__ */ React34.createElement("li", null, "Markdown & MDX-authored content"), /* @__PURE__ */ React34.createElement("li", null, "Reusable layouts for narratives"), /* @__PURE__ */ React34.createElement("li", null, "Embed IIIF media & interstitials"))), /* @__PURE__ */ React34.createElement("article", null, /* @__PURE__ */ React34.createElement("h4", null, "Search bundle"), /* @__PURE__ */ React34.createElement("ul", null, /* @__PURE__ */ React34.createElement("li", null, "Static FlexSearch index"), /* @__PURE__ */ React34.createElement("li", null, "Works + pages share records"), /* @__PURE__ */ React34.createElement("li", null, "Optional annotation dataset"))))));
|
|
2081
2420
|
}
|
|
2082
2421
|
|
|
2083
2422
|
// ui/src/content/timeline/Timeline.jsx
|
|
2084
|
-
import
|
|
2423
|
+
import React36 from "react";
|
|
2085
2424
|
|
|
2086
2425
|
// ui/src/content/timeline/date-utils.js
|
|
2087
2426
|
var FALLBACK_LOCALE = (() => {
|
|
@@ -2234,7 +2573,7 @@ function clampProgress(value) {
|
|
|
2234
2573
|
}
|
|
2235
2574
|
|
|
2236
2575
|
// ui/src/layout/ReferencedManifestCard.jsx
|
|
2237
|
-
import
|
|
2576
|
+
import React35 from "react";
|
|
2238
2577
|
function normalizeMetadata(metadata, summary) {
|
|
2239
2578
|
if (Array.isArray(metadata) && metadata.length) {
|
|
2240
2579
|
return metadata.filter(Boolean);
|
|
@@ -2268,7 +2607,7 @@ function ReferencedManifestCard({
|
|
|
2268
2607
|
"canopy-referenced-manifest-card",
|
|
2269
2608
|
className
|
|
2270
2609
|
].filter(Boolean).join(" ");
|
|
2271
|
-
return /* @__PURE__ */
|
|
2610
|
+
return /* @__PURE__ */ React35.createElement(
|
|
2272
2611
|
TeaserCard,
|
|
2273
2612
|
{
|
|
2274
2613
|
href: resolvedHref || void 0,
|
|
@@ -2450,14 +2789,14 @@ function TimelineConnector({ side, isActive, highlight }) {
|
|
|
2450
2789
|
"canopy-timeline__connector-dot",
|
|
2451
2790
|
highlight || isActive ? "is-active" : ""
|
|
2452
2791
|
].filter(Boolean).join(" ");
|
|
2453
|
-
return /* @__PURE__ */
|
|
2792
|
+
return /* @__PURE__ */ React36.createElement("span", { className: connectorClasses, "aria-hidden": "true" }, side === "left" ? /* @__PURE__ */ React36.createElement(React36.Fragment, null, /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__connector-line" }), /* @__PURE__ */ React36.createElement("span", { className: dotClasses })) : /* @__PURE__ */ React36.createElement(React36.Fragment, null, /* @__PURE__ */ React36.createElement("span", { className: dotClasses }), /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__connector-line" })));
|
|
2454
2793
|
}
|
|
2455
2794
|
function renderResourceSection(point) {
|
|
2456
2795
|
if (!point) return null;
|
|
2457
2796
|
const manifestCards = Array.isArray(point.manifests) ? point.manifests.filter(Boolean) : [];
|
|
2458
2797
|
const legacyResources = Array.isArray(point.resources) ? point.resources.filter(Boolean) : [];
|
|
2459
2798
|
if (!manifestCards.length && !legacyResources.length) return null;
|
|
2460
|
-
return /* @__PURE__ */
|
|
2799
|
+
return /* @__PURE__ */ React36.createElement("div", { className: "canopy-timeline__resources" }, /* @__PURE__ */ React36.createElement("div", { className: "canopy-timeline__resources-list" }, manifestCards.map((manifest) => /* @__PURE__ */ React36.createElement("div", { key: manifest.id || manifest.href }, /* @__PURE__ */ React36.createElement(ReferencedManifestCard, { manifest }))), legacyResources.map((resource, idx) => /* @__PURE__ */ React36.createElement("div", { key: resource.id || resource.href || `legacy-${idx}` }, /* @__PURE__ */ React36.createElement(
|
|
2461
2800
|
TeaserCard,
|
|
2462
2801
|
{
|
|
2463
2802
|
href: resource.href,
|
|
@@ -2482,26 +2821,26 @@ function Timeline({
|
|
|
2482
2821
|
...rest
|
|
2483
2822
|
}) {
|
|
2484
2823
|
const payloadPoints = payload && Array.isArray(payload.points) ? payload.points : null;
|
|
2485
|
-
const rawPoints =
|
|
2824
|
+
const rawPoints = React36.useMemo(() => {
|
|
2486
2825
|
if (Array.isArray(pointsProp) && pointsProp.length) return pointsProp;
|
|
2487
2826
|
if (payloadPoints && payloadPoints.length) return payloadPoints;
|
|
2488
2827
|
return [];
|
|
2489
2828
|
}, [pointsProp, payloadPoints]);
|
|
2490
|
-
const sanitizedPoints =
|
|
2829
|
+
const sanitizedPoints = React36.useMemo(
|
|
2491
2830
|
() => sanitizePoints(rawPoints),
|
|
2492
2831
|
[rawPoints]
|
|
2493
2832
|
);
|
|
2494
2833
|
const localeValue = payload && payload.locale ? payload.locale : localeProp;
|
|
2495
|
-
const baseLocale =
|
|
2834
|
+
const baseLocale = React36.useMemo(
|
|
2496
2835
|
() => createLocale(localeValue),
|
|
2497
2836
|
[localeValue]
|
|
2498
2837
|
);
|
|
2499
2838
|
const rangeInput = payload && payload.range ? payload.range : rangeProp || {};
|
|
2500
|
-
const rangeOverrides =
|
|
2839
|
+
const rangeOverrides = React36.useMemo(
|
|
2501
2840
|
() => deriveRangeOverrides(sanitizedPoints, rangeInput),
|
|
2502
2841
|
[sanitizedPoints, rangeInput]
|
|
2503
2842
|
);
|
|
2504
|
-
const effectiveRange =
|
|
2843
|
+
const effectiveRange = React36.useMemo(
|
|
2505
2844
|
() => normalizeRange({
|
|
2506
2845
|
...rangeOverrides,
|
|
2507
2846
|
locale: baseLocale
|
|
@@ -2510,7 +2849,7 @@ function Timeline({
|
|
|
2510
2849
|
);
|
|
2511
2850
|
const spanStart = effectiveRange.startDate.getTime();
|
|
2512
2851
|
const span = effectiveRange.span;
|
|
2513
|
-
const pointsWithPosition =
|
|
2852
|
+
const pointsWithPosition = React36.useMemo(() => {
|
|
2514
2853
|
if (!sanitizedPoints.length) return [];
|
|
2515
2854
|
return sanitizedPoints.map((point, index) => {
|
|
2516
2855
|
const timestamp = point.meta.timestamp;
|
|
@@ -2524,29 +2863,29 @@ function Timeline({
|
|
|
2524
2863
|
};
|
|
2525
2864
|
});
|
|
2526
2865
|
}, [sanitizedPoints, spanStart, span]);
|
|
2527
|
-
const [activeId, setActiveId] =
|
|
2866
|
+
const [activeId, setActiveId] = React36.useState(
|
|
2528
2867
|
() => getActivePointId(pointsWithPosition)
|
|
2529
2868
|
);
|
|
2530
|
-
|
|
2869
|
+
React36.useEffect(() => {
|
|
2531
2870
|
setActiveId(getActivePointId(pointsWithPosition));
|
|
2532
2871
|
}, [pointsWithPosition]);
|
|
2533
2872
|
const thresholdValue = typeof thresholdProp === "number" ? thresholdProp : payload && payload.threshold != null ? payload.threshold : null;
|
|
2534
2873
|
const stepsValue = typeof steps === "number" ? Number(steps) : payload && typeof payload.steps === "number" ? Number(payload.steps) : null;
|
|
2535
|
-
const thresholdMs =
|
|
2874
|
+
const thresholdMs = React36.useMemo(
|
|
2536
2875
|
() => getThresholdMs(thresholdValue, effectiveRange.granularity),
|
|
2537
2876
|
[thresholdValue, effectiveRange.granularity]
|
|
2538
2877
|
);
|
|
2539
|
-
const groupedEntries =
|
|
2878
|
+
const groupedEntries = React36.useMemo(
|
|
2540
2879
|
() => buildGroupedEntries(pointsWithPosition, thresholdMs, {
|
|
2541
2880
|
granularity: effectiveRange.granularity,
|
|
2542
2881
|
locale: baseLocale
|
|
2543
2882
|
}),
|
|
2544
2883
|
[pointsWithPosition, thresholdMs, effectiveRange.granularity, baseLocale]
|
|
2545
2884
|
);
|
|
2546
|
-
const [expandedGroupIds, setExpandedGroupIds] =
|
|
2885
|
+
const [expandedGroupIds, setExpandedGroupIds] = React36.useState(
|
|
2547
2886
|
() => /* @__PURE__ */ new Set()
|
|
2548
2887
|
);
|
|
2549
|
-
|
|
2888
|
+
React36.useEffect(() => {
|
|
2550
2889
|
setExpandedGroupIds((prev) => {
|
|
2551
2890
|
if (!prev || prev.size === 0) return prev;
|
|
2552
2891
|
const validIds = new Set(
|
|
@@ -2561,7 +2900,7 @@ function Timeline({
|
|
|
2561
2900
|
return changed ? next : prev;
|
|
2562
2901
|
});
|
|
2563
2902
|
}, [groupedEntries]);
|
|
2564
|
-
const toggleGroup =
|
|
2903
|
+
const toggleGroup = React36.useCallback((groupId) => {
|
|
2565
2904
|
setExpandedGroupIds((prev) => {
|
|
2566
2905
|
const next = new Set(prev || []);
|
|
2567
2906
|
if (next.has(groupId)) next.delete(groupId);
|
|
@@ -2584,7 +2923,7 @@ function Timeline({
|
|
|
2584
2923
|
point.id === activeId ? "is-active" : "",
|
|
2585
2924
|
point.highlight ? "is-highlighted" : ""
|
|
2586
2925
|
].filter(Boolean).join(" ");
|
|
2587
|
-
const connector = /* @__PURE__ */
|
|
2926
|
+
const connector = /* @__PURE__ */ React36.createElement(
|
|
2588
2927
|
TimelineConnector,
|
|
2589
2928
|
{
|
|
2590
2929
|
side: point.side,
|
|
@@ -2592,9 +2931,9 @@ function Timeline({
|
|
|
2592
2931
|
highlight: point.highlight
|
|
2593
2932
|
}
|
|
2594
2933
|
);
|
|
2595
|
-
const body = /* @__PURE__ */
|
|
2934
|
+
const body = /* @__PURE__ */ React36.createElement("div", { className: "canopy-timeline__point-body" }, /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label), /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__point-title" }, point.title), point.summary ? /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__point-summary" }, point.summary) : null);
|
|
2596
2935
|
const resourceSection = renderResourceSection(point);
|
|
2597
|
-
return /* @__PURE__ */
|
|
2936
|
+
return /* @__PURE__ */ React36.createElement(
|
|
2598
2937
|
"div",
|
|
2599
2938
|
{
|
|
2600
2939
|
key: point.id,
|
|
@@ -2602,7 +2941,7 @@ function Timeline({
|
|
|
2602
2941
|
style: wrapperStyle,
|
|
2603
2942
|
role: "listitem"
|
|
2604
2943
|
},
|
|
2605
|
-
point.side === "left" ? /* @__PURE__ */
|
|
2944
|
+
point.side === "left" ? /* @__PURE__ */ React36.createElement(React36.Fragment, null, /* @__PURE__ */ React36.createElement("div", { className: cardClasses }, body, resourceSection), connector) : /* @__PURE__ */ React36.createElement(React36.Fragment, null, connector, /* @__PURE__ */ React36.createElement("div", { className: cardClasses }, body, resourceSection))
|
|
2606
2945
|
);
|
|
2607
2946
|
}
|
|
2608
2947
|
function renderGroupEntry(entry) {
|
|
@@ -2613,7 +2952,7 @@ function Timeline({
|
|
|
2613
2952
|
const wrapperStyle = { top: `${entry.progress * 100}%` };
|
|
2614
2953
|
const isExpanded = expandedGroupIds.has(entry.id);
|
|
2615
2954
|
const hasActivePoint = entry.points.some((point) => point.id === activeId);
|
|
2616
|
-
const connector = /* @__PURE__ */
|
|
2955
|
+
const connector = /* @__PURE__ */ React36.createElement(
|
|
2617
2956
|
TimelineConnector,
|
|
2618
2957
|
{
|
|
2619
2958
|
side: entry.side,
|
|
@@ -2627,7 +2966,7 @@ function Timeline({
|
|
|
2627
2966
|
hasActivePoint ? "is-active" : ""
|
|
2628
2967
|
].filter(Boolean).join(" ");
|
|
2629
2968
|
const countLabel = `${entry.count} event${entry.count > 1 ? "s" : ""}`;
|
|
2630
|
-
const header = /* @__PURE__ */
|
|
2969
|
+
const header = /* @__PURE__ */ React36.createElement("div", { className: "canopy-timeline__group-header" }, /* @__PURE__ */ React36.createElement("div", { className: "canopy-timeline__group-summary" }, /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__point-date" }, entry.label), /* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__group-count" }, countLabel)), /* @__PURE__ */ React36.createElement(
|
|
2631
2970
|
"button",
|
|
2632
2971
|
{
|
|
2633
2972
|
type: "button",
|
|
@@ -2637,7 +2976,7 @@ function Timeline({
|
|
|
2637
2976
|
},
|
|
2638
2977
|
isExpanded ? "Hide details" : "Show details"
|
|
2639
2978
|
));
|
|
2640
|
-
const groupPoints = isExpanded ? /* @__PURE__ */
|
|
2979
|
+
const groupPoints = isExpanded ? /* @__PURE__ */ React36.createElement("div", { className: "canopy-timeline__group-points" }, entry.points.map((point) => /* @__PURE__ */ React36.createElement(
|
|
2641
2980
|
"button",
|
|
2642
2981
|
{
|
|
2643
2982
|
key: point.id,
|
|
@@ -2648,11 +2987,11 @@ function Timeline({
|
|
|
2648
2987
|
].filter(Boolean).join(" "),
|
|
2649
2988
|
onClick: () => setActiveId(point.id)
|
|
2650
2989
|
},
|
|
2651
|
-
/* @__PURE__ */
|
|
2652
|
-
/* @__PURE__ */
|
|
2990
|
+
/* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label),
|
|
2991
|
+
/* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__group-point-title" }, point.title)
|
|
2653
2992
|
))) : null;
|
|
2654
|
-
const groupCard = /* @__PURE__ */
|
|
2655
|
-
return /* @__PURE__ */
|
|
2993
|
+
const groupCard = /* @__PURE__ */ React36.createElement("div", { className: groupClasses }, header, groupPoints);
|
|
2994
|
+
return /* @__PURE__ */ React36.createElement(
|
|
2656
2995
|
"div",
|
|
2657
2996
|
{
|
|
2658
2997
|
key: entry.id,
|
|
@@ -2660,17 +2999,17 @@ function Timeline({
|
|
|
2660
2999
|
style: wrapperStyle,
|
|
2661
3000
|
role: "listitem"
|
|
2662
3001
|
},
|
|
2663
|
-
entry.side === "left" ? /* @__PURE__ */
|
|
3002
|
+
entry.side === "left" ? /* @__PURE__ */ React36.createElement(React36.Fragment, null, groupCard, connector) : /* @__PURE__ */ React36.createElement(React36.Fragment, null, connector, groupCard)
|
|
2664
3003
|
);
|
|
2665
3004
|
}
|
|
2666
|
-
return /* @__PURE__ */
|
|
3005
|
+
return /* @__PURE__ */ React36.createElement("section", { className: containerClasses, ...rest }, title ? /* @__PURE__ */ React36.createElement("h2", { className: "canopy-timeline__title" }, title) : null, description ? /* @__PURE__ */ React36.createElement("p", { className: "canopy-timeline__description" }, description) : null, rangeLabel ? /* @__PURE__ */ React36.createElement("p", { className: "canopy-timeline__range", "aria-live": "polite" }, rangeLabel) : null, /* @__PURE__ */ React36.createElement("div", { className: "canopy-timeline__body" }, /* @__PURE__ */ React36.createElement(
|
|
2667
3006
|
"div",
|
|
2668
3007
|
{
|
|
2669
3008
|
className: "canopy-timeline__list",
|
|
2670
3009
|
role: "list",
|
|
2671
3010
|
style: { minHeight: trackHeight }
|
|
2672
3011
|
},
|
|
2673
|
-
/* @__PURE__ */
|
|
3012
|
+
/* @__PURE__ */ React36.createElement("div", { className: "canopy-timeline__spine", "aria-hidden": "true" }),
|
|
2674
3013
|
renderSteps(stepsValue, effectiveRange),
|
|
2675
3014
|
groupedEntries.map((entry) => {
|
|
2676
3015
|
if (entry.type === "group") return renderGroupEntry(entry);
|
|
@@ -2685,7 +3024,7 @@ function renderSteps(stepSize, range) {
|
|
|
2685
3024
|
const markers = [];
|
|
2686
3025
|
if (startYear < endYear) {
|
|
2687
3026
|
markers.push(
|
|
2688
|
-
/* @__PURE__ */
|
|
3027
|
+
/* @__PURE__ */ React36.createElement(
|
|
2689
3028
|
"span",
|
|
2690
3029
|
{
|
|
2691
3030
|
key: "timeline-step-start",
|
|
@@ -2693,12 +3032,12 @@ function renderSteps(stepSize, range) {
|
|
|
2693
3032
|
style: { top: "0%" },
|
|
2694
3033
|
"aria-hidden": "true"
|
|
2695
3034
|
},
|
|
2696
|
-
/* @__PURE__ */
|
|
2697
|
-
/* @__PURE__ */
|
|
3035
|
+
/* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__step-line" }),
|
|
3036
|
+
/* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__step-label" }, startYear)
|
|
2698
3037
|
)
|
|
2699
3038
|
);
|
|
2700
3039
|
markers.push(
|
|
2701
|
-
/* @__PURE__ */
|
|
3040
|
+
/* @__PURE__ */ React36.createElement(
|
|
2702
3041
|
"span",
|
|
2703
3042
|
{
|
|
2704
3043
|
key: "timeline-step-end",
|
|
@@ -2706,8 +3045,8 @@ function renderSteps(stepSize, range) {
|
|
|
2706
3045
|
style: { top: "100%" },
|
|
2707
3046
|
"aria-hidden": "true"
|
|
2708
3047
|
},
|
|
2709
|
-
/* @__PURE__ */
|
|
2710
|
-
/* @__PURE__ */
|
|
3048
|
+
/* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__step-line" }),
|
|
3049
|
+
/* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__step-label" }, endYear)
|
|
2711
3050
|
)
|
|
2712
3051
|
);
|
|
2713
3052
|
}
|
|
@@ -2717,7 +3056,7 @@ function renderSteps(stepSize, range) {
|
|
|
2717
3056
|
const progress = (timestamp - range.startDate.getTime()) / range.span;
|
|
2718
3057
|
if (progress <= 0 || progress >= 1) continue;
|
|
2719
3058
|
markers.push(
|
|
2720
|
-
/* @__PURE__ */
|
|
3059
|
+
/* @__PURE__ */ React36.createElement(
|
|
2721
3060
|
"span",
|
|
2722
3061
|
{
|
|
2723
3062
|
key: `timeline-step-${year}`,
|
|
@@ -2725,8 +3064,8 @@ function renderSteps(stepSize, range) {
|
|
|
2725
3064
|
style: { top: `calc(${progress * 100}% - 0.5px)` },
|
|
2726
3065
|
"aria-hidden": "true"
|
|
2727
3066
|
},
|
|
2728
|
-
/* @__PURE__ */
|
|
2729
|
-
/* @__PURE__ */
|
|
3067
|
+
/* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__step-line" }),
|
|
3068
|
+
/* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__step-label" }, year)
|
|
2730
3069
|
)
|
|
2731
3070
|
);
|
|
2732
3071
|
}
|
|
@@ -2740,7 +3079,7 @@ function TimelinePoint() {
|
|
|
2740
3079
|
TimelinePoint.displayName = "TimelinePoint";
|
|
2741
3080
|
|
|
2742
3081
|
// ui/src/content/map/Map.jsx
|
|
2743
|
-
import
|
|
3082
|
+
import React37 from "react";
|
|
2744
3083
|
import { createRoot } from "react-dom/client";
|
|
2745
3084
|
var DEFAULT_TILE_LAYERS = [
|
|
2746
3085
|
{
|
|
@@ -3007,7 +3346,7 @@ function MapPopupContent({ marker }) {
|
|
|
3007
3346
|
...manifest,
|
|
3008
3347
|
href: manifest.href ? withBasePath(manifest.href) : manifest.href || ""
|
|
3009
3348
|
}));
|
|
3010
|
-
return /* @__PURE__ */
|
|
3349
|
+
return /* @__PURE__ */ React37.createElement("div", { className: "canopy-map__popup" }, thumbnail ? /* @__PURE__ */ React37.createElement("div", { className: "canopy-map__popup-media" }, /* @__PURE__ */ React37.createElement(
|
|
3011
3350
|
"img",
|
|
3012
3351
|
{
|
|
3013
3352
|
src: thumbnail,
|
|
@@ -3016,19 +3355,19 @@ function MapPopupContent({ marker }) {
|
|
|
3016
3355
|
width: typeof thumbWidth === "number" && thumbWidth > 0 ? thumbWidth : void 0,
|
|
3017
3356
|
height: typeof thumbHeight === "number" && thumbHeight > 0 ? thumbHeight : void 0
|
|
3018
3357
|
}
|
|
3019
|
-
)) : null, /* @__PURE__ */
|
|
3358
|
+
)) : null, /* @__PURE__ */ React37.createElement("div", { className: "canopy-map__popup-body" }, title ? href ? /* @__PURE__ */ React37.createElement("a", { href, className: "canopy-map__popup-title" }, title) : /* @__PURE__ */ React37.createElement("span", { className: "canopy-map__popup-title" }, title) : null, summary ? /* @__PURE__ */ React37.createElement("p", { className: "canopy-map__popup-summary" }, summary) : null, marker.detailsHtml ? /* @__PURE__ */ React37.createElement(
|
|
3020
3359
|
"div",
|
|
3021
3360
|
{
|
|
3022
3361
|
className: "canopy-map__popup-details",
|
|
3023
3362
|
dangerouslySetInnerHTML: { __html: marker.detailsHtml }
|
|
3024
3363
|
}
|
|
3025
|
-
) : null, !summary && !marker.detailsHtml && href && !title ? /* @__PURE__ */
|
|
3364
|
+
) : null, !summary && !marker.detailsHtml && href && !title ? /* @__PURE__ */ React37.createElement("a", { href, className: "canopy-map__popup-link" }, "View item") : null, normalizedManifests.length ? /* @__PURE__ */ React37.createElement("div", { className: "canopy-map__popup-manifests" }, /* @__PURE__ */ React37.createElement("div", { className: "canopy-map__popup-manifests-list" }, normalizedManifests.map((manifest, index) => /* @__PURE__ */ React37.createElement(
|
|
3026
3365
|
"div",
|
|
3027
3366
|
{
|
|
3028
3367
|
key: manifest.id || manifest.href || `manifest-${index}`,
|
|
3029
3368
|
className: "canopy-map__popup-manifests-item"
|
|
3030
3369
|
},
|
|
3031
|
-
/* @__PURE__ */
|
|
3370
|
+
/* @__PURE__ */ React37.createElement(ReferencedManifestCard, { manifest })
|
|
3032
3371
|
)))) : null));
|
|
3033
3372
|
}
|
|
3034
3373
|
function renderPopup(marker) {
|
|
@@ -3040,7 +3379,7 @@ function renderPopup(marker) {
|
|
|
3040
3379
|
if (hadError) return;
|
|
3041
3380
|
try {
|
|
3042
3381
|
if (!root) root = createRoot(container);
|
|
3043
|
-
root.render(/* @__PURE__ */
|
|
3382
|
+
root.render(/* @__PURE__ */ React37.createElement(MapPopupContent, { marker }));
|
|
3044
3383
|
} catch (error) {
|
|
3045
3384
|
hadError = true;
|
|
3046
3385
|
if (root) {
|
|
@@ -3165,26 +3504,26 @@ function Map2({
|
|
|
3165
3504
|
defaultCenter = null,
|
|
3166
3505
|
defaultZoom = null
|
|
3167
3506
|
} = {}) {
|
|
3168
|
-
const containerRef =
|
|
3169
|
-
const mapRef =
|
|
3170
|
-
const layerRef =
|
|
3171
|
-
const [leafletLib, setLeafletLib] =
|
|
3172
|
-
const [leafletError, setLeafletError] =
|
|
3507
|
+
const containerRef = React37.useRef(null);
|
|
3508
|
+
const mapRef = React37.useRef(null);
|
|
3509
|
+
const layerRef = React37.useRef(null);
|
|
3510
|
+
const [leafletLib, setLeafletLib] = React37.useState(() => resolveGlobalLeaflet());
|
|
3511
|
+
const [leafletError, setLeafletError] = React37.useState(null);
|
|
3173
3512
|
const datasetInfo = navDataset && typeof navDataset === "object" ? navDataset : null;
|
|
3174
3513
|
const datasetHref = datasetInfo && datasetInfo.href || "/api/navplace.json";
|
|
3175
3514
|
const datasetVersion = datasetInfo && datasetInfo.version;
|
|
3176
3515
|
const datasetHasFeatures = !!(datasetInfo && datasetInfo.hasFeatures);
|
|
3177
|
-
const [navState, setNavState] =
|
|
3516
|
+
const [navState, setNavState] = React37.useState(() => ({
|
|
3178
3517
|
loading: false,
|
|
3179
3518
|
error: null,
|
|
3180
3519
|
markers: []
|
|
3181
3520
|
}));
|
|
3182
|
-
const [iiifTargets, setIiifTargets] =
|
|
3521
|
+
const [iiifTargets, setIiifTargets] = React37.useState(() => ({
|
|
3183
3522
|
loading: false,
|
|
3184
3523
|
error: null,
|
|
3185
3524
|
keys: []
|
|
3186
3525
|
}));
|
|
3187
|
-
|
|
3526
|
+
React37.useEffect(() => {
|
|
3188
3527
|
if (!iiifContent) {
|
|
3189
3528
|
setIiifTargets({ loading: false, error: null, keys: [] });
|
|
3190
3529
|
return;
|
|
@@ -3232,7 +3571,7 @@ function Map2({
|
|
|
3232
3571
|
const navTargets = iiifTargets.keys || [];
|
|
3233
3572
|
const navTargetsKey = navTargets.join("|");
|
|
3234
3573
|
const shouldFetchNav = datasetHasFeatures && navTargets.length > 0;
|
|
3235
|
-
|
|
3574
|
+
React37.useEffect(() => {
|
|
3236
3575
|
if (!shouldFetchNav) {
|
|
3237
3576
|
setNavState({ loading: false, error: null, markers: [] });
|
|
3238
3577
|
return void 0;
|
|
@@ -3264,7 +3603,7 @@ function Map2({
|
|
|
3264
3603
|
cancelled = true;
|
|
3265
3604
|
};
|
|
3266
3605
|
}, [datasetHref, datasetVersion, navTargetsKey, shouldFetchNav]);
|
|
3267
|
-
|
|
3606
|
+
React37.useEffect(() => {
|
|
3268
3607
|
if (leafletLib) return;
|
|
3269
3608
|
let cancelled = false;
|
|
3270
3609
|
waitForLeaflet().then((lib) => {
|
|
@@ -3276,7 +3615,7 @@ function Map2({
|
|
|
3276
3615
|
cancelled = true;
|
|
3277
3616
|
};
|
|
3278
3617
|
}, [leafletLib]);
|
|
3279
|
-
const navMatchMap =
|
|
3618
|
+
const navMatchMap = React37.useMemo(() => {
|
|
3280
3619
|
const matchMap = createMarkerMap();
|
|
3281
3620
|
(navState.markers || []).forEach((marker) => {
|
|
3282
3621
|
if (!marker || !Array.isArray(marker.matchKeys)) return;
|
|
@@ -3287,7 +3626,7 @@ function Map2({
|
|
|
3287
3626
|
});
|
|
3288
3627
|
return matchMap;
|
|
3289
3628
|
}, [navState.markers]);
|
|
3290
|
-
const normalizedCustom =
|
|
3629
|
+
const normalizedCustom = React37.useMemo(() => {
|
|
3291
3630
|
return normalizeCustomMarkers(customPoints).map((point) => {
|
|
3292
3631
|
if (!point || point.thumbnail || !point.href) return point;
|
|
3293
3632
|
const match = navMatchMap.get(normalizeKey(point.href));
|
|
@@ -3302,11 +3641,11 @@ function Map2({
|
|
|
3302
3641
|
};
|
|
3303
3642
|
});
|
|
3304
3643
|
}, [customPoints, navMatchMap]);
|
|
3305
|
-
const allMarkers =
|
|
3644
|
+
const allMarkers = React37.useMemo(() => {
|
|
3306
3645
|
return [...navState.markers || [], ...normalizedCustom];
|
|
3307
3646
|
}, [navState.markers, normalizedCustom]);
|
|
3308
|
-
const clusterOptions =
|
|
3309
|
-
|
|
3647
|
+
const clusterOptions = React37.useMemo(() => buildClusterOptions(leafletLib), [leafletLib]);
|
|
3648
|
+
React37.useEffect(() => {
|
|
3310
3649
|
if (!containerRef.current || mapRef.current || !leafletLib) return void 0;
|
|
3311
3650
|
const map = leafletLib.map(containerRef.current, {
|
|
3312
3651
|
zoomControl: true,
|
|
@@ -3344,7 +3683,7 @@ function Map2({
|
|
|
3344
3683
|
layerRef.current = null;
|
|
3345
3684
|
};
|
|
3346
3685
|
}, [tileLayers, scrollWheelZoom, cluster, clusterOptions, leafletLib]);
|
|
3347
|
-
|
|
3686
|
+
React37.useEffect(() => {
|
|
3348
3687
|
const map = mapRef.current;
|
|
3349
3688
|
const layer = layerRef.current;
|
|
3350
3689
|
if (!map || !layer || !leafletLib) return;
|
|
@@ -3448,14 +3787,14 @@ function Map2({
|
|
|
3448
3787
|
].filter(Boolean).join(" ");
|
|
3449
3788
|
const statusLabel = leafletError ? leafletError.message || "Failed to load map library" : !leafletLib ? "Loading map\u2026" : iiifTargets.error ? iiifTargets.error : datasetUnavailable ? "Map data is unavailable for this site." : navState.error ? navState.error : isLoadingMarkers ? "Loading map data\u2026" : !iiifContent && !hasCustomPoints ? "Add iiifContent or MapPoint markers to populate this map." : !hasMarkers ? "No map locations available." : "";
|
|
3450
3789
|
const showStatus = Boolean(statusLabel);
|
|
3451
|
-
return /* @__PURE__ */
|
|
3790
|
+
return /* @__PURE__ */ React37.createElement("div", { className: rootClass, id: id || void 0, style: style || void 0 }, /* @__PURE__ */ React37.createElement(
|
|
3452
3791
|
"div",
|
|
3453
3792
|
{
|
|
3454
3793
|
ref: containerRef,
|
|
3455
3794
|
className: "canopy-map__canvas",
|
|
3456
3795
|
style: { height: height || "600px" }
|
|
3457
3796
|
}
|
|
3458
|
-
), showStatus ? /* @__PURE__ */
|
|
3797
|
+
), showStatus ? /* @__PURE__ */ React37.createElement("div", { className: "canopy-map__status", "aria-live": "polite" }, statusLabel) : null);
|
|
3459
3798
|
}
|
|
3460
3799
|
|
|
3461
3800
|
// ui/src/content/map/MapPoint.jsx
|