@canopy-iiif/app 0.9.2 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/build/mdx.js +39 -23
- package/package.json +3 -2
- package/ui/dist/index.mjs +704 -293
- package/ui/dist/index.mjs.map +4 -4
- package/ui/dist/server.mjs +640 -76
- package/ui/dist/server.mjs.map +4 -4
- package/ui/styles/components/header/_header.scss +153 -3
- package/ui/styles/components/header/_logo.scss +3 -2
- package/ui/styles/components/header/_navbar.scss +52 -10
- package/ui/styles/components/index.scss +1 -0
- package/ui/styles/components/modal/_modal.scss +122 -0
- package/ui/styles/components/modal/index.scss +1 -0
- package/ui/styles/components/search/_filters.scss +197 -225
- package/ui/styles/index.css +532 -313
- package/ui/theme.js +8 -8
package/ui/dist/server.mjs
CHANGED
|
@@ -809,51 +809,18 @@ function Layout({
|
|
|
809
809
|
)) : null);
|
|
810
810
|
}
|
|
811
811
|
|
|
812
|
-
// ui/src/
|
|
813
|
-
import React10 from "react";
|
|
814
|
-
function MdxSearchResults(props) {
|
|
815
|
-
let json = "{}";
|
|
816
|
-
try {
|
|
817
|
-
json = JSON.stringify(props || {});
|
|
818
|
-
} catch (_) {
|
|
819
|
-
json = "{}";
|
|
820
|
-
}
|
|
821
|
-
return /* @__PURE__ */ React10.createElement("div", { "data-canopy-search-results": "1" }, /* @__PURE__ */ React10.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
// ui/src/search/SearchSummary.jsx
|
|
825
|
-
import React11 from "react";
|
|
826
|
-
function SearchSummary(props) {
|
|
827
|
-
let json = "{}";
|
|
828
|
-
try {
|
|
829
|
-
json = JSON.stringify(props || {});
|
|
830
|
-
} catch (_) {
|
|
831
|
-
json = "{}";
|
|
832
|
-
}
|
|
833
|
-
return /* @__PURE__ */ React11.createElement("div", { "data-canopy-search-summary": "1" }, /* @__PURE__ */ React11.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
// ui/src/search/MdxSearchTabs.jsx
|
|
837
|
-
import React12 from "react";
|
|
838
|
-
function MdxSearchTabs(props) {
|
|
839
|
-
let json = "{}";
|
|
840
|
-
try {
|
|
841
|
-
json = JSON.stringify(props || {});
|
|
842
|
-
} catch (_) {
|
|
843
|
-
json = "{}";
|
|
844
|
-
}
|
|
845
|
-
return /* @__PURE__ */ React12.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React12.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
// ui/src/search-form/MdxSearchFormModal.jsx
|
|
812
|
+
// ui/src/layout/CanopyHeader.jsx
|
|
849
813
|
import React16 from "react";
|
|
850
814
|
|
|
851
|
-
// ui/src/
|
|
815
|
+
// ui/src/search/SearchPanel.jsx
|
|
852
816
|
import React13 from "react";
|
|
853
|
-
|
|
817
|
+
|
|
818
|
+
// ui/src/Icons.jsx
|
|
819
|
+
import React10 from "react";
|
|
820
|
+
var MagnifyingGlassIcon = (props) => /* @__PURE__ */ React10.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512", ...props }, /* @__PURE__ */ React10.createElement("path", { d: "M456.69 421.39L362.6 327.3a173.81 173.81 0 0034.84-104.58C397.44 126.38 319.06 48 222.72 48S48 126.38 48 222.72s78.38 174.72 174.72 174.72A173.81 173.81 0 00327.3 362.6l94.09 94.09a25 25 0 0035.3-35.3zM97.92 222.72a124.8 124.8 0 11124.8 124.8 124.95 124.95 0 01-124.8-124.8z" }));
|
|
854
821
|
|
|
855
822
|
// ui/src/search/SearchPanelForm.jsx
|
|
856
|
-
import
|
|
823
|
+
import React11 from "react";
|
|
857
824
|
function readBasePath() {
|
|
858
825
|
const normalize = (val) => {
|
|
859
826
|
const raw = typeof val === "string" ? val.trim() : "";
|
|
@@ -916,18 +883,18 @@ function SearchPanelForm(props = {}) {
|
|
|
916
883
|
clearLabel = "Clear search"
|
|
917
884
|
} = props || {};
|
|
918
885
|
const text = typeof label === "string" && label.trim() ? label.trim() : buttonLabel;
|
|
919
|
-
const action =
|
|
886
|
+
const action = React11.useMemo(
|
|
920
887
|
() => resolveSearchPath(searchPath),
|
|
921
888
|
[searchPath]
|
|
922
889
|
);
|
|
923
|
-
const autoId = typeof
|
|
924
|
-
const [fallbackId] =
|
|
890
|
+
const autoId = typeof React11.useId === "function" ? React11.useId() : void 0;
|
|
891
|
+
const [fallbackId] = React11.useState(
|
|
925
892
|
() => `canopy-search-form-${Math.random().toString(36).slice(2, 10)}`
|
|
926
893
|
);
|
|
927
894
|
const inputId = inputIdProp || autoId || fallbackId;
|
|
928
|
-
const inputRef =
|
|
929
|
-
const [hasValue, setHasValue] =
|
|
930
|
-
const focusInput =
|
|
895
|
+
const inputRef = React11.useRef(null);
|
|
896
|
+
const [hasValue, setHasValue] = React11.useState(false);
|
|
897
|
+
const focusInput = React11.useCallback(() => {
|
|
931
898
|
const el = inputRef.current;
|
|
932
899
|
if (!el) return;
|
|
933
900
|
if (document.activeElement === el) return;
|
|
@@ -940,7 +907,7 @@ function SearchPanelForm(props = {}) {
|
|
|
940
907
|
}
|
|
941
908
|
}
|
|
942
909
|
}, []);
|
|
943
|
-
const handlePointerDown =
|
|
910
|
+
const handlePointerDown = React11.useCallback(
|
|
944
911
|
(event) => {
|
|
945
912
|
const target = event.target;
|
|
946
913
|
if (target && typeof target.closest === "function") {
|
|
@@ -952,23 +919,23 @@ function SearchPanelForm(props = {}) {
|
|
|
952
919
|
},
|
|
953
920
|
[focusInput]
|
|
954
921
|
);
|
|
955
|
-
|
|
922
|
+
React11.useEffect(() => {
|
|
956
923
|
const el = inputRef.current;
|
|
957
924
|
if (!el) return;
|
|
958
925
|
if (el.value && el.value.trim()) {
|
|
959
926
|
setHasValue(true);
|
|
960
927
|
}
|
|
961
928
|
}, []);
|
|
962
|
-
const handleInputChange =
|
|
929
|
+
const handleInputChange = React11.useCallback((event) => {
|
|
963
930
|
var _a;
|
|
964
931
|
const nextHasValue = Boolean(
|
|
965
932
|
((_a = event == null ? void 0 : event.target) == null ? void 0 : _a.value) && event.target.value.trim()
|
|
966
933
|
);
|
|
967
934
|
setHasValue(nextHasValue);
|
|
968
935
|
}, []);
|
|
969
|
-
const handleClear =
|
|
936
|
+
const handleClear = React11.useCallback((event) => {
|
|
970
937
|
}, []);
|
|
971
|
-
const handleClearKey =
|
|
938
|
+
const handleClearKey = React11.useCallback(
|
|
972
939
|
(event) => {
|
|
973
940
|
if (event.key === "Enter" || event.key === " ") {
|
|
974
941
|
event.preventDefault();
|
|
@@ -977,7 +944,7 @@ function SearchPanelForm(props = {}) {
|
|
|
977
944
|
},
|
|
978
945
|
[handleClear]
|
|
979
946
|
);
|
|
980
|
-
return /* @__PURE__ */
|
|
947
|
+
return /* @__PURE__ */ React11.createElement(
|
|
981
948
|
"form",
|
|
982
949
|
{
|
|
983
950
|
action,
|
|
@@ -989,7 +956,7 @@ function SearchPanelForm(props = {}) {
|
|
|
989
956
|
onPointerDown: handlePointerDown,
|
|
990
957
|
"data-has-value": hasValue ? "1" : "0"
|
|
991
958
|
},
|
|
992
|
-
/* @__PURE__ */
|
|
959
|
+
/* @__PURE__ */ React11.createElement("label", { htmlFor: inputId, className: "canopy-search-form__label" }, /* @__PURE__ */ React11.createElement(MagnifyingGlassIcon, { className: "canopy-search-form__icon" }), /* @__PURE__ */ React11.createElement(
|
|
993
960
|
"input",
|
|
994
961
|
{
|
|
995
962
|
id: inputId,
|
|
@@ -1005,7 +972,7 @@ function SearchPanelForm(props = {}) {
|
|
|
1005
972
|
onInput: handleInputChange
|
|
1006
973
|
}
|
|
1007
974
|
)),
|
|
1008
|
-
hasValue ? /* @__PURE__ */
|
|
975
|
+
hasValue ? /* @__PURE__ */ React11.createElement(
|
|
1009
976
|
"button",
|
|
1010
977
|
{
|
|
1011
978
|
type: "button",
|
|
@@ -1018,44 +985,45 @@ function SearchPanelForm(props = {}) {
|
|
|
1018
985
|
},
|
|
1019
986
|
"\xD7"
|
|
1020
987
|
) : null,
|
|
1021
|
-
/* @__PURE__ */
|
|
988
|
+
/* @__PURE__ */ React11.createElement(
|
|
1022
989
|
"button",
|
|
1023
990
|
{
|
|
1024
991
|
type: "submit",
|
|
1025
992
|
"data-canopy-search-form-trigger": "submit",
|
|
1026
993
|
className: "canopy-search-form__submit"
|
|
1027
994
|
},
|
|
1028
|
-
/* @__PURE__ */
|
|
1029
|
-
/* @__PURE__ */
|
|
995
|
+
/* @__PURE__ */ React11.createElement("span", null, text),
|
|
996
|
+
/* @__PURE__ */ React11.createElement("span", { "aria-hidden": true, className: "canopy-search-form__shortcut" }, /* @__PURE__ */ React11.createElement("span", null, "\u2318"), /* @__PURE__ */ React11.createElement("span", null, "K"))
|
|
1030
997
|
)
|
|
1031
998
|
);
|
|
1032
999
|
}
|
|
1033
1000
|
|
|
1034
1001
|
// ui/src/search/SearchPanelTeaserResults.jsx
|
|
1035
|
-
import
|
|
1002
|
+
import React12 from "react";
|
|
1036
1003
|
function SearchPanelTeaserResults(props = {}) {
|
|
1037
1004
|
const { style, className } = props || {};
|
|
1038
1005
|
const classes = ["canopy-search-teaser", className].filter(Boolean).join(" ");
|
|
1039
|
-
return /* @__PURE__ */
|
|
1006
|
+
return /* @__PURE__ */ React12.createElement(
|
|
1040
1007
|
"div",
|
|
1041
1008
|
{
|
|
1042
1009
|
"data-canopy-search-form-panel": true,
|
|
1043
1010
|
className: classes || void 0,
|
|
1044
1011
|
style
|
|
1045
1012
|
},
|
|
1046
|
-
/* @__PURE__ */
|
|
1013
|
+
/* @__PURE__ */ React12.createElement("div", { id: "cplist" })
|
|
1047
1014
|
);
|
|
1048
1015
|
}
|
|
1049
1016
|
|
|
1050
|
-
// ui/src/search
|
|
1051
|
-
function
|
|
1017
|
+
// ui/src/search/SearchPanel.jsx
|
|
1018
|
+
function SearchPanel(props = {}) {
|
|
1052
1019
|
const {
|
|
1053
1020
|
placeholder = "Search\u2026",
|
|
1054
1021
|
hotkey = "mod+k",
|
|
1055
1022
|
maxResults = 8,
|
|
1056
|
-
groupOrder = ["work", "page"],
|
|
1023
|
+
groupOrder = ["work", "docs", "page"],
|
|
1024
|
+
// Kept for backward compat; form always renders submit
|
|
1057
1025
|
button = true,
|
|
1058
|
-
//
|
|
1026
|
+
// eslint-disable-line no-unused-vars
|
|
1059
1027
|
buttonLabel = "Search",
|
|
1060
1028
|
label,
|
|
1061
1029
|
searchPath = "/search"
|
|
@@ -1063,20 +1031,443 @@ function MdxSearchFormModal(props = {}) {
|
|
|
1063
1031
|
const text = typeof label === "string" && label.trim() ? label.trim() : buttonLabel;
|
|
1064
1032
|
const resolvedSearchPath = resolveSearchPath(searchPath);
|
|
1065
1033
|
const data = { placeholder, hotkey, maxResults, groupOrder, label: text, searchPath: resolvedSearchPath };
|
|
1066
|
-
return /* @__PURE__ */
|
|
1034
|
+
return /* @__PURE__ */ React13.createElement("div", { "data-canopy-search-form": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React13.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React13.createElement(SearchPanelForm, { placeholder, buttonLabel, label, searchPath: resolvedSearchPath }), /* @__PURE__ */ React13.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React13.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
|
|
1067
1035
|
}
|
|
1068
1036
|
|
|
1069
|
-
// ui/src/
|
|
1037
|
+
// ui/src/layout/CanopyBrand.jsx
|
|
1038
|
+
import React14 from "react";
|
|
1039
|
+
function CanopyBrand(props = {}) {
|
|
1040
|
+
const {
|
|
1041
|
+
labelId,
|
|
1042
|
+
label = "Canopy IIIF",
|
|
1043
|
+
href = "/",
|
|
1044
|
+
className,
|
|
1045
|
+
Logo
|
|
1046
|
+
} = props || {};
|
|
1047
|
+
const spanProps = labelId ? { id: labelId } : {};
|
|
1048
|
+
const classes = ["canopy-logo", className].filter(Boolean).join(" ");
|
|
1049
|
+
return /* @__PURE__ */ React14.createElement("a", { href, className: classes }, typeof Logo === "function" ? /* @__PURE__ */ React14.createElement(Logo, null) : null, /* @__PURE__ */ React14.createElement("span", { ...spanProps }, label));
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
// ui/src/layout/CanopyModal.jsx
|
|
1053
|
+
import React15 from "react";
|
|
1054
|
+
function CanopyModal(props = {}) {
|
|
1055
|
+
const {
|
|
1056
|
+
id,
|
|
1057
|
+
variant,
|
|
1058
|
+
open = false,
|
|
1059
|
+
labelledBy,
|
|
1060
|
+
label,
|
|
1061
|
+
logo: Logo,
|
|
1062
|
+
href = "/",
|
|
1063
|
+
closeLabel = "Close",
|
|
1064
|
+
closeDataAttr,
|
|
1065
|
+
onClose,
|
|
1066
|
+
onBackgroundClick,
|
|
1067
|
+
bodyClassName,
|
|
1068
|
+
padded = true,
|
|
1069
|
+
className,
|
|
1070
|
+
children
|
|
1071
|
+
} = props;
|
|
1072
|
+
const rootClassName = ["canopy-modal", variant ? `canopy-modal--${variant}` : null, className].filter(Boolean).join(" ");
|
|
1073
|
+
const modalProps = {
|
|
1074
|
+
id,
|
|
1075
|
+
className: rootClassName,
|
|
1076
|
+
role: "dialog",
|
|
1077
|
+
"aria-modal": "true",
|
|
1078
|
+
"aria-hidden": open ? "false" : "true",
|
|
1079
|
+
"data-open": open ? "true" : "false"
|
|
1080
|
+
};
|
|
1081
|
+
if (variant) modalProps["data-canopy-modal"] = variant;
|
|
1082
|
+
const resolvedLabelId = labelledBy || (label ? `${variant || "modal"}-label` : void 0);
|
|
1083
|
+
if (resolvedLabelId) modalProps["aria-labelledby"] = resolvedLabelId;
|
|
1084
|
+
if (typeof onBackgroundClick === "function") {
|
|
1085
|
+
modalProps.onClick = (event) => {
|
|
1086
|
+
if (event.target === event.currentTarget) onBackgroundClick(event);
|
|
1087
|
+
};
|
|
1088
|
+
}
|
|
1089
|
+
const closeButtonProps = {
|
|
1090
|
+
type: "button",
|
|
1091
|
+
className: "canopy-modal__close",
|
|
1092
|
+
"aria-label": closeLabel
|
|
1093
|
+
};
|
|
1094
|
+
if (typeof closeDataAttr === "string" && closeDataAttr) {
|
|
1095
|
+
closeButtonProps["data-canopy-header-close"] = closeDataAttr;
|
|
1096
|
+
}
|
|
1097
|
+
if (typeof onClose === "function") {
|
|
1098
|
+
closeButtonProps.onClick = onClose;
|
|
1099
|
+
}
|
|
1100
|
+
const bodyClasses = ["canopy-modal__body"];
|
|
1101
|
+
if (padded) bodyClasses.push("canopy-modal__body--padded");
|
|
1102
|
+
if (bodyClassName) bodyClasses.push(bodyClassName);
|
|
1103
|
+
const bodyClassNameValue = bodyClasses.join(" ");
|
|
1104
|
+
return /* @__PURE__ */ React15.createElement("div", { ...modalProps }, /* @__PURE__ */ React15.createElement("div", { className: "canopy-modal__panel" }, /* @__PURE__ */ React15.createElement("button", { ...closeButtonProps }, /* @__PURE__ */ React15.createElement(
|
|
1105
|
+
"svg",
|
|
1106
|
+
{
|
|
1107
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1108
|
+
viewBox: "0 0 24 24",
|
|
1109
|
+
fill: "none",
|
|
1110
|
+
stroke: "currentColor",
|
|
1111
|
+
strokeWidth: "1.5",
|
|
1112
|
+
className: "canopy-modal__close-icon"
|
|
1113
|
+
},
|
|
1114
|
+
/* @__PURE__ */ React15.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 6l12 12M6 18L18 6" })
|
|
1115
|
+
), /* @__PURE__ */ React15.createElement("span", { className: "sr-only" }, closeLabel)), /* @__PURE__ */ React15.createElement("div", { className: bodyClassNameValue }, label ? /* @__PURE__ */ React15.createElement("div", { className: "canopy-modal__brand" }, /* @__PURE__ */ React15.createElement(
|
|
1116
|
+
CanopyBrand,
|
|
1117
|
+
{
|
|
1118
|
+
labelId: resolvedLabelId,
|
|
1119
|
+
label,
|
|
1120
|
+
href,
|
|
1121
|
+
Logo,
|
|
1122
|
+
className: "canopy-modal__brand-link"
|
|
1123
|
+
}
|
|
1124
|
+
)) : null, children)));
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
// ui/src/layout/CanopyHeader.jsx
|
|
1128
|
+
function HeaderScript() {
|
|
1129
|
+
const code = `
|
|
1130
|
+
(function () {
|
|
1131
|
+
if (typeof window === 'undefined') return;
|
|
1132
|
+
|
|
1133
|
+
var doc = document;
|
|
1134
|
+
var body = doc.body;
|
|
1135
|
+
var root = doc.documentElement;
|
|
1136
|
+
|
|
1137
|
+
function ready(fn) {
|
|
1138
|
+
if (doc.readyState === 'loading') {
|
|
1139
|
+
doc.addEventListener('DOMContentLoaded', fn, { once: true });
|
|
1140
|
+
} else {
|
|
1141
|
+
fn();
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
ready(function () {
|
|
1146
|
+
var header = doc.querySelector('.canopy-header');
|
|
1147
|
+
if (!header) return;
|
|
1148
|
+
|
|
1149
|
+
var NAV_ATTR = 'data-mobile-nav';
|
|
1150
|
+
var SEARCH_ATTR = 'data-mobile-search';
|
|
1151
|
+
|
|
1152
|
+
function modalFor(type) {
|
|
1153
|
+
return doc.querySelector('[data-canopy-modal="' + type + '"]');
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
function each(list, fn) {
|
|
1157
|
+
if (!list || typeof fn !== 'function') return;
|
|
1158
|
+
Array.prototype.forEach.call(list, fn);
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
function setExpanded(type, expanded) {
|
|
1162
|
+
var toggles = header.querySelectorAll('[data-canopy-header-toggle="' + type + '"]');
|
|
1163
|
+
each(toggles, function (btn) {
|
|
1164
|
+
btn.setAttribute('aria-expanded', expanded ? 'true' : 'false');
|
|
1165
|
+
});
|
|
1166
|
+
var modal = modalFor(type);
|
|
1167
|
+
if (modal) {
|
|
1168
|
+
modal.setAttribute('data-open', expanded ? 'true' : 'false');
|
|
1169
|
+
modal.setAttribute('aria-hidden', expanded ? 'false' : 'true');
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
function lockScroll(shouldLock) {
|
|
1174
|
+
if (!body) return;
|
|
1175
|
+
if (shouldLock) {
|
|
1176
|
+
if (!body.dataset.canopyScrollLock) {
|
|
1177
|
+
body.dataset.canopyScrollPrevOverflow = body.style.overflow || '';
|
|
1178
|
+
if (root && root.dataset) {
|
|
1179
|
+
root.dataset.canopyScrollPrevOverflow = root.style.overflow || '';
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
body.dataset.canopyScrollLock = '1';
|
|
1183
|
+
body.style.overflow = 'hidden';
|
|
1184
|
+
if (root) root.style.overflow = 'hidden';
|
|
1185
|
+
} else {
|
|
1186
|
+
if (body.dataset.canopyScrollLock) {
|
|
1187
|
+
delete body.dataset.canopyScrollLock;
|
|
1188
|
+
body.style.overflow = body.dataset.canopyScrollPrevOverflow || '';
|
|
1189
|
+
delete body.dataset.canopyScrollPrevOverflow;
|
|
1190
|
+
}
|
|
1191
|
+
if (root && root.dataset) {
|
|
1192
|
+
root.style.overflow = root.dataset.canopyScrollPrevOverflow || '';
|
|
1193
|
+
delete root.dataset.canopyScrollPrevOverflow;
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
function stateFor(type) {
|
|
1199
|
+
if (type === 'nav') return header.getAttribute(NAV_ATTR);
|
|
1200
|
+
if (type === 'search') return header.getAttribute(SEARCH_ATTR);
|
|
1201
|
+
return 'closed';
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
function focusSearchForm() {
|
|
1205
|
+
var input = header.querySelector('[data-canopy-search-form-input]');
|
|
1206
|
+
if (!input) return;
|
|
1207
|
+
var raf = typeof window !== 'undefined' && window.requestAnimationFrame;
|
|
1208
|
+
(raf || function (fn) { return setTimeout(fn, 16); })(function () {
|
|
1209
|
+
try {
|
|
1210
|
+
input.focus({ preventScroll: true });
|
|
1211
|
+
} catch (_) {
|
|
1212
|
+
try { input.focus(); } catch (_) {}
|
|
1213
|
+
}
|
|
1214
|
+
});
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
function focusNavMenu() {
|
|
1218
|
+
var modal = modalFor('nav');
|
|
1219
|
+
if (!modal) return;
|
|
1220
|
+
var target = modal.querySelector('button, a, input, [tabindex]:not([tabindex="-1"])');
|
|
1221
|
+
if (!target) return;
|
|
1222
|
+
var raf = typeof window !== 'undefined' && window.requestAnimationFrame;
|
|
1223
|
+
(raf || function (fn) { return setTimeout(fn, 16); })(function () {
|
|
1224
|
+
try {
|
|
1225
|
+
target.focus({ preventScroll: true });
|
|
1226
|
+
} catch (_) {
|
|
1227
|
+
try { target.focus(); } catch (_) {}
|
|
1228
|
+
}
|
|
1229
|
+
});
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
function setState(type, next) {
|
|
1233
|
+
if (type === 'nav') header.setAttribute(NAV_ATTR, next);
|
|
1234
|
+
if (type === 'search') header.setAttribute(SEARCH_ATTR, next);
|
|
1235
|
+
setExpanded(type, next === 'open');
|
|
1236
|
+
var navOpen = header.getAttribute(NAV_ATTR) === 'open';
|
|
1237
|
+
var searchOpen = header.getAttribute(SEARCH_ATTR) === 'open';
|
|
1238
|
+
lockScroll(navOpen || searchOpen);
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
function toggle(type, force) {
|
|
1242
|
+
var current = stateFor(type) === 'open';
|
|
1243
|
+
var shouldOpen = typeof force === 'boolean' ? force : !current;
|
|
1244
|
+
if (shouldOpen && type === 'nav') setState('search', 'closed');
|
|
1245
|
+
if (shouldOpen && type === 'search') setState('nav', 'closed');
|
|
1246
|
+
setState(type, shouldOpen ? 'open' : 'closed');
|
|
1247
|
+
if (type === 'search' && shouldOpen) focusSearchForm();
|
|
1248
|
+
if (type === 'nav' && shouldOpen) focusNavMenu();
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
each(header.querySelectorAll('[data-canopy-header-toggle]'), function (btn) {
|
|
1252
|
+
btn.addEventListener('click', function (event) {
|
|
1253
|
+
event.preventDefault();
|
|
1254
|
+
var type = btn.getAttribute('data-canopy-header-toggle');
|
|
1255
|
+
if (!type) return;
|
|
1256
|
+
toggle(type);
|
|
1257
|
+
});
|
|
1258
|
+
});
|
|
1259
|
+
|
|
1260
|
+
each(doc.querySelectorAll('[data-canopy-header-close]'), function (btn) {
|
|
1261
|
+
btn.addEventListener('click', function () {
|
|
1262
|
+
var type = btn.getAttribute('data-canopy-header-close');
|
|
1263
|
+
if (!type) return;
|
|
1264
|
+
toggle(type, false);
|
|
1265
|
+
});
|
|
1266
|
+
});
|
|
1267
|
+
|
|
1268
|
+
var navModal = modalFor('nav');
|
|
1269
|
+
if (navModal) {
|
|
1270
|
+
navModal.addEventListener('click', function (event) {
|
|
1271
|
+
if (event.target === navModal) {
|
|
1272
|
+
toggle('nav', false);
|
|
1273
|
+
return;
|
|
1274
|
+
}
|
|
1275
|
+
var target = event.target && event.target.closest && event.target.closest('a');
|
|
1276
|
+
if (!target) return;
|
|
1277
|
+
toggle('nav', false);
|
|
1278
|
+
});
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
var searchModal = modalFor('search');
|
|
1282
|
+
if (searchModal) {
|
|
1283
|
+
searchModal.addEventListener('click', function (event) {
|
|
1284
|
+
if (event.target === searchModal) toggle('search', false);
|
|
1285
|
+
});
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
doc.addEventListener('keydown', function (event) {
|
|
1289
|
+
if (event.key !== 'Escape') return;
|
|
1290
|
+
var navOpen = header.getAttribute(NAV_ATTR) === 'open';
|
|
1291
|
+
var searchOpen = header.getAttribute(SEARCH_ATTR) === 'open';
|
|
1292
|
+
if (!navOpen && !searchOpen) return;
|
|
1293
|
+
event.preventDefault();
|
|
1294
|
+
toggle('nav', false);
|
|
1295
|
+
toggle('search', false);
|
|
1296
|
+
});
|
|
1297
|
+
|
|
1298
|
+
var mq = window.matchMedia('(min-width: 48rem)');
|
|
1299
|
+
function syncDesktopState() {
|
|
1300
|
+
if (mq.matches) {
|
|
1301
|
+
setState('nav', 'closed');
|
|
1302
|
+
setState('search', 'closed');
|
|
1303
|
+
setExpanded('nav', false);
|
|
1304
|
+
setExpanded('search', false);
|
|
1305
|
+
lockScroll(false);
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
try {
|
|
1310
|
+
mq.addEventListener('change', syncDesktopState);
|
|
1311
|
+
} catch (_) {
|
|
1312
|
+
mq.addListener(syncDesktopState);
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
syncDesktopState();
|
|
1316
|
+
});
|
|
1317
|
+
})();
|
|
1318
|
+
`;
|
|
1319
|
+
return /* @__PURE__ */ React16.createElement(
|
|
1320
|
+
"script",
|
|
1321
|
+
{
|
|
1322
|
+
dangerouslySetInnerHTML: {
|
|
1323
|
+
__html: code
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
);
|
|
1327
|
+
}
|
|
1328
|
+
function ensureArray(navLinks) {
|
|
1329
|
+
if (!Array.isArray(navLinks)) return [];
|
|
1330
|
+
return navLinks.filter((link) => link && typeof link === "object" && typeof link.href === "string");
|
|
1331
|
+
}
|
|
1332
|
+
function CanopyHeader(props = {}) {
|
|
1333
|
+
const {
|
|
1334
|
+
navigation: navLinksProp,
|
|
1335
|
+
searchLabel = "Search",
|
|
1336
|
+
searchHotkey = "mod+k",
|
|
1337
|
+
searchPlaceholder = "Search\u2026",
|
|
1338
|
+
brandHref = "/",
|
|
1339
|
+
title = "Canopy IIIF",
|
|
1340
|
+
logo: SiteLogo
|
|
1341
|
+
} = props;
|
|
1342
|
+
const navLinks = ensureArray(navLinksProp);
|
|
1343
|
+
return /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement("header", { className: "canopy-header", "data-mobile-nav": "closed", "data-mobile-search": "closed" }, /* @__PURE__ */ React16.createElement("div", { className: "canopy-header__brand" }, /* @__PURE__ */ React16.createElement(
|
|
1344
|
+
CanopyBrand,
|
|
1345
|
+
{
|
|
1346
|
+
label: title,
|
|
1347
|
+
href: brandHref,
|
|
1348
|
+
className: "canopy-header__brand-link",
|
|
1349
|
+
Logo: SiteLogo
|
|
1350
|
+
}
|
|
1351
|
+
)), /* @__PURE__ */ React16.createElement("div", { className: "canopy-header__desktop-search" }, /* @__PURE__ */ React16.createElement(SearchPanel, { label: searchLabel, hotkey: searchHotkey, placeholder: searchPlaceholder })), /* @__PURE__ */ React16.createElement("nav", { className: "canopy-nav-links canopy-header__desktop-nav", "aria-label": "Primary navigation" }, navLinks.map((link) => /* @__PURE__ */ React16.createElement("a", { key: link.href, href: link.href }, link.label || link.href))), /* @__PURE__ */ React16.createElement("div", { className: "canopy-header__actions" }, /* @__PURE__ */ React16.createElement(
|
|
1352
|
+
"button",
|
|
1353
|
+
{
|
|
1354
|
+
type: "button",
|
|
1355
|
+
className: "canopy-header__icon-button canopy-header__search-trigger",
|
|
1356
|
+
"aria-label": "Open search",
|
|
1357
|
+
"aria-controls": "canopy-modal-search",
|
|
1358
|
+
"aria-expanded": "false",
|
|
1359
|
+
"data-canopy-header-toggle": "search"
|
|
1360
|
+
},
|
|
1361
|
+
/* @__PURE__ */ React16.createElement(
|
|
1362
|
+
"svg",
|
|
1363
|
+
{
|
|
1364
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1365
|
+
viewBox: "0 0 24 24",
|
|
1366
|
+
fill: "none",
|
|
1367
|
+
stroke: "currentColor",
|
|
1368
|
+
strokeWidth: "1.5",
|
|
1369
|
+
className: "canopy-header__search-icon"
|
|
1370
|
+
},
|
|
1371
|
+
/* @__PURE__ */ React16.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", 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" })
|
|
1372
|
+
)
|
|
1373
|
+
), /* @__PURE__ */ React16.createElement(
|
|
1374
|
+
"button",
|
|
1375
|
+
{
|
|
1376
|
+
type: "button",
|
|
1377
|
+
className: "canopy-header__icon-button canopy-header__menu",
|
|
1378
|
+
"aria-label": "Open navigation",
|
|
1379
|
+
"aria-controls": "canopy-modal-nav",
|
|
1380
|
+
"aria-expanded": "false",
|
|
1381
|
+
"data-canopy-header-toggle": "nav"
|
|
1382
|
+
},
|
|
1383
|
+
/* @__PURE__ */ React16.createElement(
|
|
1384
|
+
"svg",
|
|
1385
|
+
{
|
|
1386
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1387
|
+
fill: "none",
|
|
1388
|
+
viewBox: "0 0 24 24",
|
|
1389
|
+
strokeWidth: "1.5",
|
|
1390
|
+
stroke: "currentColor",
|
|
1391
|
+
className: "canopy-header__menu-icon"
|
|
1392
|
+
},
|
|
1393
|
+
/* @__PURE__ */ React16.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" })
|
|
1394
|
+
)
|
|
1395
|
+
))), /* @__PURE__ */ React16.createElement(
|
|
1396
|
+
CanopyModal,
|
|
1397
|
+
{
|
|
1398
|
+
id: "canopy-modal-nav",
|
|
1399
|
+
variant: "nav",
|
|
1400
|
+
labelledBy: "canopy-modal-nav-label",
|
|
1401
|
+
label: title,
|
|
1402
|
+
logo: SiteLogo,
|
|
1403
|
+
href: brandHref,
|
|
1404
|
+
closeLabel: "Close navigation",
|
|
1405
|
+
closeDataAttr: "nav"
|
|
1406
|
+
},
|
|
1407
|
+
/* @__PURE__ */ React16.createElement("nav", { className: "canopy-nav-links canopy-modal__nav", "aria-label": "Primary navigation" }, navLinks.map((link) => /* @__PURE__ */ React16.createElement("a", { key: link.href, href: link.href }, link.label || link.href)))
|
|
1408
|
+
), /* @__PURE__ */ React16.createElement(
|
|
1409
|
+
CanopyModal,
|
|
1410
|
+
{
|
|
1411
|
+
id: "canopy-modal-search",
|
|
1412
|
+
variant: "search",
|
|
1413
|
+
labelledBy: "canopy-modal-search-label",
|
|
1414
|
+
label: title,
|
|
1415
|
+
logo: SiteLogo,
|
|
1416
|
+
href: brandHref,
|
|
1417
|
+
closeLabel: "Close search",
|
|
1418
|
+
closeDataAttr: "search",
|
|
1419
|
+
bodyClassName: "canopy-modal__body--search"
|
|
1420
|
+
},
|
|
1421
|
+
/* @__PURE__ */ React16.createElement(SearchPanel, { label: searchLabel, hotkey: searchHotkey, placeholder: searchPlaceholder })
|
|
1422
|
+
), /* @__PURE__ */ React16.createElement(HeaderScript, null));
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
// ui/src/search/MdxSearchResults.jsx
|
|
1070
1426
|
import React17 from "react";
|
|
1071
|
-
function
|
|
1427
|
+
function MdxSearchResults(props) {
|
|
1428
|
+
let json = "{}";
|
|
1429
|
+
try {
|
|
1430
|
+
json = JSON.stringify(props || {});
|
|
1431
|
+
} catch (_) {
|
|
1432
|
+
json = "{}";
|
|
1433
|
+
}
|
|
1434
|
+
return /* @__PURE__ */ React17.createElement("div", { "data-canopy-search-results": "1" }, /* @__PURE__ */ React17.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
// ui/src/search/SearchSummary.jsx
|
|
1438
|
+
import React18 from "react";
|
|
1439
|
+
function SearchSummary(props) {
|
|
1440
|
+
let json = "{}";
|
|
1441
|
+
try {
|
|
1442
|
+
json = JSON.stringify(props || {});
|
|
1443
|
+
} catch (_) {
|
|
1444
|
+
json = "{}";
|
|
1445
|
+
}
|
|
1446
|
+
return /* @__PURE__ */ React18.createElement("div", { "data-canopy-search-summary": "1" }, /* @__PURE__ */ React18.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
// ui/src/search/MdxSearchTabs.jsx
|
|
1450
|
+
import React19 from "react";
|
|
1451
|
+
function MdxSearchTabs(props) {
|
|
1452
|
+
let json = "{}";
|
|
1453
|
+
try {
|
|
1454
|
+
json = JSON.stringify(props || {});
|
|
1455
|
+
} catch (_) {
|
|
1456
|
+
json = "{}";
|
|
1457
|
+
}
|
|
1458
|
+
return /* @__PURE__ */ React19.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React19.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
// ui/src/search-form/MdxSearchFormModal.jsx
|
|
1462
|
+
import React20 from "react";
|
|
1463
|
+
function MdxSearchFormModal(props = {}) {
|
|
1072
1464
|
const {
|
|
1073
1465
|
placeholder = "Search\u2026",
|
|
1074
1466
|
hotkey = "mod+k",
|
|
1075
1467
|
maxResults = 8,
|
|
1076
|
-
groupOrder = ["work", "
|
|
1077
|
-
// Kept for backward compat; form always renders submit
|
|
1468
|
+
groupOrder = ["work", "page"],
|
|
1078
1469
|
button = true,
|
|
1079
|
-
//
|
|
1470
|
+
// kept for backward compat; ignored by teaser form
|
|
1080
1471
|
buttonLabel = "Search",
|
|
1081
1472
|
label,
|
|
1082
1473
|
searchPath = "/search"
|
|
@@ -1084,11 +1475,11 @@ function SearchPanel(props = {}) {
|
|
|
1084
1475
|
const text = typeof label === "string" && label.trim() ? label.trim() : buttonLabel;
|
|
1085
1476
|
const resolvedSearchPath = resolveSearchPath(searchPath);
|
|
1086
1477
|
const data = { placeholder, hotkey, maxResults, groupOrder, label: text, searchPath: resolvedSearchPath };
|
|
1087
|
-
return /* @__PURE__ */
|
|
1478
|
+
return /* @__PURE__ */ React20.createElement("div", { "data-canopy-search-form": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React20.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React20.createElement(SearchPanelForm, { placeholder, buttonLabel, label, searchPath: resolvedSearchPath }), /* @__PURE__ */ React20.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React20.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
|
|
1088
1479
|
}
|
|
1089
1480
|
|
|
1090
1481
|
// ui/src/iiif/ManifestPrimitives.jsx
|
|
1091
|
-
import
|
|
1482
|
+
import React21 from "react";
|
|
1092
1483
|
import {
|
|
1093
1484
|
Label as CloverLabel,
|
|
1094
1485
|
Metadata as CloverMetadata,
|
|
@@ -1113,26 +1504,199 @@ function ensureMetadata(items) {
|
|
|
1113
1504
|
function Label({ manifest, label, ...rest }) {
|
|
1114
1505
|
const intl = label || manifest && manifest.label;
|
|
1115
1506
|
if (!hasInternationalValue(intl)) return null;
|
|
1116
|
-
return /* @__PURE__ */
|
|
1507
|
+
return /* @__PURE__ */ React21.createElement(CloverLabel, { label: intl, ...rest });
|
|
1117
1508
|
}
|
|
1118
1509
|
function Summary({ manifest, summary, ...rest }) {
|
|
1119
1510
|
const intl = summary || manifest && manifest.summary;
|
|
1120
1511
|
if (!hasInternationalValue(intl)) return null;
|
|
1121
|
-
return /* @__PURE__ */
|
|
1512
|
+
return /* @__PURE__ */ React21.createElement(CloverSummary, { summary: intl, ...rest });
|
|
1122
1513
|
}
|
|
1123
1514
|
function Metadata({ manifest, metadata, ...rest }) {
|
|
1124
1515
|
const items = ensureMetadata(metadata || manifest && manifest.metadata);
|
|
1125
1516
|
if (!items.length) return null;
|
|
1126
|
-
return /* @__PURE__ */
|
|
1517
|
+
return /* @__PURE__ */ React21.createElement(CloverMetadata, { metadata: items, ...rest });
|
|
1127
1518
|
}
|
|
1128
1519
|
function RequiredStatement({ manifest, requiredStatement, ...rest }) {
|
|
1129
1520
|
const stmt = requiredStatement || manifest && manifest.requiredStatement;
|
|
1130
1521
|
if (!stmt || !hasInternationalValue(stmt.label) || !hasInternationalValue(stmt.value)) {
|
|
1131
1522
|
return null;
|
|
1132
1523
|
}
|
|
1133
|
-
return /* @__PURE__ */
|
|
1524
|
+
return /* @__PURE__ */ React21.createElement(CloverRequiredStatement, { requiredStatement: stmt, ...rest });
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1527
|
+
// ui/src/docs/CodeBlock.jsx
|
|
1528
|
+
import React22 from "react";
|
|
1529
|
+
function parseHighlightAttr(attr) {
|
|
1530
|
+
if (!attr) return /* @__PURE__ */ new Set();
|
|
1531
|
+
const cleaned = String(attr || "").trim();
|
|
1532
|
+
if (!cleaned) return /* @__PURE__ */ new Set();
|
|
1533
|
+
const segments = cleaned.split(",").map((segment) => segment.trim()).filter(Boolean);
|
|
1534
|
+
const lines = /* @__PURE__ */ new Set();
|
|
1535
|
+
for (const segment of segments) {
|
|
1536
|
+
if (!segment) continue;
|
|
1537
|
+
if (/^\d+-\d+$/.test(segment)) {
|
|
1538
|
+
const [startRaw, endRaw] = segment.split("-");
|
|
1539
|
+
const start = Number(startRaw);
|
|
1540
|
+
const end = Number(endRaw);
|
|
1541
|
+
if (Number.isFinite(start) && Number.isFinite(end) && end >= start) {
|
|
1542
|
+
for (let i = start; i <= end; i += 1) {
|
|
1543
|
+
lines.add(i);
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
} else if (/^\d+$/.test(segment)) {
|
|
1547
|
+
const value = Number(segment);
|
|
1548
|
+
if (Number.isFinite(value)) lines.add(value);
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
return lines;
|
|
1552
|
+
}
|
|
1553
|
+
function normaliseCode(children) {
|
|
1554
|
+
if (children == null) return "";
|
|
1555
|
+
if (typeof children === "string") return children;
|
|
1556
|
+
if (Array.isArray(children)) {
|
|
1557
|
+
return children.map((child) => typeof child === "string" ? child : "").join("");
|
|
1558
|
+
}
|
|
1559
|
+
if (typeof children === "object" && typeof children.toString === "function") {
|
|
1560
|
+
return children.toString();
|
|
1561
|
+
}
|
|
1562
|
+
return "";
|
|
1563
|
+
}
|
|
1564
|
+
var baseLineStyle = {
|
|
1565
|
+
display: "block",
|
|
1566
|
+
padding: "0.125rem 1.25rem",
|
|
1567
|
+
boxSizing: "border-box"
|
|
1568
|
+
};
|
|
1569
|
+
var highlightBaseStyle = {
|
|
1570
|
+
background: "linear-gradient(to right, var(--color-brand-200, #bfdbfe), var(--color-brand-100, #bfdbfe))"
|
|
1571
|
+
};
|
|
1572
|
+
function DocsCodeBlock(props = {}) {
|
|
1573
|
+
const { children, ...rest } = props;
|
|
1574
|
+
const childArray = React22.Children.toArray(children);
|
|
1575
|
+
const codeElement = childArray.find((el) => React22.isValidElement(el));
|
|
1576
|
+
if (!codeElement || !codeElement.props) {
|
|
1577
|
+
return React22.createElement("pre", props);
|
|
1578
|
+
}
|
|
1579
|
+
const {
|
|
1580
|
+
className = "",
|
|
1581
|
+
children: codeChildren,
|
|
1582
|
+
...codeProps
|
|
1583
|
+
} = codeElement.props;
|
|
1584
|
+
const rawCode = normaliseCode(codeChildren);
|
|
1585
|
+
const trimmedCode = rawCode.endsWith("\n") ? rawCode.slice(0, -1) : rawCode;
|
|
1586
|
+
const lines = trimmedCode.split("\n");
|
|
1587
|
+
const filename = codeProps["data-filename"] || "";
|
|
1588
|
+
const highlightAttr = codeProps["data-highlight"] || "";
|
|
1589
|
+
const highlightSet = parseHighlightAttr(highlightAttr);
|
|
1590
|
+
const copyAttr = codeProps["data-copy"];
|
|
1591
|
+
const enableCopy = copyAttr !== void 0 ? copyAttr === true || copyAttr === "true" || copyAttr === "" : false;
|
|
1592
|
+
const [copied, setCopied] = React22.useState(false);
|
|
1593
|
+
const handleCopy = React22.useCallback(async () => {
|
|
1594
|
+
const text = rawCode;
|
|
1595
|
+
try {
|
|
1596
|
+
if (typeof navigator !== "undefined" && navigator.clipboard && navigator.clipboard.writeText) {
|
|
1597
|
+
await navigator.clipboard.writeText(text);
|
|
1598
|
+
} else {
|
|
1599
|
+
const textarea = document.createElement("textarea");
|
|
1600
|
+
textarea.value = text;
|
|
1601
|
+
textarea.setAttribute("readonly", "");
|
|
1602
|
+
textarea.style.position = "absolute";
|
|
1603
|
+
textarea.style.left = "-9999px";
|
|
1604
|
+
document.body.appendChild(textarea);
|
|
1605
|
+
textarea.select();
|
|
1606
|
+
document.execCommand("copy");
|
|
1607
|
+
document.body.removeChild(textarea);
|
|
1608
|
+
}
|
|
1609
|
+
setCopied(true);
|
|
1610
|
+
setTimeout(() => setCopied(false), 1500);
|
|
1611
|
+
} catch (_) {
|
|
1612
|
+
setCopied(false);
|
|
1613
|
+
}
|
|
1614
|
+
}, [rawCode]);
|
|
1615
|
+
const containerStyle = {
|
|
1616
|
+
borderRadius: "12px",
|
|
1617
|
+
overflow: "hidden",
|
|
1618
|
+
margin: "1.5rem 0",
|
|
1619
|
+
background: "var(--color-brand-100, #e0f2ff)",
|
|
1620
|
+
fontFamily: "var(--font-mono)",
|
|
1621
|
+
fontSize: "0.85rem"
|
|
1622
|
+
};
|
|
1623
|
+
const headerStyle = {
|
|
1624
|
+
display: "flex",
|
|
1625
|
+
alignItems: "center",
|
|
1626
|
+
justifyContent: "space-between",
|
|
1627
|
+
padding: "1rem 1.25rem",
|
|
1628
|
+
fontWeight: 700,
|
|
1629
|
+
background: "var(--color-brand-200, #dbeafe)",
|
|
1630
|
+
color: "var(--color-brand-900)"
|
|
1631
|
+
};
|
|
1632
|
+
const preStyle = {
|
|
1633
|
+
margin: 0,
|
|
1634
|
+
background: "var(--color-brand-100, #e0f2ff)",
|
|
1635
|
+
color: "var(--color-brand-800, #1f2d5c)",
|
|
1636
|
+
lineHeight: 1.55,
|
|
1637
|
+
padding: "1rem 0",
|
|
1638
|
+
overflowX: "auto"
|
|
1639
|
+
};
|
|
1640
|
+
const codeStyle = {
|
|
1641
|
+
display: "block",
|
|
1642
|
+
padding: 0
|
|
1643
|
+
};
|
|
1644
|
+
const lineContentStyle = {
|
|
1645
|
+
whiteSpace: "pre",
|
|
1646
|
+
display: "inline"
|
|
1647
|
+
};
|
|
1648
|
+
const showFilename = Boolean(filename);
|
|
1649
|
+
const { style: preStyleOverride, className: preClassName, ...preRest } = rest;
|
|
1650
|
+
const mergedPreStyle = Object.assign({}, preStyle, preStyleOverride || {});
|
|
1651
|
+
const lineElements = lines.map((line, index) => {
|
|
1652
|
+
const lineNumber = index + 1;
|
|
1653
|
+
const highlight = highlightSet.has(lineNumber);
|
|
1654
|
+
const style = highlight ? { ...baseLineStyle, ...highlightBaseStyle } : baseLineStyle;
|
|
1655
|
+
const displayLine = line === "" ? " " : line;
|
|
1656
|
+
return React22.createElement(
|
|
1657
|
+
"span",
|
|
1658
|
+
{ key: lineNumber, style },
|
|
1659
|
+
React22.createElement("span", { style: lineContentStyle }, displayLine)
|
|
1660
|
+
);
|
|
1661
|
+
});
|
|
1662
|
+
return React22.createElement(
|
|
1663
|
+
"div",
|
|
1664
|
+
{ style: containerStyle },
|
|
1665
|
+
React22.createElement(
|
|
1666
|
+
"div",
|
|
1667
|
+
{ style: headerStyle },
|
|
1668
|
+
React22.createElement("span", null, showFilename ? filename : null),
|
|
1669
|
+
enableCopy ? React22.createElement(
|
|
1670
|
+
"button",
|
|
1671
|
+
{
|
|
1672
|
+
type: "button",
|
|
1673
|
+
onClick: handleCopy,
|
|
1674
|
+
style: {
|
|
1675
|
+
border: "1px solid var(--color-brand-300, #bfdbfe)",
|
|
1676
|
+
borderRadius: "6px",
|
|
1677
|
+
padding: "0.2rem 0.55rem",
|
|
1678
|
+
fontSize: "0.7rem",
|
|
1679
|
+
fontWeight: 500,
|
|
1680
|
+
background: "color-mix(in srgb, var(--color-brand-100, #e0f2ff) 55%, #ffffff)",
|
|
1681
|
+
color: "var(--color-brand-700, #1d4ed8)",
|
|
1682
|
+
cursor: "pointer"
|
|
1683
|
+
}
|
|
1684
|
+
},
|
|
1685
|
+
copied ? "Copied" : "Copy"
|
|
1686
|
+
) : null
|
|
1687
|
+
),
|
|
1688
|
+
React22.createElement(
|
|
1689
|
+
"pre",
|
|
1690
|
+
{ ...preRest, className: preClassName, style: mergedPreStyle },
|
|
1691
|
+
React22.createElement("code", { style: codeStyle }, lineElements)
|
|
1692
|
+
)
|
|
1693
|
+
);
|
|
1134
1694
|
}
|
|
1135
1695
|
export {
|
|
1696
|
+
CanopyBrand,
|
|
1697
|
+
CanopyHeader,
|
|
1698
|
+
CanopyModal,
|
|
1699
|
+
DocsCodeBlock,
|
|
1136
1700
|
HelloWorld,
|
|
1137
1701
|
interstitials_exports as Interstitials,
|
|
1138
1702
|
Label,
|