@canopy-iiif/app 0.9.14 → 0.10.0
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/AGENTS.md +1 -0
- package/lib/build/build.js +1 -0
- package/lib/build/dev.js +17 -4
- package/lib/build/iiif.js +234 -12
- package/lib/build/mdx.js +2 -0
- package/lib/build/pages.js +17 -1
- package/lib/build/styles.js +4 -8
- package/lib/components/featured.js +6 -0
- package/lib/components/hero-slider-runtime.js +9 -2
- package/lib/iiif/thumbnail.js +262 -4
- package/package.json +14 -1
- package/ui/dist/index.mjs +191 -99
- package/ui/dist/index.mjs.map +4 -4
- package/ui/dist/server.mjs +295 -187
- package/ui/dist/server.mjs.map +4 -4
- package/ui/styles/base/_common.scss +33 -33
- package/ui/styles/base/_heading.scss +26 -19
- package/ui/styles/base/index.scss +0 -1
- package/ui/styles/components/_buttons.scss +53 -46
- package/ui/styles/components/_interstitial-hero.scss +13 -18
- package/ui/styles/components/_sub-navigation.scss +1 -0
- package/ui/styles/components/header/_header.scss +10 -3
- package/ui/styles/components/header/_logo.scss +32 -33
- package/ui/styles/components/search/_form.scss +4 -9
- package/ui/styles/index.css +161 -171
- package/ui/tailwind-canopy-iiif-preset.js +5 -15
- package/ui/tailwind-config.d.ts +21 -0
- package/ui/tailwind-config.js +134 -0
- package/ui/tailwind-default.config.mjs +3 -0
- package/ui/theme.js +4 -4
- package/ui/styles/_variables.scss +0 -1
package/ui/dist/index.mjs
CHANGED
|
@@ -458,8 +458,7 @@ function SearchPanelForm(props = {}) {
|
|
|
458
458
|
"data-canopy-search-form-trigger": "submit",
|
|
459
459
|
className: "canopy-search-form__submit"
|
|
460
460
|
},
|
|
461
|
-
|
|
462
|
-
/* @__PURE__ */ React9.createElement("span", { "aria-hidden": true, className: "canopy-search-form__shortcut" }, /* @__PURE__ */ React9.createElement("span", null, "\u2318"), /* @__PURE__ */ React9.createElement("span", null, "K"))
|
|
461
|
+
text
|
|
463
462
|
)
|
|
464
463
|
);
|
|
465
464
|
}
|
|
@@ -793,7 +792,9 @@ function HeaderScript() {
|
|
|
793
792
|
}
|
|
794
793
|
function ensureArray(navLinks) {
|
|
795
794
|
if (!Array.isArray(navLinks)) return [];
|
|
796
|
-
return navLinks.filter(
|
|
795
|
+
return navLinks.filter(
|
|
796
|
+
(link) => link && typeof link === "object" && typeof link.href === "string"
|
|
797
|
+
);
|
|
797
798
|
}
|
|
798
799
|
function CanopyHeader(props = {}) {
|
|
799
800
|
const {
|
|
@@ -806,59 +807,98 @@ function CanopyHeader(props = {}) {
|
|
|
806
807
|
logo: SiteLogo
|
|
807
808
|
} = props;
|
|
808
809
|
const navLinks = ensureArray(navLinksProp);
|
|
809
|
-
return /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(
|
|
810
|
-
|
|
811
|
-
{
|
|
812
|
-
label: title,
|
|
813
|
-
href: brandHref,
|
|
814
|
-
className: "canopy-header__brand-link",
|
|
815
|
-
Logo: SiteLogo
|
|
816
|
-
}
|
|
817
|
-
)), /* @__PURE__ */ React14.createElement("div", { className: "canopy-header__desktop-search" }, /* @__PURE__ */ React14.createElement(SearchPanel, { label: searchLabel, hotkey: searchHotkey, placeholder: searchPlaceholder })), /* @__PURE__ */ React14.createElement("nav", { className: "canopy-nav-links canopy-header__desktop-nav", "aria-label": "Primary navigation" }, navLinks.map((link) => /* @__PURE__ */ React14.createElement("a", { key: link.href, href: link.href }, link.label || link.href))), /* @__PURE__ */ React14.createElement("div", { className: "canopy-header__actions" }, /* @__PURE__ */ React14.createElement(
|
|
818
|
-
"button",
|
|
810
|
+
return /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(
|
|
811
|
+
"header",
|
|
819
812
|
{
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
"
|
|
823
|
-
"aria-controls": "canopy-modal-search",
|
|
824
|
-
"aria-expanded": "false",
|
|
825
|
-
"data-canopy-header-toggle": "search"
|
|
813
|
+
className: "canopy-header",
|
|
814
|
+
"data-mobile-nav": "closed",
|
|
815
|
+
"data-mobile-search": "closed"
|
|
826
816
|
},
|
|
817
|
+
/* @__PURE__ */ React14.createElement("div", { className: "canopy-header__brand" }, /* @__PURE__ */ React14.createElement(
|
|
818
|
+
CanopyBrand,
|
|
819
|
+
{
|
|
820
|
+
label: title,
|
|
821
|
+
href: brandHref,
|
|
822
|
+
className: "canopy-header__brand-link",
|
|
823
|
+
Logo: SiteLogo
|
|
824
|
+
}
|
|
825
|
+
)),
|
|
826
|
+
/* @__PURE__ */ React14.createElement("div", { className: "canopy-header__desktop-search" }, /* @__PURE__ */ React14.createElement(
|
|
827
|
+
SearchPanel,
|
|
828
|
+
{
|
|
829
|
+
label: searchLabel,
|
|
830
|
+
hotkey: searchHotkey,
|
|
831
|
+
placeholder: searchPlaceholder
|
|
832
|
+
}
|
|
833
|
+
)),
|
|
827
834
|
/* @__PURE__ */ React14.createElement(
|
|
828
|
-
"
|
|
835
|
+
"nav",
|
|
829
836
|
{
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
fill: "none",
|
|
833
|
-
stroke: "currentColor",
|
|
834
|
-
strokeWidth: "1.5",
|
|
835
|
-
className: "canopy-header__search-icon"
|
|
837
|
+
className: "canopy-nav-links canopy-header__desktop-nav",
|
|
838
|
+
"aria-label": "Primary navigation"
|
|
836
839
|
},
|
|
837
|
-
/* @__PURE__ */ React14.createElement("
|
|
838
|
-
)
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
{
|
|
842
|
-
type: "button",
|
|
843
|
-
className: "canopy-header__icon-button canopy-header__menu",
|
|
844
|
-
"aria-label": "Open navigation",
|
|
845
|
-
"aria-controls": "canopy-modal-nav",
|
|
846
|
-
"aria-expanded": "false",
|
|
847
|
-
"data-canopy-header-toggle": "nav"
|
|
848
|
-
},
|
|
849
|
-
/* @__PURE__ */ React14.createElement(
|
|
850
|
-
"svg",
|
|
840
|
+
navLinks.map((link) => /* @__PURE__ */ React14.createElement("a", { key: link.href, href: link.href }, link.label || link.href))
|
|
841
|
+
),
|
|
842
|
+
/* @__PURE__ */ React14.createElement("div", { className: "canopy-header__actions" }, /* @__PURE__ */ React14.createElement(
|
|
843
|
+
"button",
|
|
851
844
|
{
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
845
|
+
type: "button",
|
|
846
|
+
className: "canopy-header__icon-button canopy-header__search-trigger",
|
|
847
|
+
"aria-label": "Open search",
|
|
848
|
+
"aria-controls": "canopy-modal-search",
|
|
849
|
+
"aria-expanded": "false",
|
|
850
|
+
"data-canopy-header-toggle": "search"
|
|
858
851
|
},
|
|
859
|
-
/* @__PURE__ */ React14.createElement(
|
|
860
|
-
|
|
861
|
-
|
|
852
|
+
/* @__PURE__ */ React14.createElement(
|
|
853
|
+
"svg",
|
|
854
|
+
{
|
|
855
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
856
|
+
viewBox: "0 0 24 24",
|
|
857
|
+
fill: "none",
|
|
858
|
+
stroke: "currentColor",
|
|
859
|
+
strokeWidth: "1.5",
|
|
860
|
+
className: "canopy-header__search-icon"
|
|
861
|
+
},
|
|
862
|
+
/* @__PURE__ */ React14.createElement(
|
|
863
|
+
"path",
|
|
864
|
+
{
|
|
865
|
+
strokeLinecap: "round",
|
|
866
|
+
strokeLinejoin: "round",
|
|
867
|
+
d: "m21 21-3.8-3.8M10.5 18a7.5 7.5 0 1 1 0-15 7.5 7.5 0 0 1 0 15Z"
|
|
868
|
+
}
|
|
869
|
+
)
|
|
870
|
+
)
|
|
871
|
+
), /* @__PURE__ */ React14.createElement(
|
|
872
|
+
"button",
|
|
873
|
+
{
|
|
874
|
+
type: "button",
|
|
875
|
+
className: "canopy-header__icon-button canopy-header__menu",
|
|
876
|
+
"aria-label": "Open navigation",
|
|
877
|
+
"aria-controls": "canopy-modal-nav",
|
|
878
|
+
"aria-expanded": "false",
|
|
879
|
+
"data-canopy-header-toggle": "nav"
|
|
880
|
+
},
|
|
881
|
+
/* @__PURE__ */ React14.createElement(
|
|
882
|
+
"svg",
|
|
883
|
+
{
|
|
884
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
885
|
+
fill: "none",
|
|
886
|
+
viewBox: "0 0 24 24",
|
|
887
|
+
strokeWidth: "1.5",
|
|
888
|
+
stroke: "currentColor",
|
|
889
|
+
className: "canopy-header__menu-icon"
|
|
890
|
+
},
|
|
891
|
+
/* @__PURE__ */ React14.createElement(
|
|
892
|
+
"path",
|
|
893
|
+
{
|
|
894
|
+
strokeLinecap: "round",
|
|
895
|
+
strokeLinejoin: "round",
|
|
896
|
+
d: "M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"
|
|
897
|
+
}
|
|
898
|
+
)
|
|
899
|
+
)
|
|
900
|
+
))
|
|
901
|
+
), /* @__PURE__ */ React14.createElement(
|
|
862
902
|
CanopyModal,
|
|
863
903
|
{
|
|
864
904
|
id: "canopy-modal-nav",
|
|
@@ -870,7 +910,14 @@ function CanopyHeader(props = {}) {
|
|
|
870
910
|
closeLabel: "Close navigation",
|
|
871
911
|
closeDataAttr: "nav"
|
|
872
912
|
},
|
|
873
|
-
/* @__PURE__ */ React14.createElement(
|
|
913
|
+
/* @__PURE__ */ React14.createElement(
|
|
914
|
+
"nav",
|
|
915
|
+
{
|
|
916
|
+
className: "canopy-nav-links canopy-modal__nav",
|
|
917
|
+
"aria-label": "Primary navigation"
|
|
918
|
+
},
|
|
919
|
+
navLinks.map((link) => /* @__PURE__ */ React14.createElement("a", { key: link.href, href: link.href }, link.label || link.href))
|
|
920
|
+
)
|
|
874
921
|
), /* @__PURE__ */ React14.createElement(
|
|
875
922
|
CanopyModal,
|
|
876
923
|
{
|
|
@@ -884,7 +931,14 @@ function CanopyHeader(props = {}) {
|
|
|
884
931
|
closeDataAttr: "search",
|
|
885
932
|
bodyClassName: "canopy-modal__body--search"
|
|
886
933
|
},
|
|
887
|
-
/* @__PURE__ */ React14.createElement(
|
|
934
|
+
/* @__PURE__ */ React14.createElement(
|
|
935
|
+
SearchPanel,
|
|
936
|
+
{
|
|
937
|
+
label: searchLabel,
|
|
938
|
+
hotkey: searchHotkey,
|
|
939
|
+
placeholder: searchPlaceholder
|
|
940
|
+
}
|
|
941
|
+
)
|
|
888
942
|
), /* @__PURE__ */ React14.createElement(HeaderScript, null));
|
|
889
943
|
}
|
|
890
944
|
|
|
@@ -1038,8 +1092,45 @@ var Scroll = (props) => {
|
|
|
1038
1092
|
return /* @__PURE__ */ React18.createElement(CloverScroll, { ...props });
|
|
1039
1093
|
};
|
|
1040
1094
|
|
|
1095
|
+
// ui/src/iiif/Image.jsx
|
|
1096
|
+
import React19, { useEffect as useEffect5, useState as useState5 } from "react";
|
|
1097
|
+
var Image = (props) => {
|
|
1098
|
+
const [CloverImage, setCloverImage] = useState5(null);
|
|
1099
|
+
useEffect5(() => {
|
|
1100
|
+
let mounted = true;
|
|
1101
|
+
const canUseDom = typeof window !== "undefined" && typeof document !== "undefined";
|
|
1102
|
+
if (canUseDom) {
|
|
1103
|
+
import("@samvera/clover-iiif/image").then((mod) => {
|
|
1104
|
+
if (!mounted) return;
|
|
1105
|
+
const Comp = mod && (mod.default || mod.Image || mod);
|
|
1106
|
+
setCloverImage(() => Comp);
|
|
1107
|
+
}).catch(() => {
|
|
1108
|
+
});
|
|
1109
|
+
}
|
|
1110
|
+
return () => {
|
|
1111
|
+
mounted = false;
|
|
1112
|
+
};
|
|
1113
|
+
}, []);
|
|
1114
|
+
if (!CloverImage) {
|
|
1115
|
+
let json = "{}";
|
|
1116
|
+
try {
|
|
1117
|
+
json = JSON.stringify(props || {});
|
|
1118
|
+
} catch (_) {
|
|
1119
|
+
json = "{}";
|
|
1120
|
+
}
|
|
1121
|
+
return /* @__PURE__ */ React19.createElement("div", { "data-canopy-image": "1", className: "not-prose" }, /* @__PURE__ */ React19.createElement(
|
|
1122
|
+
"script",
|
|
1123
|
+
{
|
|
1124
|
+
type: "application/json",
|
|
1125
|
+
dangerouslySetInnerHTML: { __html: json }
|
|
1126
|
+
}
|
|
1127
|
+
));
|
|
1128
|
+
}
|
|
1129
|
+
return /* @__PURE__ */ React19.createElement(CloverImage, { ...props });
|
|
1130
|
+
};
|
|
1131
|
+
|
|
1041
1132
|
// ui/src/iiif/MdxRelatedItems.jsx
|
|
1042
|
-
import
|
|
1133
|
+
import React20 from "react";
|
|
1043
1134
|
function MdxRelatedItems(props) {
|
|
1044
1135
|
let json = "{}";
|
|
1045
1136
|
try {
|
|
@@ -1047,11 +1138,11 @@ function MdxRelatedItems(props) {
|
|
|
1047
1138
|
} catch (_) {
|
|
1048
1139
|
json = "{}";
|
|
1049
1140
|
}
|
|
1050
|
-
return /* @__PURE__ */
|
|
1141
|
+
return /* @__PURE__ */ React20.createElement("div", { "data-canopy-related-items": "1", className: "not-prose" }, /* @__PURE__ */ React20.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
1051
1142
|
}
|
|
1052
1143
|
|
|
1053
1144
|
// ui/src/search/MdxSearchResults.jsx
|
|
1054
|
-
import
|
|
1145
|
+
import React21 from "react";
|
|
1055
1146
|
function MdxSearchResults(props) {
|
|
1056
1147
|
let json = "{}";
|
|
1057
1148
|
try {
|
|
@@ -1059,11 +1150,11 @@ function MdxSearchResults(props) {
|
|
|
1059
1150
|
} catch (_) {
|
|
1060
1151
|
json = "{}";
|
|
1061
1152
|
}
|
|
1062
|
-
return /* @__PURE__ */
|
|
1153
|
+
return /* @__PURE__ */ React21.createElement("div", { "data-canopy-search-results": "1" }, /* @__PURE__ */ React21.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
1063
1154
|
}
|
|
1064
1155
|
|
|
1065
1156
|
// ui/src/search/SearchSummary.jsx
|
|
1066
|
-
import
|
|
1157
|
+
import React22 from "react";
|
|
1067
1158
|
function SearchSummary(props) {
|
|
1068
1159
|
let json = "{}";
|
|
1069
1160
|
try {
|
|
@@ -1071,11 +1162,11 @@ function SearchSummary(props) {
|
|
|
1071
1162
|
} catch (_) {
|
|
1072
1163
|
json = "{}";
|
|
1073
1164
|
}
|
|
1074
|
-
return /* @__PURE__ */
|
|
1165
|
+
return /* @__PURE__ */ React22.createElement("div", { "data-canopy-search-summary": "1" }, /* @__PURE__ */ React22.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
1075
1166
|
}
|
|
1076
1167
|
|
|
1077
1168
|
// ui/src/search/MdxSearchTabs.jsx
|
|
1078
|
-
import
|
|
1169
|
+
import React23 from "react";
|
|
1079
1170
|
function MdxSearchTabs(props) {
|
|
1080
1171
|
let json = "{}";
|
|
1081
1172
|
try {
|
|
@@ -1083,11 +1174,11 @@ function MdxSearchTabs(props) {
|
|
|
1083
1174
|
} catch (_) {
|
|
1084
1175
|
json = "{}";
|
|
1085
1176
|
}
|
|
1086
|
-
return /* @__PURE__ */
|
|
1177
|
+
return /* @__PURE__ */ React23.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React23.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
1087
1178
|
}
|
|
1088
1179
|
|
|
1089
1180
|
// ui/src/search/SearchResults.jsx
|
|
1090
|
-
import
|
|
1181
|
+
import React24 from "react";
|
|
1091
1182
|
function SearchResults({
|
|
1092
1183
|
results = [],
|
|
1093
1184
|
type = "all",
|
|
@@ -1095,19 +1186,19 @@ function SearchResults({
|
|
|
1095
1186
|
query = ""
|
|
1096
1187
|
}) {
|
|
1097
1188
|
if (!results.length) {
|
|
1098
|
-
return /* @__PURE__ */
|
|
1189
|
+
return /* @__PURE__ */ React24.createElement("div", { className: "text-slate-600" }, /* @__PURE__ */ React24.createElement("em", null, "No results"));
|
|
1099
1190
|
}
|
|
1100
1191
|
const normalizedType = String(type || "all").toLowerCase();
|
|
1101
1192
|
const isAnnotationView = normalizedType === "annotation";
|
|
1102
1193
|
if (isAnnotationView) {
|
|
1103
|
-
return /* @__PURE__ */
|
|
1194
|
+
return /* @__PURE__ */ React24.createElement("div", { id: "search-results", className: "space-y-4" }, results.map((r, i) => {
|
|
1104
1195
|
if (!r) return null;
|
|
1105
1196
|
return renderTextCard(r, r.id || i);
|
|
1106
1197
|
}));
|
|
1107
1198
|
}
|
|
1108
1199
|
const renderTextCard = (record, key) => {
|
|
1109
1200
|
if (!record) return null;
|
|
1110
|
-
return /* @__PURE__ */
|
|
1201
|
+
return /* @__PURE__ */ React24.createElement(
|
|
1111
1202
|
TextCard,
|
|
1112
1203
|
{
|
|
1113
1204
|
key,
|
|
@@ -1123,20 +1214,20 @@ function SearchResults({
|
|
|
1123
1214
|
const isWorkRecord = (record) => String(record && record.type).toLowerCase() === "work";
|
|
1124
1215
|
const shouldRenderAsTextCard = (record) => !isWorkRecord(record) || normalizedType !== "work";
|
|
1125
1216
|
if (layout === "list") {
|
|
1126
|
-
return /* @__PURE__ */
|
|
1217
|
+
return /* @__PURE__ */ React24.createElement("ul", { id: "search-results", className: "space-y-3" }, results.map((r, i) => {
|
|
1127
1218
|
if (shouldRenderAsTextCard(r)) {
|
|
1128
|
-
return /* @__PURE__ */
|
|
1219
|
+
return /* @__PURE__ */ React24.createElement("li", { key: i, className: `search-result ${r && r.type}` }, renderTextCard(r, i));
|
|
1129
1220
|
}
|
|
1130
1221
|
const hasDims = Number.isFinite(Number(r.thumbnailWidth)) && Number(r.thumbnailWidth) > 0 && Number.isFinite(Number(r.thumbnailHeight)) && Number(r.thumbnailHeight) > 0;
|
|
1131
1222
|
const aspect = hasDims ? Number(r.thumbnailWidth) / Number(r.thumbnailHeight) : void 0;
|
|
1132
|
-
return /* @__PURE__ */
|
|
1223
|
+
return /* @__PURE__ */ React24.createElement(
|
|
1133
1224
|
"li",
|
|
1134
1225
|
{
|
|
1135
1226
|
key: i,
|
|
1136
1227
|
className: `search-result ${r.type}`,
|
|
1137
1228
|
"data-thumbnail-aspect-ratio": aspect
|
|
1138
1229
|
},
|
|
1139
|
-
/* @__PURE__ */
|
|
1230
|
+
/* @__PURE__ */ React24.createElement(
|
|
1140
1231
|
Card,
|
|
1141
1232
|
{
|
|
1142
1233
|
href: r.href,
|
|
@@ -1150,20 +1241,20 @@ function SearchResults({
|
|
|
1150
1241
|
);
|
|
1151
1242
|
}));
|
|
1152
1243
|
}
|
|
1153
|
-
return /* @__PURE__ */
|
|
1244
|
+
return /* @__PURE__ */ React24.createElement("div", { id: "search-results" }, /* @__PURE__ */ React24.createElement(Grid, null, results.map((r, i) => {
|
|
1154
1245
|
if (shouldRenderAsTextCard(r)) {
|
|
1155
|
-
return /* @__PURE__ */
|
|
1246
|
+
return /* @__PURE__ */ React24.createElement(GridItem, { key: i, className: `search-result ${r && r.type}` }, renderTextCard(r, i));
|
|
1156
1247
|
}
|
|
1157
1248
|
const hasDims = Number.isFinite(Number(r.thumbnailWidth)) && Number(r.thumbnailWidth) > 0 && Number.isFinite(Number(r.thumbnailHeight)) && Number(r.thumbnailHeight) > 0;
|
|
1158
1249
|
const aspect = hasDims ? Number(r.thumbnailWidth) / Number(r.thumbnailHeight) : void 0;
|
|
1159
|
-
return /* @__PURE__ */
|
|
1250
|
+
return /* @__PURE__ */ React24.createElement(
|
|
1160
1251
|
GridItem,
|
|
1161
1252
|
{
|
|
1162
1253
|
key: i,
|
|
1163
1254
|
className: `search-result ${r.type}`,
|
|
1164
1255
|
"data-thumbnail-aspect-ratio": aspect
|
|
1165
1256
|
},
|
|
1166
|
-
/* @__PURE__ */
|
|
1257
|
+
/* @__PURE__ */ React24.createElement(
|
|
1167
1258
|
Card,
|
|
1168
1259
|
{
|
|
1169
1260
|
href: r.href,
|
|
@@ -1179,7 +1270,7 @@ function SearchResults({
|
|
|
1179
1270
|
}
|
|
1180
1271
|
|
|
1181
1272
|
// ui/src/search/SearchTabs.jsx
|
|
1182
|
-
import
|
|
1273
|
+
import React25 from "react";
|
|
1183
1274
|
function SearchTabs({
|
|
1184
1275
|
type = "all",
|
|
1185
1276
|
onTypeChange,
|
|
@@ -1194,7 +1285,7 @@ function SearchTabs({
|
|
|
1194
1285
|
const toLabel = (t) => t && t.length ? t.charAt(0).toUpperCase() + t.slice(1) : "";
|
|
1195
1286
|
const hasFilters = typeof onOpenFilters === "function";
|
|
1196
1287
|
const filterBadge = activeFilterCount > 0 ? ` (${activeFilterCount})` : "";
|
|
1197
|
-
return /* @__PURE__ */
|
|
1288
|
+
return /* @__PURE__ */ React25.createElement("div", { className: "canopy-search-tabs-wrapper" }, /* @__PURE__ */ React25.createElement(
|
|
1198
1289
|
"div",
|
|
1199
1290
|
{
|
|
1200
1291
|
role: "tablist",
|
|
@@ -1205,7 +1296,7 @@ function SearchTabs({
|
|
|
1205
1296
|
const active = String(type).toLowerCase() === String(t).toLowerCase();
|
|
1206
1297
|
const cRaw = counts && Object.prototype.hasOwnProperty.call(counts, t) ? counts[t] : void 0;
|
|
1207
1298
|
const c = Number.isFinite(Number(cRaw)) ? Number(cRaw) : 0;
|
|
1208
|
-
return /* @__PURE__ */
|
|
1299
|
+
return /* @__PURE__ */ React25.createElement(
|
|
1209
1300
|
"button",
|
|
1210
1301
|
{
|
|
1211
1302
|
key: t,
|
|
@@ -1220,7 +1311,7 @@ function SearchTabs({
|
|
|
1220
1311
|
")"
|
|
1221
1312
|
);
|
|
1222
1313
|
})
|
|
1223
|
-
), hasFilters ? /* @__PURE__ */
|
|
1314
|
+
), hasFilters ? /* @__PURE__ */ React25.createElement(
|
|
1224
1315
|
"button",
|
|
1225
1316
|
{
|
|
1226
1317
|
type: "button",
|
|
@@ -1228,12 +1319,12 @@ function SearchTabs({
|
|
|
1228
1319
|
"aria-expanded": filtersOpen ? "true" : "false",
|
|
1229
1320
|
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"
|
|
1230
1321
|
},
|
|
1231
|
-
/* @__PURE__ */
|
|
1322
|
+
/* @__PURE__ */ React25.createElement("span", null, filtersLabel, filterBadge)
|
|
1232
1323
|
) : null);
|
|
1233
1324
|
}
|
|
1234
1325
|
|
|
1235
1326
|
// ui/src/search/SearchFiltersDialog.jsx
|
|
1236
|
-
import
|
|
1327
|
+
import React26 from "react";
|
|
1237
1328
|
function toArray(input) {
|
|
1238
1329
|
if (!input) return [];
|
|
1239
1330
|
if (Array.isArray(input)) return input;
|
|
@@ -1272,20 +1363,20 @@ function FacetSection({ facet, selected, onToggle }) {
|
|
|
1272
1363
|
const selectedValues = selected.get(String(slug)) || /* @__PURE__ */ new Set();
|
|
1273
1364
|
const checkboxId = (valueSlug) => `filter-${slug}-${valueSlug}`;
|
|
1274
1365
|
const hasSelection = selectedValues.size > 0;
|
|
1275
|
-
const [quickQuery, setQuickQuery] =
|
|
1366
|
+
const [quickQuery, setQuickQuery] = React26.useState("");
|
|
1276
1367
|
const hasQuery = quickQuery.trim().length > 0;
|
|
1277
|
-
const filteredValues =
|
|
1368
|
+
const filteredValues = React26.useMemo(
|
|
1278
1369
|
() => facetMatches(values, quickQuery),
|
|
1279
1370
|
[values, quickQuery]
|
|
1280
1371
|
);
|
|
1281
|
-
return /* @__PURE__ */
|
|
1372
|
+
return /* @__PURE__ */ React26.createElement(
|
|
1282
1373
|
"details",
|
|
1283
1374
|
{
|
|
1284
1375
|
className: "canopy-search-filters__facet",
|
|
1285
1376
|
open: hasSelection
|
|
1286
1377
|
},
|
|
1287
|
-
/* @__PURE__ */
|
|
1288
|
-
/* @__PURE__ */
|
|
1378
|
+
/* @__PURE__ */ React26.createElement("summary", { className: "canopy-search-filters__facet-summary" }, /* @__PURE__ */ React26.createElement("span", null, label), /* @__PURE__ */ React26.createElement("span", { className: "canopy-search-filters__facet-count" }, values.length)),
|
|
1379
|
+
/* @__PURE__ */ React26.createElement("div", { className: "canopy-search-filters__facet-content" }, /* @__PURE__ */ React26.createElement("div", { className: "canopy-search-filters__quick" }, /* @__PURE__ */ React26.createElement(
|
|
1289
1380
|
"input",
|
|
1290
1381
|
{
|
|
1291
1382
|
type: "search",
|
|
@@ -1295,7 +1386,7 @@ function FacetSection({ facet, selected, onToggle }) {
|
|
|
1295
1386
|
className: "canopy-search-filters__quick-input",
|
|
1296
1387
|
"aria-label": `Filter ${label} values`
|
|
1297
1388
|
}
|
|
1298
|
-
), quickQuery ? /* @__PURE__ */
|
|
1389
|
+
), quickQuery ? /* @__PURE__ */ React26.createElement(
|
|
1299
1390
|
"button",
|
|
1300
1391
|
{
|
|
1301
1392
|
type: "button",
|
|
@@ -1303,11 +1394,11 @@ function FacetSection({ facet, selected, onToggle }) {
|
|
|
1303
1394
|
className: "canopy-search-filters__quick-clear"
|
|
1304
1395
|
},
|
|
1305
1396
|
"Clear"
|
|
1306
|
-
) : null), hasQuery && !filteredValues.length ? /* @__PURE__ */
|
|
1397
|
+
) : null), hasQuery && !filteredValues.length ? /* @__PURE__ */ React26.createElement("p", { className: "canopy-search-filters__facet-notice" }, "No matches found.") : null, /* @__PURE__ */ React26.createElement("ul", { className: "canopy-search-filters__facet-list" }, filteredValues.map((entry) => {
|
|
1307
1398
|
const valueSlug = String(entry.slug || entry.value || "");
|
|
1308
1399
|
const isChecked = selectedValues.has(valueSlug);
|
|
1309
1400
|
const inputId = checkboxId(valueSlug);
|
|
1310
|
-
return /* @__PURE__ */
|
|
1401
|
+
return /* @__PURE__ */ React26.createElement("li", { key: valueSlug, className: "canopy-search-filters__facet-item" }, /* @__PURE__ */ React26.createElement(
|
|
1311
1402
|
"input",
|
|
1312
1403
|
{
|
|
1313
1404
|
id: inputId,
|
|
@@ -1319,15 +1410,15 @@ function FacetSection({ facet, selected, onToggle }) {
|
|
|
1319
1410
|
if (onToggle) onToggle(slug, valueSlug, nextChecked);
|
|
1320
1411
|
}
|
|
1321
1412
|
}
|
|
1322
|
-
), /* @__PURE__ */
|
|
1413
|
+
), /* @__PURE__ */ React26.createElement(
|
|
1323
1414
|
"label",
|
|
1324
1415
|
{
|
|
1325
1416
|
htmlFor: inputId,
|
|
1326
1417
|
className: "canopy-search-filters__facet-label"
|
|
1327
1418
|
},
|
|
1328
|
-
/* @__PURE__ */
|
|
1419
|
+
/* @__PURE__ */ React26.createElement("span", null, entry.value, " ", Number.isFinite(entry.doc_count) ? /* @__PURE__ */ React26.createElement("span", { className: "canopy-search-filters__facet-count" }, "(", entry.doc_count, ")") : null)
|
|
1329
1420
|
));
|
|
1330
|
-
}), !filteredValues.length && !hasQuery ? /* @__PURE__ */
|
|
1421
|
+
}), !filteredValues.length && !hasQuery ? /* @__PURE__ */ React26.createElement("li", { className: "canopy-search-filters__facet-empty" }, "No values available.") : null))
|
|
1331
1422
|
);
|
|
1332
1423
|
}
|
|
1333
1424
|
function SearchFiltersDialog(props = {}) {
|
|
@@ -1349,7 +1440,7 @@ function SearchFiltersDialog(props = {}) {
|
|
|
1349
1440
|
(total, set) => total + set.size,
|
|
1350
1441
|
0
|
|
1351
1442
|
);
|
|
1352
|
-
|
|
1443
|
+
React26.useEffect(() => {
|
|
1353
1444
|
if (!open) return void 0;
|
|
1354
1445
|
if (typeof document === "undefined") return void 0;
|
|
1355
1446
|
const body = document.body;
|
|
@@ -1366,7 +1457,7 @@ function SearchFiltersDialog(props = {}) {
|
|
|
1366
1457
|
if (!open) return null;
|
|
1367
1458
|
const brandId = "canopy-modal-filters-label";
|
|
1368
1459
|
const subtitleText = subtitle != null ? subtitle : title;
|
|
1369
|
-
return /* @__PURE__ */
|
|
1460
|
+
return /* @__PURE__ */ React26.createElement(
|
|
1370
1461
|
CanopyModal,
|
|
1371
1462
|
{
|
|
1372
1463
|
id: "canopy-modal-filters",
|
|
@@ -1381,8 +1472,8 @@ function SearchFiltersDialog(props = {}) {
|
|
|
1381
1472
|
onBackgroundClick: () => onOpenChange && onOpenChange(false),
|
|
1382
1473
|
bodyClassName: "canopy-modal__body--filters"
|
|
1383
1474
|
},
|
|
1384
|
-
subtitleText ? /* @__PURE__ */
|
|
1385
|
-
/* @__PURE__ */
|
|
1475
|
+
subtitleText ? /* @__PURE__ */ React26.createElement("p", { className: "canopy-search-filters__subtitle" }, subtitleText) : null,
|
|
1476
|
+
/* @__PURE__ */ React26.createElement("div", { className: "canopy-search-filters__body" }, Array.isArray(facets) && facets.length ? /* @__PURE__ */ React26.createElement("div", { className: "canopy-search-filters__facets" }, facets.map((facet) => /* @__PURE__ */ React26.createElement(
|
|
1386
1477
|
FacetSection,
|
|
1387
1478
|
{
|
|
1388
1479
|
key: facet.slug || facet.label,
|
|
@@ -1390,8 +1481,8 @@ function SearchFiltersDialog(props = {}) {
|
|
|
1390
1481
|
selected: selectedMap,
|
|
1391
1482
|
onToggle
|
|
1392
1483
|
}
|
|
1393
|
-
))) : /* @__PURE__ */
|
|
1394
|
-
/* @__PURE__ */
|
|
1484
|
+
))) : /* @__PURE__ */ React26.createElement("p", { className: "canopy-search-filters__empty" }, "No filters are available for this collection.")),
|
|
1485
|
+
/* @__PURE__ */ React26.createElement("footer", { className: "canopy-search-filters__footer" }, /* @__PURE__ */ React26.createElement("div", null, activeCount ? `${activeCount} filter${activeCount === 1 ? "" : "s"} applied` : "No filters applied"), /* @__PURE__ */ React26.createElement("div", { className: "canopy-search-filters__footer-actions" }, /* @__PURE__ */ React26.createElement(
|
|
1395
1486
|
"button",
|
|
1396
1487
|
{
|
|
1397
1488
|
type: "button",
|
|
@@ -1402,7 +1493,7 @@ function SearchFiltersDialog(props = {}) {
|
|
|
1402
1493
|
className: "canopy-search-filters__button canopy-search-filters__button--secondary"
|
|
1403
1494
|
},
|
|
1404
1495
|
"Clear all"
|
|
1405
|
-
), /* @__PURE__ */
|
|
1496
|
+
), /* @__PURE__ */ React26.createElement(
|
|
1406
1497
|
"button",
|
|
1407
1498
|
{
|
|
1408
1499
|
type: "button",
|
|
@@ -1415,7 +1506,7 @@ function SearchFiltersDialog(props = {}) {
|
|
|
1415
1506
|
}
|
|
1416
1507
|
|
|
1417
1508
|
// ui/src/search-form/MdxSearchFormModal.jsx
|
|
1418
|
-
import
|
|
1509
|
+
import React27 from "react";
|
|
1419
1510
|
function MdxSearchFormModal(props = {}) {
|
|
1420
1511
|
const {
|
|
1421
1512
|
placeholder = "Search\u2026",
|
|
@@ -1431,14 +1522,14 @@ function MdxSearchFormModal(props = {}) {
|
|
|
1431
1522
|
const text = typeof label === "string" && label.trim() ? label.trim() : buttonLabel;
|
|
1432
1523
|
const resolvedSearchPath = resolveSearchPath(searchPath);
|
|
1433
1524
|
const data = { placeholder, hotkey, maxResults, groupOrder, label: text, searchPath: resolvedSearchPath };
|
|
1434
|
-
return /* @__PURE__ */
|
|
1525
|
+
return /* @__PURE__ */ React27.createElement("div", { "data-canopy-search-form": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React27.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React27.createElement(SearchPanelForm, { placeholder, buttonLabel, label, searchPath: resolvedSearchPath }), /* @__PURE__ */ React27.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React27.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
|
|
1435
1526
|
}
|
|
1436
1527
|
|
|
1437
1528
|
// ui/src/docs/MarkdownTable.jsx
|
|
1438
|
-
import
|
|
1529
|
+
import React28 from "react";
|
|
1439
1530
|
function MarkdownTable({ className = "", ...rest }) {
|
|
1440
1531
|
const merged = ["markdown-table", className].filter(Boolean).join(" ");
|
|
1441
|
-
return /* @__PURE__ */
|
|
1532
|
+
return /* @__PURE__ */ React28.createElement("div", { className: "markdown-table__frame" }, /* @__PURE__ */ React28.createElement("table", { className: merged, ...rest }));
|
|
1442
1533
|
}
|
|
1443
1534
|
export {
|
|
1444
1535
|
Button,
|
|
@@ -1453,6 +1544,7 @@ export {
|
|
|
1453
1544
|
Grid,
|
|
1454
1545
|
GridItem,
|
|
1455
1546
|
HelloWorld,
|
|
1547
|
+
Image,
|
|
1456
1548
|
MdxRelatedItems as RelatedItems,
|
|
1457
1549
|
Scroll,
|
|
1458
1550
|
SearchFiltersDialog,
|