@canopy-iiif/app 1.5.9 → 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 +524 -204
- package/ui/dist/index.mjs.map +4 -4
- package/ui/dist/server.mjs +602 -309
- package/ui/dist/server.mjs.map +4 -4
- 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/header/_header.scss +3 -1
- package/ui/styles/components/header/_navbar.scss +65 -50
- package/ui/styles/components/index.scss +1 -0
- package/ui/styles/index.css +168 -67
- package/ui/styles/settings/_breakpoints.scss +7 -0
package/ui/dist/index.mjs
CHANGED
|
@@ -451,7 +451,7 @@ function ButtonWrapper({
|
|
|
451
451
|
}
|
|
452
452
|
|
|
453
453
|
// ui/src/layout/CanopyHeader.jsx
|
|
454
|
-
import
|
|
454
|
+
import React15 from "react";
|
|
455
455
|
|
|
456
456
|
// ui/src/search/SearchPanel.jsx
|
|
457
457
|
import React11 from "react";
|
|
@@ -764,6 +764,130 @@ function CanopyModal(props = {}) {
|
|
|
764
764
|
)) : null, children)));
|
|
765
765
|
}
|
|
766
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
|
+
|
|
767
891
|
// ui/src/layout/CanopyHeader.jsx
|
|
768
892
|
function HeaderScript() {
|
|
769
893
|
const code = `
|
|
@@ -774,11 +898,24 @@ function HeaderScript() {
|
|
|
774
898
|
var body = doc.body;
|
|
775
899
|
var root = doc.documentElement;
|
|
776
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
|
+
|
|
777
914
|
function ready(fn) {
|
|
778
915
|
if (doc.readyState === 'loading') {
|
|
779
916
|
doc.addEventListener('DOMContentLoaded', fn, { once: true });
|
|
780
917
|
} else {
|
|
781
|
-
fn();
|
|
918
|
+
fn();
|
|
782
919
|
}
|
|
783
920
|
}
|
|
784
921
|
|
|
@@ -788,6 +925,8 @@ function HeaderScript() {
|
|
|
788
925
|
|
|
789
926
|
var NAV_ATTR = 'data-mobile-nav';
|
|
790
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';
|
|
791
930
|
|
|
792
931
|
function modalFor(type) {
|
|
793
932
|
return doc.querySelector('[data-canopy-modal="' + type + '"]');
|
|
@@ -869,6 +1008,51 @@ function HeaderScript() {
|
|
|
869
1008
|
});
|
|
870
1009
|
}
|
|
871
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
|
+
|
|
872
1056
|
function setState(type, next) {
|
|
873
1057
|
if (type === 'nav') header.setAttribute(NAV_ATTR, next);
|
|
874
1058
|
if (type === 'search') header.setAttribute(SEARCH_ATTR, next);
|
|
@@ -876,6 +1060,13 @@ function HeaderScript() {
|
|
|
876
1060
|
var navOpen = header.getAttribute(NAV_ATTR) === 'open';
|
|
877
1061
|
var searchOpen = header.getAttribute(SEARCH_ATTR) === 'open';
|
|
878
1062
|
lockScroll(navOpen || searchOpen);
|
|
1063
|
+
if (type === 'nav') {
|
|
1064
|
+
if (next !== 'open') {
|
|
1065
|
+
resetNavItemToggles(modalFor('nav'));
|
|
1066
|
+
} else {
|
|
1067
|
+
applyDefaultNavItemState(modalFor('nav'));
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
879
1070
|
}
|
|
880
1071
|
|
|
881
1072
|
function toggle(type, force) {
|
|
@@ -888,6 +1079,35 @@ function HeaderScript() {
|
|
|
888
1079
|
if (type === 'nav' && shouldOpen) focusNavMenu();
|
|
889
1080
|
}
|
|
890
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
|
+
|
|
891
1111
|
each(header.querySelectorAll('[data-canopy-header-toggle]'), function (btn) {
|
|
892
1112
|
btn.addEventListener('click', function (event) {
|
|
893
1113
|
event.preventDefault();
|
|
@@ -935,7 +1155,7 @@ function HeaderScript() {
|
|
|
935
1155
|
toggle('search', false);
|
|
936
1156
|
});
|
|
937
1157
|
|
|
938
|
-
var mq = window.matchMedia(
|
|
1158
|
+
var mq = window.matchMedia(desktopBreakpointQuery());
|
|
939
1159
|
function syncDesktopState() {
|
|
940
1160
|
if (mq.matches) {
|
|
941
1161
|
setState('nav', 'closed');
|
|
@@ -952,11 +1172,13 @@ function HeaderScript() {
|
|
|
952
1172
|
mq.addListener(syncDesktopState);
|
|
953
1173
|
}
|
|
954
1174
|
|
|
1175
|
+
setupNavItemToggles();
|
|
1176
|
+
applyDefaultNavItemState(null);
|
|
955
1177
|
syncDesktopState();
|
|
956
1178
|
});
|
|
957
1179
|
})();
|
|
958
1180
|
`;
|
|
959
|
-
return /* @__PURE__ */
|
|
1181
|
+
return /* @__PURE__ */ React15.createElement(
|
|
960
1182
|
"script",
|
|
961
1183
|
{
|
|
962
1184
|
dangerouslySetInnerHTML: {
|
|
@@ -975,7 +1197,7 @@ function getSharedRoot() {
|
|
|
975
1197
|
function getSafePageContext() {
|
|
976
1198
|
const root = getSharedRoot();
|
|
977
1199
|
if (root && root[CONTEXT_KEY]) return root[CONTEXT_KEY];
|
|
978
|
-
const ctx =
|
|
1200
|
+
const ctx = React15.createContext({ navigation: null, page: null });
|
|
979
1201
|
if (root) root[CONTEXT_KEY] = ctx;
|
|
980
1202
|
return ctx;
|
|
981
1203
|
}
|
|
@@ -985,29 +1207,55 @@ function ensureArray(navLinks) {
|
|
|
985
1207
|
(link) => link && typeof link === "object" && typeof link.href === "string"
|
|
986
1208
|
);
|
|
987
1209
|
}
|
|
988
|
-
function
|
|
989
|
-
if (
|
|
990
|
-
|
|
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;
|
|
991
1226
|
}
|
|
992
|
-
function
|
|
993
|
-
if (!
|
|
994
|
-
const
|
|
995
|
-
|
|
996
|
-
const
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
if (
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
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;
|
|
1011
1259
|
}
|
|
1012
1260
|
function CanopyHeader(props = {}) {
|
|
1013
1261
|
const {
|
|
@@ -1021,20 +1269,34 @@ function CanopyHeader(props = {}) {
|
|
|
1021
1269
|
} = props;
|
|
1022
1270
|
const navLinks = ensureArray(navLinksProp);
|
|
1023
1271
|
const PageContext = getSafePageContext();
|
|
1024
|
-
const context =
|
|
1025
|
-
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;
|
|
1026
1276
|
const sectionHeading = sectionNavigation && sectionNavigation.title || (sectionNavigation && sectionNavigation.root ? sectionNavigation.root.title : "");
|
|
1027
1277
|
const hasSectionNav = !!(sectionNavigation && sectionNavigation.root && Array.isArray(sectionNavigation.root.children) && sectionNavigation.root.children.length);
|
|
1028
1278
|
const sectionLabel = sectionHeading ? `More in ${sectionHeading}` : "More in this section";
|
|
1029
1279
|
const sectionAriaLabel = sectionHeading ? `${sectionHeading} section navigation` : "Section navigation";
|
|
1030
|
-
|
|
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(
|
|
1031
1293
|
"header",
|
|
1032
1294
|
{
|
|
1033
1295
|
className: "canopy-header",
|
|
1034
1296
|
"data-mobile-nav": "closed",
|
|
1035
1297
|
"data-mobile-search": "closed"
|
|
1036
1298
|
},
|
|
1037
|
-
/* @__PURE__ */
|
|
1299
|
+
/* @__PURE__ */ React15.createElement("div", { className: "canopy-header__brand" }, /* @__PURE__ */ React15.createElement(
|
|
1038
1300
|
CanopyBrand,
|
|
1039
1301
|
{
|
|
1040
1302
|
label: title,
|
|
@@ -1043,7 +1305,7 @@ function CanopyHeader(props = {}) {
|
|
|
1043
1305
|
Logo: SiteLogo
|
|
1044
1306
|
}
|
|
1045
1307
|
)),
|
|
1046
|
-
/* @__PURE__ */
|
|
1308
|
+
/* @__PURE__ */ React15.createElement("div", { className: "canopy-header__desktop-search" }, /* @__PURE__ */ React15.createElement(
|
|
1047
1309
|
SearchPanel,
|
|
1048
1310
|
{
|
|
1049
1311
|
label: searchLabel,
|
|
@@ -1051,13 +1313,13 @@ function CanopyHeader(props = {}) {
|
|
|
1051
1313
|
placeholder: searchPlaceholder
|
|
1052
1314
|
}
|
|
1053
1315
|
)),
|
|
1054
|
-
/* @__PURE__ */
|
|
1316
|
+
/* @__PURE__ */ React15.createElement(
|
|
1055
1317
|
"nav",
|
|
1056
1318
|
{
|
|
1057
1319
|
className: "canopy-nav-links canopy-header__desktop-nav",
|
|
1058
1320
|
"aria-label": "Primary navigation"
|
|
1059
1321
|
},
|
|
1060
|
-
navLinks.map((link) => /* @__PURE__ */
|
|
1322
|
+
navLinks.map((link) => /* @__PURE__ */ React15.createElement(
|
|
1061
1323
|
"a",
|
|
1062
1324
|
{
|
|
1063
1325
|
key: link.href,
|
|
@@ -1067,7 +1329,7 @@ function CanopyHeader(props = {}) {
|
|
|
1067
1329
|
link.label || link.href
|
|
1068
1330
|
))
|
|
1069
1331
|
),
|
|
1070
|
-
/* @__PURE__ */
|
|
1332
|
+
/* @__PURE__ */ React15.createElement("div", { className: "canopy-header__actions" }, /* @__PURE__ */ React15.createElement(
|
|
1071
1333
|
"button",
|
|
1072
1334
|
{
|
|
1073
1335
|
type: "button",
|
|
@@ -1077,7 +1339,7 @@ function CanopyHeader(props = {}) {
|
|
|
1077
1339
|
"aria-expanded": "false",
|
|
1078
1340
|
"data-canopy-header-toggle": "search"
|
|
1079
1341
|
},
|
|
1080
|
-
/* @__PURE__ */
|
|
1342
|
+
/* @__PURE__ */ React15.createElement(
|
|
1081
1343
|
"svg",
|
|
1082
1344
|
{
|
|
1083
1345
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -1087,7 +1349,7 @@ function CanopyHeader(props = {}) {
|
|
|
1087
1349
|
strokeWidth: "1.5",
|
|
1088
1350
|
className: "canopy-header__search-icon"
|
|
1089
1351
|
},
|
|
1090
|
-
/* @__PURE__ */
|
|
1352
|
+
/* @__PURE__ */ React15.createElement(
|
|
1091
1353
|
"path",
|
|
1092
1354
|
{
|
|
1093
1355
|
strokeLinecap: "round",
|
|
@@ -1096,7 +1358,7 @@ function CanopyHeader(props = {}) {
|
|
|
1096
1358
|
}
|
|
1097
1359
|
)
|
|
1098
1360
|
)
|
|
1099
|
-
), /* @__PURE__ */
|
|
1361
|
+
), /* @__PURE__ */ React15.createElement(
|
|
1100
1362
|
"button",
|
|
1101
1363
|
{
|
|
1102
1364
|
type: "button",
|
|
@@ -1106,7 +1368,7 @@ function CanopyHeader(props = {}) {
|
|
|
1106
1368
|
"aria-expanded": "false",
|
|
1107
1369
|
"data-canopy-header-toggle": "nav"
|
|
1108
1370
|
},
|
|
1109
|
-
/* @__PURE__ */
|
|
1371
|
+
/* @__PURE__ */ React15.createElement(
|
|
1110
1372
|
"svg",
|
|
1111
1373
|
{
|
|
1112
1374
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -1116,7 +1378,7 @@ function CanopyHeader(props = {}) {
|
|
|
1116
1378
|
stroke: "currentColor",
|
|
1117
1379
|
className: "canopy-header__menu-icon"
|
|
1118
1380
|
},
|
|
1119
|
-
/* @__PURE__ */
|
|
1381
|
+
/* @__PURE__ */ React15.createElement(
|
|
1120
1382
|
"path",
|
|
1121
1383
|
{
|
|
1122
1384
|
strokeLinecap: "round",
|
|
@@ -1126,7 +1388,7 @@ function CanopyHeader(props = {}) {
|
|
|
1126
1388
|
)
|
|
1127
1389
|
)
|
|
1128
1390
|
))
|
|
1129
|
-
), /* @__PURE__ */
|
|
1391
|
+
), /* @__PURE__ */ React15.createElement(
|
|
1130
1392
|
CanopyModal,
|
|
1131
1393
|
{
|
|
1132
1394
|
id: "canopy-modal-nav",
|
|
@@ -1138,32 +1400,90 @@ function CanopyHeader(props = {}) {
|
|
|
1138
1400
|
closeLabel: "Close navigation",
|
|
1139
1401
|
closeDataAttr: "nav"
|
|
1140
1402
|
},
|
|
1141
|
-
/* @__PURE__ */
|
|
1403
|
+
/* @__PURE__ */ React15.createElement(
|
|
1142
1404
|
"nav",
|
|
1143
1405
|
{
|
|
1144
1406
|
className: "canopy-nav-links canopy-modal__nav",
|
|
1145
1407
|
"aria-label": "Primary navigation"
|
|
1146
1408
|
},
|
|
1147
|
-
navLinks.map((link) =>
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
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
|
+
}))
|
|
1156
1475
|
),
|
|
1157
|
-
hasSectionNav ? /* @__PURE__ */
|
|
1158
|
-
|
|
1476
|
+
hasSectionNav && !hasIntegratedSectionNav ? /* @__PURE__ */ React15.createElement(
|
|
1477
|
+
NavigationTree,
|
|
1159
1478
|
{
|
|
1479
|
+
root: sectionNavigation.root,
|
|
1480
|
+
component: "nav",
|
|
1160
1481
|
className: "canopy-modal__section-nav",
|
|
1161
|
-
"aria-label":
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
/* @__PURE__ */ React14.createElement(SectionNavList, { root: sectionNavigation.root })
|
|
1482
|
+
"aria-label": defaultSectionAriaLabel,
|
|
1483
|
+
parentKey: "fallback-nav"
|
|
1484
|
+
}
|
|
1165
1485
|
) : null
|
|
1166
|
-
), /* @__PURE__ */
|
|
1486
|
+
), /* @__PURE__ */ React15.createElement(
|
|
1167
1487
|
CanopyModal,
|
|
1168
1488
|
{
|
|
1169
1489
|
id: "canopy-modal-search",
|
|
@@ -1176,7 +1496,7 @@ function CanopyHeader(props = {}) {
|
|
|
1176
1496
|
closeDataAttr: "search",
|
|
1177
1497
|
bodyClassName: "canopy-modal__body--search"
|
|
1178
1498
|
},
|
|
1179
|
-
/* @__PURE__ */
|
|
1499
|
+
/* @__PURE__ */ React15.createElement(
|
|
1180
1500
|
SearchPanel,
|
|
1181
1501
|
{
|
|
1182
1502
|
label: searchLabel,
|
|
@@ -1184,18 +1504,18 @@ function CanopyHeader(props = {}) {
|
|
|
1184
1504
|
placeholder: searchPlaceholder
|
|
1185
1505
|
}
|
|
1186
1506
|
)
|
|
1187
|
-
), /* @__PURE__ */
|
|
1507
|
+
), /* @__PURE__ */ React15.createElement(HeaderScript, null));
|
|
1188
1508
|
}
|
|
1189
1509
|
|
|
1190
1510
|
// ui/src/layout/CanopyFooter.jsx
|
|
1191
|
-
import
|
|
1511
|
+
import React16 from "react";
|
|
1192
1512
|
function CanopyFooter({ className = "", children }) {
|
|
1193
1513
|
const footerClassName = ["canopy-footer", className].filter(Boolean).join(" ");
|
|
1194
|
-
return /* @__PURE__ */
|
|
1514
|
+
return /* @__PURE__ */ React16.createElement("footer", { className: footerClassName }, /* @__PURE__ */ React16.createElement("div", { className: "canopy-footer__inner" }, children));
|
|
1195
1515
|
}
|
|
1196
1516
|
|
|
1197
1517
|
// ui/src/layout/TeaserCard.jsx
|
|
1198
|
-
import
|
|
1518
|
+
import React17 from "react";
|
|
1199
1519
|
function TeaserCard({
|
|
1200
1520
|
href = "",
|
|
1201
1521
|
title = "",
|
|
@@ -1216,7 +1536,7 @@ function TeaserCard({
|
|
|
1216
1536
|
].filter(Boolean).join(" ");
|
|
1217
1537
|
const showThumb = type === "work" && thumbnail;
|
|
1218
1538
|
const metaLine = (Array.isArray(metadata) && metadata.length ? metadata.filter(Boolean) : summary ? [summary] : []).filter(Boolean).slice(0, 2).join(" \u2022 ");
|
|
1219
|
-
return /* @__PURE__ */
|
|
1539
|
+
return /* @__PURE__ */ React17.createElement(
|
|
1220
1540
|
Tag,
|
|
1221
1541
|
{
|
|
1222
1542
|
className: classes,
|
|
@@ -1224,7 +1544,7 @@ function TeaserCard({
|
|
|
1224
1544
|
"data-canopy-item": href ? "" : void 0,
|
|
1225
1545
|
...rest
|
|
1226
1546
|
},
|
|
1227
|
-
showThumb ? /* @__PURE__ */
|
|
1547
|
+
showThumb ? /* @__PURE__ */ React17.createElement("div", { className: "canopy-search-teaser__thumb" }, /* @__PURE__ */ React17.createElement(
|
|
1228
1548
|
"img",
|
|
1229
1549
|
{
|
|
1230
1550
|
src: thumbnail,
|
|
@@ -1234,12 +1554,12 @@ function TeaserCard({
|
|
|
1234
1554
|
className: "canopy-search-teaser__thumb-img"
|
|
1235
1555
|
}
|
|
1236
1556
|
)) : null,
|
|
1237
|
-
/* @__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)
|
|
1238
1558
|
);
|
|
1239
1559
|
}
|
|
1240
1560
|
|
|
1241
1561
|
// ui/src/layout/GoogleAnalytics.jsx
|
|
1242
|
-
import
|
|
1562
|
+
import React18 from "react";
|
|
1243
1563
|
var GA_HOST = "https://www.googletagmanager.com/gtag/js";
|
|
1244
1564
|
function GoogleAnalytics({ id }) {
|
|
1245
1565
|
if (!id) return null;
|
|
@@ -1249,11 +1569,11 @@ function GoogleAnalytics({ id }) {
|
|
|
1249
1569
|
gtag('js', new Date());
|
|
1250
1570
|
gtag('config', '${id}');
|
|
1251
1571
|
`;
|
|
1252
|
-
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 } }));
|
|
1253
1573
|
}
|
|
1254
1574
|
|
|
1255
1575
|
// ui/src/iiif/Viewer.jsx
|
|
1256
|
-
import
|
|
1576
|
+
import React19, { useEffect as useEffect2, useState as useState2 } from "react";
|
|
1257
1577
|
var DEFAULT_VIEWER_OPTIONS = {
|
|
1258
1578
|
showDownload: false,
|
|
1259
1579
|
showIIIFBadge: false,
|
|
@@ -1309,7 +1629,7 @@ var Viewer = (props) => {
|
|
|
1309
1629
|
} catch (_) {
|
|
1310
1630
|
json = "{}";
|
|
1311
1631
|
}
|
|
1312
|
-
return /* @__PURE__ */
|
|
1632
|
+
return /* @__PURE__ */ React19.createElement("div", { "data-canopy-viewer": "1", className: "not-prose" }, /* @__PURE__ */ React19.createElement(
|
|
1313
1633
|
"script",
|
|
1314
1634
|
{
|
|
1315
1635
|
type: "application/json",
|
|
@@ -1317,11 +1637,11 @@ var Viewer = (props) => {
|
|
|
1317
1637
|
}
|
|
1318
1638
|
));
|
|
1319
1639
|
}
|
|
1320
|
-
return /* @__PURE__ */
|
|
1640
|
+
return /* @__PURE__ */ React19.createElement(CloverViewer, { ...props, options: mergedOptions });
|
|
1321
1641
|
};
|
|
1322
1642
|
|
|
1323
1643
|
// ui/src/iiif/Slider.jsx
|
|
1324
|
-
import
|
|
1644
|
+
import React20, { useEffect as useEffect3, useState as useState3 } from "react";
|
|
1325
1645
|
|
|
1326
1646
|
// ui/src/iiif/sliderOptions.js
|
|
1327
1647
|
var UNIT_TOKEN = "__canopySliderUnit";
|
|
@@ -1468,7 +1788,7 @@ var Slider = (props = {}) => {
|
|
|
1468
1788
|
} catch (_) {
|
|
1469
1789
|
json = "{}";
|
|
1470
1790
|
}
|
|
1471
|
-
return /* @__PURE__ */
|
|
1791
|
+
return /* @__PURE__ */ React20.createElement("div", { className: sliderClassName, "data-canopy-slider": "1" }, /* @__PURE__ */ React20.createElement(
|
|
1472
1792
|
"script",
|
|
1473
1793
|
{
|
|
1474
1794
|
type: "application/json",
|
|
@@ -1476,11 +1796,11 @@ var Slider = (props = {}) => {
|
|
|
1476
1796
|
}
|
|
1477
1797
|
));
|
|
1478
1798
|
}
|
|
1479
|
-
return /* @__PURE__ */
|
|
1799
|
+
return /* @__PURE__ */ React20.createElement(CloverSlider, { ...resolvedProps });
|
|
1480
1800
|
};
|
|
1481
1801
|
|
|
1482
1802
|
// ui/src/iiif/Scroll.jsx
|
|
1483
|
-
import
|
|
1803
|
+
import React21, { useEffect as useEffect4, useState as useState4 } from "react";
|
|
1484
1804
|
var Scroll = (props) => {
|
|
1485
1805
|
const [CloverScroll, setCloverScroll] = useState4(null);
|
|
1486
1806
|
useEffect4(() => {
|
|
@@ -1505,7 +1825,7 @@ var Scroll = (props) => {
|
|
|
1505
1825
|
} catch (_) {
|
|
1506
1826
|
json = "{}";
|
|
1507
1827
|
}
|
|
1508
|
-
return /* @__PURE__ */
|
|
1828
|
+
return /* @__PURE__ */ React21.createElement("div", { "data-canopy-scroll": "1", className: "not-prose" }, /* @__PURE__ */ React21.createElement(
|
|
1509
1829
|
"script",
|
|
1510
1830
|
{
|
|
1511
1831
|
type: "application/json",
|
|
@@ -1513,11 +1833,11 @@ var Scroll = (props) => {
|
|
|
1513
1833
|
}
|
|
1514
1834
|
));
|
|
1515
1835
|
}
|
|
1516
|
-
return /* @__PURE__ */
|
|
1836
|
+
return /* @__PURE__ */ React21.createElement(CloverScroll, { ...props });
|
|
1517
1837
|
};
|
|
1518
1838
|
|
|
1519
1839
|
// ui/src/iiif/Image.jsx
|
|
1520
|
-
import
|
|
1840
|
+
import React22, { useEffect as useEffect5, useState as useState5 } from "react";
|
|
1521
1841
|
var Image = (props = {}) => {
|
|
1522
1842
|
const [CloverImage, setCloverImage] = useState5(null);
|
|
1523
1843
|
const baseClass = "canopy-iiif-image";
|
|
@@ -1550,7 +1870,7 @@ var Image = (props = {}) => {
|
|
|
1550
1870
|
} catch (_) {
|
|
1551
1871
|
json = "{}";
|
|
1552
1872
|
}
|
|
1553
|
-
return /* @__PURE__ */
|
|
1873
|
+
return /* @__PURE__ */ React22.createElement("figure", { className: rootClassName }, /* @__PURE__ */ React22.createElement(
|
|
1554
1874
|
"div",
|
|
1555
1875
|
{
|
|
1556
1876
|
className: `${baseClass}__placeholder`,
|
|
@@ -1560,26 +1880,26 @@ var Image = (props = {}) => {
|
|
|
1560
1880
|
"--canopy-iiif-image-bg": backgroundColor
|
|
1561
1881
|
}
|
|
1562
1882
|
},
|
|
1563
|
-
/* @__PURE__ */
|
|
1883
|
+
/* @__PURE__ */ React22.createElement(
|
|
1564
1884
|
"script",
|
|
1565
1885
|
{
|
|
1566
1886
|
type: "application/json",
|
|
1567
1887
|
dangerouslySetInnerHTML: { __html: json }
|
|
1568
1888
|
}
|
|
1569
1889
|
)
|
|
1570
|
-
), caption && /* @__PURE__ */
|
|
1890
|
+
), caption && /* @__PURE__ */ React22.createElement("figcaption", { className: `${baseClass}__caption` }, caption));
|
|
1571
1891
|
}
|
|
1572
|
-
return /* @__PURE__ */
|
|
1892
|
+
return /* @__PURE__ */ React22.createElement(CloverImage, { ...props, className: rootClassName });
|
|
1573
1893
|
};
|
|
1574
1894
|
|
|
1575
1895
|
// ui/src/iiif/Properties/Id.jsx
|
|
1576
|
-
import
|
|
1896
|
+
import React23 from "react";
|
|
1577
1897
|
function Id({ title = "IIIF Manifest", id, ...props }) {
|
|
1578
|
-
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)));
|
|
1579
1899
|
}
|
|
1580
1900
|
|
|
1581
1901
|
// ui/src/iiif/MdxRelatedItems.jsx
|
|
1582
|
-
import
|
|
1902
|
+
import React24 from "react";
|
|
1583
1903
|
function MdxRelatedItems(props) {
|
|
1584
1904
|
let json = "{}";
|
|
1585
1905
|
try {
|
|
@@ -1587,7 +1907,7 @@ function MdxRelatedItems(props) {
|
|
|
1587
1907
|
} catch (_) {
|
|
1588
1908
|
json = "{}";
|
|
1589
1909
|
}
|
|
1590
|
-
return /* @__PURE__ */
|
|
1910
|
+
return /* @__PURE__ */ React24.createElement("div", { "data-canopy-related-items": "1" }, /* @__PURE__ */ React24.createElement(
|
|
1591
1911
|
"script",
|
|
1592
1912
|
{
|
|
1593
1913
|
type: "application/json",
|
|
@@ -1597,7 +1917,7 @@ function MdxRelatedItems(props) {
|
|
|
1597
1917
|
}
|
|
1598
1918
|
|
|
1599
1919
|
// ui/src/search/MdxSearchResults.jsx
|
|
1600
|
-
import
|
|
1920
|
+
import React25 from "react";
|
|
1601
1921
|
function MdxSearchResults(props) {
|
|
1602
1922
|
let json = "{}";
|
|
1603
1923
|
try {
|
|
@@ -1605,11 +1925,11 @@ function MdxSearchResults(props) {
|
|
|
1605
1925
|
} catch (_) {
|
|
1606
1926
|
json = "{}";
|
|
1607
1927
|
}
|
|
1608
|
-
return /* @__PURE__ */
|
|
1928
|
+
return /* @__PURE__ */ React25.createElement("div", { "data-canopy-search-results": "1" }, /* @__PURE__ */ React25.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
1609
1929
|
}
|
|
1610
1930
|
|
|
1611
1931
|
// ui/src/search/SearchSummary.jsx
|
|
1612
|
-
import
|
|
1932
|
+
import React26 from "react";
|
|
1613
1933
|
function SearchSummary(props) {
|
|
1614
1934
|
let json = "{}";
|
|
1615
1935
|
try {
|
|
@@ -1617,11 +1937,11 @@ function SearchSummary(props) {
|
|
|
1617
1937
|
} catch (_) {
|
|
1618
1938
|
json = "{}";
|
|
1619
1939
|
}
|
|
1620
|
-
return /* @__PURE__ */
|
|
1940
|
+
return /* @__PURE__ */ React26.createElement("div", { "data-canopy-search-summary": "1" }, /* @__PURE__ */ React26.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
1621
1941
|
}
|
|
1622
1942
|
|
|
1623
1943
|
// ui/src/search/MdxSearchTabs.jsx
|
|
1624
|
-
import
|
|
1944
|
+
import React27 from "react";
|
|
1625
1945
|
function MdxSearchTabs(props) {
|
|
1626
1946
|
let json = "{}";
|
|
1627
1947
|
try {
|
|
@@ -1629,11 +1949,11 @@ function MdxSearchTabs(props) {
|
|
|
1629
1949
|
} catch (_) {
|
|
1630
1950
|
json = "{}";
|
|
1631
1951
|
}
|
|
1632
|
-
return /* @__PURE__ */
|
|
1952
|
+
return /* @__PURE__ */ React27.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React27.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
1633
1953
|
}
|
|
1634
1954
|
|
|
1635
1955
|
// ui/src/search/MdxSearch.jsx
|
|
1636
|
-
import
|
|
1956
|
+
import React28 from "react";
|
|
1637
1957
|
function MdxSearch(props = {}) {
|
|
1638
1958
|
const {
|
|
1639
1959
|
layout,
|
|
@@ -1651,15 +1971,15 @@ function MdxSearch(props = {}) {
|
|
|
1651
1971
|
resultsPayload.layout = layout;
|
|
1652
1972
|
}
|
|
1653
1973
|
const classes = ["canopy-search", className].filter(Boolean).join(" ");
|
|
1654
|
-
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);
|
|
1655
1975
|
}
|
|
1656
1976
|
|
|
1657
1977
|
// ui/src/search/SearchResults.jsx
|
|
1658
|
-
import
|
|
1978
|
+
import React29 from "react";
|
|
1659
1979
|
function DefaultArticleTemplate({ record, query }) {
|
|
1660
1980
|
if (!record) return null;
|
|
1661
1981
|
const metadata = Array.isArray(record.metadata) ? record.metadata : [];
|
|
1662
|
-
return /* @__PURE__ */
|
|
1982
|
+
return /* @__PURE__ */ React29.createElement(
|
|
1663
1983
|
ArticleCard,
|
|
1664
1984
|
{
|
|
1665
1985
|
href: record.href,
|
|
@@ -1677,7 +1997,7 @@ function DefaultFigureTemplate({ record, thumbnailAspectRatio }) {
|
|
|
1677
1997
|
if (!record) return null;
|
|
1678
1998
|
const hasDims = Number.isFinite(Number(record.thumbnailWidth)) && Number(record.thumbnailWidth) > 0 && Number.isFinite(Number(record.thumbnailHeight)) && Number(record.thumbnailHeight) > 0;
|
|
1679
1999
|
const aspect = Number.isFinite(Number(thumbnailAspectRatio)) && Number(thumbnailAspectRatio) > 0 ? Number(thumbnailAspectRatio) : hasDims ? Number(record.thumbnailWidth) / Number(record.thumbnailHeight) : void 0;
|
|
1680
|
-
return /* @__PURE__ */
|
|
2000
|
+
return /* @__PURE__ */ React29.createElement(
|
|
1681
2001
|
Card,
|
|
1682
2002
|
{
|
|
1683
2003
|
href: record.href,
|
|
@@ -1698,7 +2018,7 @@ function SearchResults({
|
|
|
1698
2018
|
variant = "auto"
|
|
1699
2019
|
}) {
|
|
1700
2020
|
if (!results.length) {
|
|
1701
|
-
return /* @__PURE__ */
|
|
2021
|
+
return /* @__PURE__ */ React29.createElement("div", { className: "text-slate-600" }, /* @__PURE__ */ React29.createElement("em", null, "No results"));
|
|
1702
2022
|
}
|
|
1703
2023
|
const normalizedType = String(type || "all").toLowerCase();
|
|
1704
2024
|
const normalizedVariant = variant === "figure" || variant === "article" ? variant : "auto";
|
|
@@ -1706,9 +2026,9 @@ function SearchResults({
|
|
|
1706
2026
|
const FigureTemplate = templates && templates.figure ? templates.figure : DefaultFigureTemplate;
|
|
1707
2027
|
const ArticleTemplate = templates && templates.article ? templates.article : DefaultArticleTemplate;
|
|
1708
2028
|
if (isAnnotationView) {
|
|
1709
|
-
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) => {
|
|
1710
2030
|
if (!r) return null;
|
|
1711
|
-
return /* @__PURE__ */
|
|
2031
|
+
return /* @__PURE__ */ React29.createElement(
|
|
1712
2032
|
ArticleTemplate,
|
|
1713
2033
|
{
|
|
1714
2034
|
key: r.id || i,
|
|
@@ -1726,20 +2046,20 @@ function SearchResults({
|
|
|
1726
2046
|
return !isWorkRecord(record) || normalizedType !== "work";
|
|
1727
2047
|
};
|
|
1728
2048
|
if (layout === "list") {
|
|
1729
|
-
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) => {
|
|
1730
2050
|
if (shouldRenderAsArticle(r)) {
|
|
1731
|
-
return /* @__PURE__ */
|
|
2051
|
+
return /* @__PURE__ */ React29.createElement("div", { key: i, className: `search-result ${r && r.type}` }, /* @__PURE__ */ React29.createElement(ArticleTemplate, { record: r, query, layout }));
|
|
1732
2052
|
}
|
|
1733
2053
|
const hasDims = Number.isFinite(Number(r.thumbnailWidth)) && Number(r.thumbnailWidth) > 0 && Number.isFinite(Number(r.thumbnailHeight)) && Number(r.thumbnailHeight) > 0;
|
|
1734
2054
|
const aspect = hasDims ? Number(r.thumbnailWidth) / Number(r.thumbnailHeight) : void 0;
|
|
1735
|
-
return /* @__PURE__ */
|
|
2055
|
+
return /* @__PURE__ */ React29.createElement(
|
|
1736
2056
|
"div",
|
|
1737
2057
|
{
|
|
1738
2058
|
key: i,
|
|
1739
2059
|
className: `search-result ${r.type}`,
|
|
1740
2060
|
"data-thumbnail-aspect-ratio": aspect
|
|
1741
2061
|
},
|
|
1742
|
-
/* @__PURE__ */
|
|
2062
|
+
/* @__PURE__ */ React29.createElement(
|
|
1743
2063
|
FigureTemplate,
|
|
1744
2064
|
{
|
|
1745
2065
|
record: r,
|
|
@@ -1751,20 +2071,20 @@ function SearchResults({
|
|
|
1751
2071
|
);
|
|
1752
2072
|
}));
|
|
1753
2073
|
}
|
|
1754
|
-
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) => {
|
|
1755
2075
|
if (shouldRenderAsArticle(r)) {
|
|
1756
|
-
return /* @__PURE__ */
|
|
2076
|
+
return /* @__PURE__ */ React29.createElement(GridItem, { key: i, className: `search-result ${r && r.type}` }, /* @__PURE__ */ React29.createElement(ArticleTemplate, { record: r, query, layout }));
|
|
1757
2077
|
}
|
|
1758
2078
|
const hasDims = Number.isFinite(Number(r.thumbnailWidth)) && Number(r.thumbnailWidth) > 0 && Number.isFinite(Number(r.thumbnailHeight)) && Number(r.thumbnailHeight) > 0;
|
|
1759
2079
|
const aspect = hasDims ? Number(r.thumbnailWidth) / Number(r.thumbnailHeight) : void 0;
|
|
1760
|
-
return /* @__PURE__ */
|
|
2080
|
+
return /* @__PURE__ */ React29.createElement(
|
|
1761
2081
|
GridItem,
|
|
1762
2082
|
{
|
|
1763
2083
|
key: i,
|
|
1764
2084
|
className: `search-result ${r.type}`,
|
|
1765
2085
|
"data-thumbnail-aspect-ratio": aspect
|
|
1766
2086
|
},
|
|
1767
|
-
/* @__PURE__ */
|
|
2087
|
+
/* @__PURE__ */ React29.createElement(
|
|
1768
2088
|
FigureTemplate,
|
|
1769
2089
|
{
|
|
1770
2090
|
record: r,
|
|
@@ -1778,7 +2098,7 @@ function SearchResults({
|
|
|
1778
2098
|
}
|
|
1779
2099
|
|
|
1780
2100
|
// ui/src/search/SearchTabs.jsx
|
|
1781
|
-
import
|
|
2101
|
+
import React30, { useRef as useRef2, useState as useState6, useEffect as useEffect6 } from "react";
|
|
1782
2102
|
function SearchTabs({
|
|
1783
2103
|
type = "all",
|
|
1784
2104
|
onTypeChange,
|
|
@@ -1832,7 +2152,7 @@ function SearchTabs({
|
|
|
1832
2152
|
width: `${itemBoundingBox.width}px`
|
|
1833
2153
|
};
|
|
1834
2154
|
}
|
|
1835
|
-
return /* @__PURE__ */
|
|
2155
|
+
return /* @__PURE__ */ React30.createElement("div", { className: "canopy-search-tabs-wrapper" }, /* @__PURE__ */ React30.createElement(
|
|
1836
2156
|
"div",
|
|
1837
2157
|
{
|
|
1838
2158
|
role: "tablist",
|
|
@@ -1841,7 +2161,7 @@ function SearchTabs({
|
|
|
1841
2161
|
ref: wrapperRef,
|
|
1842
2162
|
onMouseLeave: resetHighlight
|
|
1843
2163
|
},
|
|
1844
|
-
/* @__PURE__ */
|
|
2164
|
+
/* @__PURE__ */ React30.createElement(
|
|
1845
2165
|
"div",
|
|
1846
2166
|
{
|
|
1847
2167
|
ref: highlightRef,
|
|
@@ -1853,7 +2173,7 @@ function SearchTabs({
|
|
|
1853
2173
|
const active = String(type).toLowerCase() === String(t).toLowerCase();
|
|
1854
2174
|
const cRaw = counts && Object.prototype.hasOwnProperty.call(counts, t) ? counts[t] : void 0;
|
|
1855
2175
|
const c = Number.isFinite(Number(cRaw)) ? Number(cRaw) : 0;
|
|
1856
|
-
return /* @__PURE__ */
|
|
2176
|
+
return /* @__PURE__ */ React30.createElement(
|
|
1857
2177
|
"button",
|
|
1858
2178
|
{
|
|
1859
2179
|
key: t,
|
|
@@ -1871,7 +2191,7 @@ function SearchTabs({
|
|
|
1871
2191
|
")"
|
|
1872
2192
|
);
|
|
1873
2193
|
})
|
|
1874
|
-
), hasFilters ? /* @__PURE__ */
|
|
2194
|
+
), hasFilters ? /* @__PURE__ */ React30.createElement(
|
|
1875
2195
|
"button",
|
|
1876
2196
|
{
|
|
1877
2197
|
type: "button",
|
|
@@ -1879,12 +2199,12 @@ function SearchTabs({
|
|
|
1879
2199
|
"aria-expanded": filtersOpen ? "true" : "false",
|
|
1880
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"
|
|
1881
2201
|
},
|
|
1882
|
-
/* @__PURE__ */
|
|
2202
|
+
/* @__PURE__ */ React30.createElement("span", null, filtersLabel, filterBadge)
|
|
1883
2203
|
) : null);
|
|
1884
2204
|
}
|
|
1885
2205
|
|
|
1886
2206
|
// ui/src/search/SearchFiltersDialog.jsx
|
|
1887
|
-
import
|
|
2207
|
+
import React31 from "react";
|
|
1888
2208
|
function toArray(input) {
|
|
1889
2209
|
if (!input) return [];
|
|
1890
2210
|
if (Array.isArray(input)) return input;
|
|
@@ -1923,20 +2243,20 @@ function FacetSection({ facet, selected, onToggle }) {
|
|
|
1923
2243
|
const selectedValues = selected.get(String(slug)) || /* @__PURE__ */ new Set();
|
|
1924
2244
|
const checkboxId = (valueSlug) => `filter-${slug}-${valueSlug}`;
|
|
1925
2245
|
const hasSelection = selectedValues.size > 0;
|
|
1926
|
-
const [quickQuery, setQuickQuery] =
|
|
2246
|
+
const [quickQuery, setQuickQuery] = React31.useState("");
|
|
1927
2247
|
const hasQuery = quickQuery.trim().length > 0;
|
|
1928
|
-
const filteredValues =
|
|
2248
|
+
const filteredValues = React31.useMemo(
|
|
1929
2249
|
() => facetMatches(values, quickQuery),
|
|
1930
2250
|
[values, quickQuery]
|
|
1931
2251
|
);
|
|
1932
|
-
return /* @__PURE__ */
|
|
2252
|
+
return /* @__PURE__ */ React31.createElement(
|
|
1933
2253
|
"details",
|
|
1934
2254
|
{
|
|
1935
2255
|
className: "canopy-search-filters__facet",
|
|
1936
2256
|
open: hasSelection
|
|
1937
2257
|
},
|
|
1938
|
-
/* @__PURE__ */
|
|
1939
|
-
/* @__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(
|
|
1940
2260
|
"input",
|
|
1941
2261
|
{
|
|
1942
2262
|
type: "search",
|
|
@@ -1946,7 +2266,7 @@ function FacetSection({ facet, selected, onToggle }) {
|
|
|
1946
2266
|
className: "canopy-search-filters__quick-input",
|
|
1947
2267
|
"aria-label": `Filter ${label} values`
|
|
1948
2268
|
}
|
|
1949
|
-
), quickQuery ? /* @__PURE__ */
|
|
2269
|
+
), quickQuery ? /* @__PURE__ */ React31.createElement(
|
|
1950
2270
|
"button",
|
|
1951
2271
|
{
|
|
1952
2272
|
type: "button",
|
|
@@ -1955,11 +2275,11 @@ function FacetSection({ facet, selected, onToggle }) {
|
|
|
1955
2275
|
"aria-label": `Clear ${label} filter search`
|
|
1956
2276
|
},
|
|
1957
2277
|
"Clear"
|
|
1958
|
-
) : 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) => {
|
|
1959
2279
|
const valueSlug = String(entry.slug || entry.value || "");
|
|
1960
2280
|
const isChecked = selectedValues.has(valueSlug);
|
|
1961
2281
|
const inputId = checkboxId(valueSlug);
|
|
1962
|
-
return /* @__PURE__ */
|
|
2282
|
+
return /* @__PURE__ */ React31.createElement("li", { key: valueSlug, className: "canopy-search-filters__facet-item" }, /* @__PURE__ */ React31.createElement(
|
|
1963
2283
|
"input",
|
|
1964
2284
|
{
|
|
1965
2285
|
id: inputId,
|
|
@@ -1971,15 +2291,15 @@ function FacetSection({ facet, selected, onToggle }) {
|
|
|
1971
2291
|
if (onToggle) onToggle(slug, valueSlug, nextChecked);
|
|
1972
2292
|
}
|
|
1973
2293
|
}
|
|
1974
|
-
), /* @__PURE__ */
|
|
2294
|
+
), /* @__PURE__ */ React31.createElement(
|
|
1975
2295
|
"label",
|
|
1976
2296
|
{
|
|
1977
2297
|
htmlFor: inputId,
|
|
1978
2298
|
className: "canopy-search-filters__facet-label"
|
|
1979
2299
|
},
|
|
1980
|
-
/* @__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)
|
|
1981
2301
|
));
|
|
1982
|
-
}), !filteredValues.length && !hasQuery ? /* @__PURE__ */
|
|
2302
|
+
}), !filteredValues.length && !hasQuery ? /* @__PURE__ */ React31.createElement("li", { className: "canopy-search-filters__facet-empty" }, "No values available.") : null))
|
|
1983
2303
|
);
|
|
1984
2304
|
}
|
|
1985
2305
|
function SearchFiltersDialog(props = {}) {
|
|
@@ -2001,7 +2321,7 @@ function SearchFiltersDialog(props = {}) {
|
|
|
2001
2321
|
(total, set) => total + set.size,
|
|
2002
2322
|
0
|
|
2003
2323
|
);
|
|
2004
|
-
|
|
2324
|
+
React31.useEffect(() => {
|
|
2005
2325
|
if (!open) return void 0;
|
|
2006
2326
|
if (typeof document === "undefined") return void 0;
|
|
2007
2327
|
const body = document.body;
|
|
@@ -2018,7 +2338,7 @@ function SearchFiltersDialog(props = {}) {
|
|
|
2018
2338
|
if (!open) return null;
|
|
2019
2339
|
const brandId = "canopy-modal-filters-label";
|
|
2020
2340
|
const subtitleText = subtitle != null ? subtitle : title;
|
|
2021
|
-
return /* @__PURE__ */
|
|
2341
|
+
return /* @__PURE__ */ React31.createElement(
|
|
2022
2342
|
CanopyModal,
|
|
2023
2343
|
{
|
|
2024
2344
|
id: "canopy-modal-filters",
|
|
@@ -2033,8 +2353,8 @@ function SearchFiltersDialog(props = {}) {
|
|
|
2033
2353
|
onBackgroundClick: () => onOpenChange && onOpenChange(false),
|
|
2034
2354
|
bodyClassName: "canopy-modal__body--filters"
|
|
2035
2355
|
},
|
|
2036
|
-
subtitleText ? /* @__PURE__ */
|
|
2037
|
-
/* @__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(
|
|
2038
2358
|
FacetSection,
|
|
2039
2359
|
{
|
|
2040
2360
|
key: facet.slug || facet.label,
|
|
@@ -2042,8 +2362,8 @@ function SearchFiltersDialog(props = {}) {
|
|
|
2042
2362
|
selected: selectedMap,
|
|
2043
2363
|
onToggle
|
|
2044
2364
|
}
|
|
2045
|
-
))) : /* @__PURE__ */
|
|
2046
|
-
/* @__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(
|
|
2047
2367
|
"button",
|
|
2048
2368
|
{
|
|
2049
2369
|
type: "button",
|
|
@@ -2054,7 +2374,7 @@ function SearchFiltersDialog(props = {}) {
|
|
|
2054
2374
|
className: "canopy-search-filters__button canopy-search-filters__button--secondary"
|
|
2055
2375
|
},
|
|
2056
2376
|
"Clear all"
|
|
2057
|
-
), /* @__PURE__ */
|
|
2377
|
+
), /* @__PURE__ */ React31.createElement(
|
|
2058
2378
|
"button",
|
|
2059
2379
|
{
|
|
2060
2380
|
type: "button",
|
|
@@ -2067,7 +2387,7 @@ function SearchFiltersDialog(props = {}) {
|
|
|
2067
2387
|
}
|
|
2068
2388
|
|
|
2069
2389
|
// ui/src/search-form/MdxSearchFormModal.jsx
|
|
2070
|
-
import
|
|
2390
|
+
import React32 from "react";
|
|
2071
2391
|
function MdxSearchFormModal(props = {}) {
|
|
2072
2392
|
const {
|
|
2073
2393
|
placeholder = "Search\u2026",
|
|
@@ -2083,24 +2403,24 @@ function MdxSearchFormModal(props = {}) {
|
|
|
2083
2403
|
const text = typeof label === "string" && label.trim() ? label.trim() : buttonLabel;
|
|
2084
2404
|
const resolvedSearchPath = resolveSearchPath(searchPath);
|
|
2085
2405
|
const data = { placeholder, hotkey, maxResults, groupOrder, label: text, searchPath: resolvedSearchPath };
|
|
2086
|
-
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) } }));
|
|
2087
2407
|
}
|
|
2088
2408
|
|
|
2089
2409
|
// ui/src/docs/MarkdownTable.jsx
|
|
2090
|
-
import
|
|
2410
|
+
import React33 from "react";
|
|
2091
2411
|
function MarkdownTable({ className = "", ...rest }) {
|
|
2092
2412
|
const merged = ["markdown-table", className].filter(Boolean).join(" ");
|
|
2093
|
-
return /* @__PURE__ */
|
|
2413
|
+
return /* @__PURE__ */ React33.createElement("div", { className: "markdown-table__frame" }, /* @__PURE__ */ React33.createElement("table", { className: merged, ...rest }));
|
|
2094
2414
|
}
|
|
2095
2415
|
|
|
2096
2416
|
// ui/src/docs/Diagram.jsx
|
|
2097
|
-
import
|
|
2417
|
+
import React34 from "react";
|
|
2098
2418
|
function CanopyDiagram() {
|
|
2099
|
-
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"))))));
|
|
2100
2420
|
}
|
|
2101
2421
|
|
|
2102
2422
|
// ui/src/content/timeline/Timeline.jsx
|
|
2103
|
-
import
|
|
2423
|
+
import React36 from "react";
|
|
2104
2424
|
|
|
2105
2425
|
// ui/src/content/timeline/date-utils.js
|
|
2106
2426
|
var FALLBACK_LOCALE = (() => {
|
|
@@ -2253,7 +2573,7 @@ function clampProgress(value) {
|
|
|
2253
2573
|
}
|
|
2254
2574
|
|
|
2255
2575
|
// ui/src/layout/ReferencedManifestCard.jsx
|
|
2256
|
-
import
|
|
2576
|
+
import React35 from "react";
|
|
2257
2577
|
function normalizeMetadata(metadata, summary) {
|
|
2258
2578
|
if (Array.isArray(metadata) && metadata.length) {
|
|
2259
2579
|
return metadata.filter(Boolean);
|
|
@@ -2287,7 +2607,7 @@ function ReferencedManifestCard({
|
|
|
2287
2607
|
"canopy-referenced-manifest-card",
|
|
2288
2608
|
className
|
|
2289
2609
|
].filter(Boolean).join(" ");
|
|
2290
|
-
return /* @__PURE__ */
|
|
2610
|
+
return /* @__PURE__ */ React35.createElement(
|
|
2291
2611
|
TeaserCard,
|
|
2292
2612
|
{
|
|
2293
2613
|
href: resolvedHref || void 0,
|
|
@@ -2469,14 +2789,14 @@ function TimelineConnector({ side, isActive, highlight }) {
|
|
|
2469
2789
|
"canopy-timeline__connector-dot",
|
|
2470
2790
|
highlight || isActive ? "is-active" : ""
|
|
2471
2791
|
].filter(Boolean).join(" ");
|
|
2472
|
-
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" })));
|
|
2473
2793
|
}
|
|
2474
2794
|
function renderResourceSection(point) {
|
|
2475
2795
|
if (!point) return null;
|
|
2476
2796
|
const manifestCards = Array.isArray(point.manifests) ? point.manifests.filter(Boolean) : [];
|
|
2477
2797
|
const legacyResources = Array.isArray(point.resources) ? point.resources.filter(Boolean) : [];
|
|
2478
2798
|
if (!manifestCards.length && !legacyResources.length) return null;
|
|
2479
|
-
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(
|
|
2480
2800
|
TeaserCard,
|
|
2481
2801
|
{
|
|
2482
2802
|
href: resource.href,
|
|
@@ -2501,26 +2821,26 @@ function Timeline({
|
|
|
2501
2821
|
...rest
|
|
2502
2822
|
}) {
|
|
2503
2823
|
const payloadPoints = payload && Array.isArray(payload.points) ? payload.points : null;
|
|
2504
|
-
const rawPoints =
|
|
2824
|
+
const rawPoints = React36.useMemo(() => {
|
|
2505
2825
|
if (Array.isArray(pointsProp) && pointsProp.length) return pointsProp;
|
|
2506
2826
|
if (payloadPoints && payloadPoints.length) return payloadPoints;
|
|
2507
2827
|
return [];
|
|
2508
2828
|
}, [pointsProp, payloadPoints]);
|
|
2509
|
-
const sanitizedPoints =
|
|
2829
|
+
const sanitizedPoints = React36.useMemo(
|
|
2510
2830
|
() => sanitizePoints(rawPoints),
|
|
2511
2831
|
[rawPoints]
|
|
2512
2832
|
);
|
|
2513
2833
|
const localeValue = payload && payload.locale ? payload.locale : localeProp;
|
|
2514
|
-
const baseLocale =
|
|
2834
|
+
const baseLocale = React36.useMemo(
|
|
2515
2835
|
() => createLocale(localeValue),
|
|
2516
2836
|
[localeValue]
|
|
2517
2837
|
);
|
|
2518
2838
|
const rangeInput = payload && payload.range ? payload.range : rangeProp || {};
|
|
2519
|
-
const rangeOverrides =
|
|
2839
|
+
const rangeOverrides = React36.useMemo(
|
|
2520
2840
|
() => deriveRangeOverrides(sanitizedPoints, rangeInput),
|
|
2521
2841
|
[sanitizedPoints, rangeInput]
|
|
2522
2842
|
);
|
|
2523
|
-
const effectiveRange =
|
|
2843
|
+
const effectiveRange = React36.useMemo(
|
|
2524
2844
|
() => normalizeRange({
|
|
2525
2845
|
...rangeOverrides,
|
|
2526
2846
|
locale: baseLocale
|
|
@@ -2529,7 +2849,7 @@ function Timeline({
|
|
|
2529
2849
|
);
|
|
2530
2850
|
const spanStart = effectiveRange.startDate.getTime();
|
|
2531
2851
|
const span = effectiveRange.span;
|
|
2532
|
-
const pointsWithPosition =
|
|
2852
|
+
const pointsWithPosition = React36.useMemo(() => {
|
|
2533
2853
|
if (!sanitizedPoints.length) return [];
|
|
2534
2854
|
return sanitizedPoints.map((point, index) => {
|
|
2535
2855
|
const timestamp = point.meta.timestamp;
|
|
@@ -2543,29 +2863,29 @@ function Timeline({
|
|
|
2543
2863
|
};
|
|
2544
2864
|
});
|
|
2545
2865
|
}, [sanitizedPoints, spanStart, span]);
|
|
2546
|
-
const [activeId, setActiveId] =
|
|
2866
|
+
const [activeId, setActiveId] = React36.useState(
|
|
2547
2867
|
() => getActivePointId(pointsWithPosition)
|
|
2548
2868
|
);
|
|
2549
|
-
|
|
2869
|
+
React36.useEffect(() => {
|
|
2550
2870
|
setActiveId(getActivePointId(pointsWithPosition));
|
|
2551
2871
|
}, [pointsWithPosition]);
|
|
2552
2872
|
const thresholdValue = typeof thresholdProp === "number" ? thresholdProp : payload && payload.threshold != null ? payload.threshold : null;
|
|
2553
2873
|
const stepsValue = typeof steps === "number" ? Number(steps) : payload && typeof payload.steps === "number" ? Number(payload.steps) : null;
|
|
2554
|
-
const thresholdMs =
|
|
2874
|
+
const thresholdMs = React36.useMemo(
|
|
2555
2875
|
() => getThresholdMs(thresholdValue, effectiveRange.granularity),
|
|
2556
2876
|
[thresholdValue, effectiveRange.granularity]
|
|
2557
2877
|
);
|
|
2558
|
-
const groupedEntries =
|
|
2878
|
+
const groupedEntries = React36.useMemo(
|
|
2559
2879
|
() => buildGroupedEntries(pointsWithPosition, thresholdMs, {
|
|
2560
2880
|
granularity: effectiveRange.granularity,
|
|
2561
2881
|
locale: baseLocale
|
|
2562
2882
|
}),
|
|
2563
2883
|
[pointsWithPosition, thresholdMs, effectiveRange.granularity, baseLocale]
|
|
2564
2884
|
);
|
|
2565
|
-
const [expandedGroupIds, setExpandedGroupIds] =
|
|
2885
|
+
const [expandedGroupIds, setExpandedGroupIds] = React36.useState(
|
|
2566
2886
|
() => /* @__PURE__ */ new Set()
|
|
2567
2887
|
);
|
|
2568
|
-
|
|
2888
|
+
React36.useEffect(() => {
|
|
2569
2889
|
setExpandedGroupIds((prev) => {
|
|
2570
2890
|
if (!prev || prev.size === 0) return prev;
|
|
2571
2891
|
const validIds = new Set(
|
|
@@ -2580,7 +2900,7 @@ function Timeline({
|
|
|
2580
2900
|
return changed ? next : prev;
|
|
2581
2901
|
});
|
|
2582
2902
|
}, [groupedEntries]);
|
|
2583
|
-
const toggleGroup =
|
|
2903
|
+
const toggleGroup = React36.useCallback((groupId) => {
|
|
2584
2904
|
setExpandedGroupIds((prev) => {
|
|
2585
2905
|
const next = new Set(prev || []);
|
|
2586
2906
|
if (next.has(groupId)) next.delete(groupId);
|
|
@@ -2603,7 +2923,7 @@ function Timeline({
|
|
|
2603
2923
|
point.id === activeId ? "is-active" : "",
|
|
2604
2924
|
point.highlight ? "is-highlighted" : ""
|
|
2605
2925
|
].filter(Boolean).join(" ");
|
|
2606
|
-
const connector = /* @__PURE__ */
|
|
2926
|
+
const connector = /* @__PURE__ */ React36.createElement(
|
|
2607
2927
|
TimelineConnector,
|
|
2608
2928
|
{
|
|
2609
2929
|
side: point.side,
|
|
@@ -2611,9 +2931,9 @@ function Timeline({
|
|
|
2611
2931
|
highlight: point.highlight
|
|
2612
2932
|
}
|
|
2613
2933
|
);
|
|
2614
|
-
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);
|
|
2615
2935
|
const resourceSection = renderResourceSection(point);
|
|
2616
|
-
return /* @__PURE__ */
|
|
2936
|
+
return /* @__PURE__ */ React36.createElement(
|
|
2617
2937
|
"div",
|
|
2618
2938
|
{
|
|
2619
2939
|
key: point.id,
|
|
@@ -2621,7 +2941,7 @@ function Timeline({
|
|
|
2621
2941
|
style: wrapperStyle,
|
|
2622
2942
|
role: "listitem"
|
|
2623
2943
|
},
|
|
2624
|
-
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))
|
|
2625
2945
|
);
|
|
2626
2946
|
}
|
|
2627
2947
|
function renderGroupEntry(entry) {
|
|
@@ -2632,7 +2952,7 @@ function Timeline({
|
|
|
2632
2952
|
const wrapperStyle = { top: `${entry.progress * 100}%` };
|
|
2633
2953
|
const isExpanded = expandedGroupIds.has(entry.id);
|
|
2634
2954
|
const hasActivePoint = entry.points.some((point) => point.id === activeId);
|
|
2635
|
-
const connector = /* @__PURE__ */
|
|
2955
|
+
const connector = /* @__PURE__ */ React36.createElement(
|
|
2636
2956
|
TimelineConnector,
|
|
2637
2957
|
{
|
|
2638
2958
|
side: entry.side,
|
|
@@ -2646,7 +2966,7 @@ function Timeline({
|
|
|
2646
2966
|
hasActivePoint ? "is-active" : ""
|
|
2647
2967
|
].filter(Boolean).join(" ");
|
|
2648
2968
|
const countLabel = `${entry.count} event${entry.count > 1 ? "s" : ""}`;
|
|
2649
|
-
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(
|
|
2650
2970
|
"button",
|
|
2651
2971
|
{
|
|
2652
2972
|
type: "button",
|
|
@@ -2656,7 +2976,7 @@ function Timeline({
|
|
|
2656
2976
|
},
|
|
2657
2977
|
isExpanded ? "Hide details" : "Show details"
|
|
2658
2978
|
));
|
|
2659
|
-
const groupPoints = isExpanded ? /* @__PURE__ */
|
|
2979
|
+
const groupPoints = isExpanded ? /* @__PURE__ */ React36.createElement("div", { className: "canopy-timeline__group-points" }, entry.points.map((point) => /* @__PURE__ */ React36.createElement(
|
|
2660
2980
|
"button",
|
|
2661
2981
|
{
|
|
2662
2982
|
key: point.id,
|
|
@@ -2667,11 +2987,11 @@ function Timeline({
|
|
|
2667
2987
|
].filter(Boolean).join(" "),
|
|
2668
2988
|
onClick: () => setActiveId(point.id)
|
|
2669
2989
|
},
|
|
2670
|
-
/* @__PURE__ */
|
|
2671
|
-
/* @__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)
|
|
2672
2992
|
))) : null;
|
|
2673
|
-
const groupCard = /* @__PURE__ */
|
|
2674
|
-
return /* @__PURE__ */
|
|
2993
|
+
const groupCard = /* @__PURE__ */ React36.createElement("div", { className: groupClasses }, header, groupPoints);
|
|
2994
|
+
return /* @__PURE__ */ React36.createElement(
|
|
2675
2995
|
"div",
|
|
2676
2996
|
{
|
|
2677
2997
|
key: entry.id,
|
|
@@ -2679,17 +2999,17 @@ function Timeline({
|
|
|
2679
2999
|
style: wrapperStyle,
|
|
2680
3000
|
role: "listitem"
|
|
2681
3001
|
},
|
|
2682
|
-
entry.side === "left" ? /* @__PURE__ */
|
|
3002
|
+
entry.side === "left" ? /* @__PURE__ */ React36.createElement(React36.Fragment, null, groupCard, connector) : /* @__PURE__ */ React36.createElement(React36.Fragment, null, connector, groupCard)
|
|
2683
3003
|
);
|
|
2684
3004
|
}
|
|
2685
|
-
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(
|
|
2686
3006
|
"div",
|
|
2687
3007
|
{
|
|
2688
3008
|
className: "canopy-timeline__list",
|
|
2689
3009
|
role: "list",
|
|
2690
3010
|
style: { minHeight: trackHeight }
|
|
2691
3011
|
},
|
|
2692
|
-
/* @__PURE__ */
|
|
3012
|
+
/* @__PURE__ */ React36.createElement("div", { className: "canopy-timeline__spine", "aria-hidden": "true" }),
|
|
2693
3013
|
renderSteps(stepsValue, effectiveRange),
|
|
2694
3014
|
groupedEntries.map((entry) => {
|
|
2695
3015
|
if (entry.type === "group") return renderGroupEntry(entry);
|
|
@@ -2704,7 +3024,7 @@ function renderSteps(stepSize, range) {
|
|
|
2704
3024
|
const markers = [];
|
|
2705
3025
|
if (startYear < endYear) {
|
|
2706
3026
|
markers.push(
|
|
2707
|
-
/* @__PURE__ */
|
|
3027
|
+
/* @__PURE__ */ React36.createElement(
|
|
2708
3028
|
"span",
|
|
2709
3029
|
{
|
|
2710
3030
|
key: "timeline-step-start",
|
|
@@ -2712,12 +3032,12 @@ function renderSteps(stepSize, range) {
|
|
|
2712
3032
|
style: { top: "0%" },
|
|
2713
3033
|
"aria-hidden": "true"
|
|
2714
3034
|
},
|
|
2715
|
-
/* @__PURE__ */
|
|
2716
|
-
/* @__PURE__ */
|
|
3035
|
+
/* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__step-line" }),
|
|
3036
|
+
/* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__step-label" }, startYear)
|
|
2717
3037
|
)
|
|
2718
3038
|
);
|
|
2719
3039
|
markers.push(
|
|
2720
|
-
/* @__PURE__ */
|
|
3040
|
+
/* @__PURE__ */ React36.createElement(
|
|
2721
3041
|
"span",
|
|
2722
3042
|
{
|
|
2723
3043
|
key: "timeline-step-end",
|
|
@@ -2725,8 +3045,8 @@ function renderSteps(stepSize, range) {
|
|
|
2725
3045
|
style: { top: "100%" },
|
|
2726
3046
|
"aria-hidden": "true"
|
|
2727
3047
|
},
|
|
2728
|
-
/* @__PURE__ */
|
|
2729
|
-
/* @__PURE__ */
|
|
3048
|
+
/* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__step-line" }),
|
|
3049
|
+
/* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__step-label" }, endYear)
|
|
2730
3050
|
)
|
|
2731
3051
|
);
|
|
2732
3052
|
}
|
|
@@ -2736,7 +3056,7 @@ function renderSteps(stepSize, range) {
|
|
|
2736
3056
|
const progress = (timestamp - range.startDate.getTime()) / range.span;
|
|
2737
3057
|
if (progress <= 0 || progress >= 1) continue;
|
|
2738
3058
|
markers.push(
|
|
2739
|
-
/* @__PURE__ */
|
|
3059
|
+
/* @__PURE__ */ React36.createElement(
|
|
2740
3060
|
"span",
|
|
2741
3061
|
{
|
|
2742
3062
|
key: `timeline-step-${year}`,
|
|
@@ -2744,8 +3064,8 @@ function renderSteps(stepSize, range) {
|
|
|
2744
3064
|
style: { top: `calc(${progress * 100}% - 0.5px)` },
|
|
2745
3065
|
"aria-hidden": "true"
|
|
2746
3066
|
},
|
|
2747
|
-
/* @__PURE__ */
|
|
2748
|
-
/* @__PURE__ */
|
|
3067
|
+
/* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__step-line" }),
|
|
3068
|
+
/* @__PURE__ */ React36.createElement("span", { className: "canopy-timeline__step-label" }, year)
|
|
2749
3069
|
)
|
|
2750
3070
|
);
|
|
2751
3071
|
}
|
|
@@ -2759,7 +3079,7 @@ function TimelinePoint() {
|
|
|
2759
3079
|
TimelinePoint.displayName = "TimelinePoint";
|
|
2760
3080
|
|
|
2761
3081
|
// ui/src/content/map/Map.jsx
|
|
2762
|
-
import
|
|
3082
|
+
import React37 from "react";
|
|
2763
3083
|
import { createRoot } from "react-dom/client";
|
|
2764
3084
|
var DEFAULT_TILE_LAYERS = [
|
|
2765
3085
|
{
|
|
@@ -3026,7 +3346,7 @@ function MapPopupContent({ marker }) {
|
|
|
3026
3346
|
...manifest,
|
|
3027
3347
|
href: manifest.href ? withBasePath(manifest.href) : manifest.href || ""
|
|
3028
3348
|
}));
|
|
3029
|
-
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(
|
|
3030
3350
|
"img",
|
|
3031
3351
|
{
|
|
3032
3352
|
src: thumbnail,
|
|
@@ -3035,19 +3355,19 @@ function MapPopupContent({ marker }) {
|
|
|
3035
3355
|
width: typeof thumbWidth === "number" && thumbWidth > 0 ? thumbWidth : void 0,
|
|
3036
3356
|
height: typeof thumbHeight === "number" && thumbHeight > 0 ? thumbHeight : void 0
|
|
3037
3357
|
}
|
|
3038
|
-
)) : 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(
|
|
3039
3359
|
"div",
|
|
3040
3360
|
{
|
|
3041
3361
|
className: "canopy-map__popup-details",
|
|
3042
3362
|
dangerouslySetInnerHTML: { __html: marker.detailsHtml }
|
|
3043
3363
|
}
|
|
3044
|
-
) : 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(
|
|
3045
3365
|
"div",
|
|
3046
3366
|
{
|
|
3047
3367
|
key: manifest.id || manifest.href || `manifest-${index}`,
|
|
3048
3368
|
className: "canopy-map__popup-manifests-item"
|
|
3049
3369
|
},
|
|
3050
|
-
/* @__PURE__ */
|
|
3370
|
+
/* @__PURE__ */ React37.createElement(ReferencedManifestCard, { manifest })
|
|
3051
3371
|
)))) : null));
|
|
3052
3372
|
}
|
|
3053
3373
|
function renderPopup(marker) {
|
|
@@ -3059,7 +3379,7 @@ function renderPopup(marker) {
|
|
|
3059
3379
|
if (hadError) return;
|
|
3060
3380
|
try {
|
|
3061
3381
|
if (!root) root = createRoot(container);
|
|
3062
|
-
root.render(/* @__PURE__ */
|
|
3382
|
+
root.render(/* @__PURE__ */ React37.createElement(MapPopupContent, { marker }));
|
|
3063
3383
|
} catch (error) {
|
|
3064
3384
|
hadError = true;
|
|
3065
3385
|
if (root) {
|
|
@@ -3184,26 +3504,26 @@ function Map2({
|
|
|
3184
3504
|
defaultCenter = null,
|
|
3185
3505
|
defaultZoom = null
|
|
3186
3506
|
} = {}) {
|
|
3187
|
-
const containerRef =
|
|
3188
|
-
const mapRef =
|
|
3189
|
-
const layerRef =
|
|
3190
|
-
const [leafletLib, setLeafletLib] =
|
|
3191
|
-
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);
|
|
3192
3512
|
const datasetInfo = navDataset && typeof navDataset === "object" ? navDataset : null;
|
|
3193
3513
|
const datasetHref = datasetInfo && datasetInfo.href || "/api/navplace.json";
|
|
3194
3514
|
const datasetVersion = datasetInfo && datasetInfo.version;
|
|
3195
3515
|
const datasetHasFeatures = !!(datasetInfo && datasetInfo.hasFeatures);
|
|
3196
|
-
const [navState, setNavState] =
|
|
3516
|
+
const [navState, setNavState] = React37.useState(() => ({
|
|
3197
3517
|
loading: false,
|
|
3198
3518
|
error: null,
|
|
3199
3519
|
markers: []
|
|
3200
3520
|
}));
|
|
3201
|
-
const [iiifTargets, setIiifTargets] =
|
|
3521
|
+
const [iiifTargets, setIiifTargets] = React37.useState(() => ({
|
|
3202
3522
|
loading: false,
|
|
3203
3523
|
error: null,
|
|
3204
3524
|
keys: []
|
|
3205
3525
|
}));
|
|
3206
|
-
|
|
3526
|
+
React37.useEffect(() => {
|
|
3207
3527
|
if (!iiifContent) {
|
|
3208
3528
|
setIiifTargets({ loading: false, error: null, keys: [] });
|
|
3209
3529
|
return;
|
|
@@ -3251,7 +3571,7 @@ function Map2({
|
|
|
3251
3571
|
const navTargets = iiifTargets.keys || [];
|
|
3252
3572
|
const navTargetsKey = navTargets.join("|");
|
|
3253
3573
|
const shouldFetchNav = datasetHasFeatures && navTargets.length > 0;
|
|
3254
|
-
|
|
3574
|
+
React37.useEffect(() => {
|
|
3255
3575
|
if (!shouldFetchNav) {
|
|
3256
3576
|
setNavState({ loading: false, error: null, markers: [] });
|
|
3257
3577
|
return void 0;
|
|
@@ -3283,7 +3603,7 @@ function Map2({
|
|
|
3283
3603
|
cancelled = true;
|
|
3284
3604
|
};
|
|
3285
3605
|
}, [datasetHref, datasetVersion, navTargetsKey, shouldFetchNav]);
|
|
3286
|
-
|
|
3606
|
+
React37.useEffect(() => {
|
|
3287
3607
|
if (leafletLib) return;
|
|
3288
3608
|
let cancelled = false;
|
|
3289
3609
|
waitForLeaflet().then((lib) => {
|
|
@@ -3295,7 +3615,7 @@ function Map2({
|
|
|
3295
3615
|
cancelled = true;
|
|
3296
3616
|
};
|
|
3297
3617
|
}, [leafletLib]);
|
|
3298
|
-
const navMatchMap =
|
|
3618
|
+
const navMatchMap = React37.useMemo(() => {
|
|
3299
3619
|
const matchMap = createMarkerMap();
|
|
3300
3620
|
(navState.markers || []).forEach((marker) => {
|
|
3301
3621
|
if (!marker || !Array.isArray(marker.matchKeys)) return;
|
|
@@ -3306,7 +3626,7 @@ function Map2({
|
|
|
3306
3626
|
});
|
|
3307
3627
|
return matchMap;
|
|
3308
3628
|
}, [navState.markers]);
|
|
3309
|
-
const normalizedCustom =
|
|
3629
|
+
const normalizedCustom = React37.useMemo(() => {
|
|
3310
3630
|
return normalizeCustomMarkers(customPoints).map((point) => {
|
|
3311
3631
|
if (!point || point.thumbnail || !point.href) return point;
|
|
3312
3632
|
const match = navMatchMap.get(normalizeKey(point.href));
|
|
@@ -3321,11 +3641,11 @@ function Map2({
|
|
|
3321
3641
|
};
|
|
3322
3642
|
});
|
|
3323
3643
|
}, [customPoints, navMatchMap]);
|
|
3324
|
-
const allMarkers =
|
|
3644
|
+
const allMarkers = React37.useMemo(() => {
|
|
3325
3645
|
return [...navState.markers || [], ...normalizedCustom];
|
|
3326
3646
|
}, [navState.markers, normalizedCustom]);
|
|
3327
|
-
const clusterOptions =
|
|
3328
|
-
|
|
3647
|
+
const clusterOptions = React37.useMemo(() => buildClusterOptions(leafletLib), [leafletLib]);
|
|
3648
|
+
React37.useEffect(() => {
|
|
3329
3649
|
if (!containerRef.current || mapRef.current || !leafletLib) return void 0;
|
|
3330
3650
|
const map = leafletLib.map(containerRef.current, {
|
|
3331
3651
|
zoomControl: true,
|
|
@@ -3363,7 +3683,7 @@ function Map2({
|
|
|
3363
3683
|
layerRef.current = null;
|
|
3364
3684
|
};
|
|
3365
3685
|
}, [tileLayers, scrollWheelZoom, cluster, clusterOptions, leafletLib]);
|
|
3366
|
-
|
|
3686
|
+
React37.useEffect(() => {
|
|
3367
3687
|
const map = mapRef.current;
|
|
3368
3688
|
const layer = layerRef.current;
|
|
3369
3689
|
if (!map || !layer || !leafletLib) return;
|
|
@@ -3467,14 +3787,14 @@ function Map2({
|
|
|
3467
3787
|
].filter(Boolean).join(" ");
|
|
3468
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." : "";
|
|
3469
3789
|
const showStatus = Boolean(statusLabel);
|
|
3470
|
-
return /* @__PURE__ */
|
|
3790
|
+
return /* @__PURE__ */ React37.createElement("div", { className: rootClass, id: id || void 0, style: style || void 0 }, /* @__PURE__ */ React37.createElement(
|
|
3471
3791
|
"div",
|
|
3472
3792
|
{
|
|
3473
3793
|
ref: containerRef,
|
|
3474
3794
|
className: "canopy-map__canvas",
|
|
3475
3795
|
style: { height: height || "600px" }
|
|
3476
3796
|
}
|
|
3477
|
-
), showStatus ? /* @__PURE__ */
|
|
3797
|
+
), showStatus ? /* @__PURE__ */ React37.createElement("div", { className: "canopy-map__status", "aria-live": "polite" }, statusLabel) : null);
|
|
3478
3798
|
}
|
|
3479
3799
|
|
|
3480
3800
|
// ui/src/content/map/MapPoint.jsx
|