@canopy-iiif/app 0.7.9 → 0.7.11
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/build.js +20 -1
- package/lib/build/iiif.js +68 -2
- package/lib/build/mdx.js +197 -6
- package/lib/build/pages.js +7 -3
- package/lib/build/runtimes.js +66 -8
- package/lib/build/verify.js +60 -0
- package/lib/components/featured.js +144 -0
- package/lib/search/search-app.jsx +35 -13
- package/lib/search/search.js +15 -44
- package/package.json +1 -1
- package/ui/dist/index.mjs +143 -166
- package/ui/dist/index.mjs.map +4 -4
- package/ui/dist/server.mjs +212 -26
- package/ui/dist/server.mjs.map +4 -4
package/ui/dist/index.mjs
CHANGED
|
@@ -293,20 +293,8 @@ function MdxRelatedItems(props) {
|
|
|
293
293
|
return /* @__PURE__ */ React7.createElement("div", { "data-canopy-related-items": "1", className: "not-prose" }, /* @__PURE__ */ React7.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
294
294
|
}
|
|
295
295
|
|
|
296
|
-
// ui/src/search/MdxSearchForm.jsx
|
|
297
|
-
import React8 from "react";
|
|
298
|
-
function MdxSearchForm(props) {
|
|
299
|
-
let json = "{}";
|
|
300
|
-
try {
|
|
301
|
-
json = JSON.stringify(props || {});
|
|
302
|
-
} catch (_) {
|
|
303
|
-
json = "{}";
|
|
304
|
-
}
|
|
305
|
-
return /* @__PURE__ */ React8.createElement("div", { "data-canopy-search-form": "1" }, /* @__PURE__ */ React8.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
306
|
-
}
|
|
307
|
-
|
|
308
296
|
// ui/src/search/MdxSearchResults.jsx
|
|
309
|
-
import
|
|
297
|
+
import React8 from "react";
|
|
310
298
|
function MdxSearchResults(props) {
|
|
311
299
|
let json = "{}";
|
|
312
300
|
try {
|
|
@@ -314,11 +302,11 @@ function MdxSearchResults(props) {
|
|
|
314
302
|
} catch (_) {
|
|
315
303
|
json = "{}";
|
|
316
304
|
}
|
|
317
|
-
return /* @__PURE__ */
|
|
305
|
+
return /* @__PURE__ */ React8.createElement("div", { "data-canopy-search-results": "1" }, /* @__PURE__ */ React8.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
318
306
|
}
|
|
319
307
|
|
|
320
308
|
// ui/src/search/SearchSummary.jsx
|
|
321
|
-
import
|
|
309
|
+
import React9 from "react";
|
|
322
310
|
function SearchSummary(props) {
|
|
323
311
|
let json = "{}";
|
|
324
312
|
try {
|
|
@@ -326,80 +314,43 @@ function SearchSummary(props) {
|
|
|
326
314
|
} catch (_) {
|
|
327
315
|
json = "{}";
|
|
328
316
|
}
|
|
329
|
-
return /* @__PURE__ */
|
|
317
|
+
return /* @__PURE__ */ React9.createElement("div", { "data-canopy-search-summary": "1" }, /* @__PURE__ */ React9.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
330
318
|
}
|
|
331
319
|
|
|
332
|
-
// ui/src/search/
|
|
333
|
-
import
|
|
334
|
-
function
|
|
320
|
+
// ui/src/search/MdxSearchTabs.jsx
|
|
321
|
+
import React10 from "react";
|
|
322
|
+
function MdxSearchTabs(props) {
|
|
335
323
|
let json = "{}";
|
|
336
324
|
try {
|
|
337
325
|
json = JSON.stringify(props || {});
|
|
338
326
|
} catch (_) {
|
|
339
327
|
json = "{}";
|
|
340
328
|
}
|
|
341
|
-
return /* @__PURE__ */
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
// ui/src/search/SearchForm.jsx
|
|
345
|
-
import React12 from "react";
|
|
346
|
-
function SearchForm({ query, onQueryChange, type = "all", onTypeChange, types = [], counts = {} }) {
|
|
347
|
-
const orderedTypes = Array.isArray(types) ? types : [];
|
|
348
|
-
const toLabel = (t) => t && t.length ? t.charAt(0).toUpperCase() + t.slice(1) : "";
|
|
349
|
-
return /* @__PURE__ */ React12.createElement("form", { onSubmit: (e) => e.preventDefault(), className: "space-y-3" }, /* @__PURE__ */ React12.createElement(
|
|
350
|
-
"input",
|
|
351
|
-
{
|
|
352
|
-
id: "search-input",
|
|
353
|
-
type: "search",
|
|
354
|
-
value: query,
|
|
355
|
-
placeholder: "Type to search\u2026",
|
|
356
|
-
onChange: (e) => onQueryChange && onQueryChange(e.target.value),
|
|
357
|
-
className: "w-full px-3 py-2 border border-slate-300 rounded-md focus:outline-none focus:ring-2 focus:ring-brand-500 focus:border-brand-500"
|
|
358
|
-
}
|
|
359
|
-
), /* @__PURE__ */ React12.createElement("div", { role: "tablist", "aria-label": "Search types", className: "flex items-center gap-2 border-b border-slate-200" }, orderedTypes.map((t) => {
|
|
360
|
-
const active = String(type).toLowerCase() === String(t).toLowerCase();
|
|
361
|
-
const cRaw = counts && Object.prototype.hasOwnProperty.call(counts, t) ? counts[t] : void 0;
|
|
362
|
-
const c = Number.isFinite(Number(cRaw)) ? Number(cRaw) : 0;
|
|
363
|
-
return /* @__PURE__ */ React12.createElement(
|
|
364
|
-
"button",
|
|
365
|
-
{
|
|
366
|
-
key: t,
|
|
367
|
-
role: "tab",
|
|
368
|
-
"aria-selected": active,
|
|
369
|
-
type: "button",
|
|
370
|
-
onClick: () => onTypeChange && onTypeChange(t),
|
|
371
|
-
className: "px-3 py-1.5 text-sm rounded-t-md border-b-2 -mb-px transition-colors " + (active ? "border-brand-600 text-brand-700" : "border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300")
|
|
372
|
-
},
|
|
373
|
-
toLabel(t),
|
|
374
|
-
" (",
|
|
375
|
-
c,
|
|
376
|
-
")"
|
|
377
|
-
);
|
|
378
|
-
})));
|
|
329
|
+
return /* @__PURE__ */ React10.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React10.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
379
330
|
}
|
|
380
331
|
|
|
381
332
|
// ui/src/search/SearchResults.jsx
|
|
382
|
-
import
|
|
333
|
+
import React11 from "react";
|
|
383
334
|
function SearchResults({
|
|
384
335
|
results = [],
|
|
385
336
|
type = "all",
|
|
386
337
|
layout = "grid"
|
|
387
338
|
}) {
|
|
388
339
|
if (!results.length) {
|
|
389
|
-
return /* @__PURE__ */
|
|
340
|
+
return /* @__PURE__ */ React11.createElement("div", { className: "text-slate-600" }, /* @__PURE__ */ React11.createElement("em", null, "No results"));
|
|
390
341
|
}
|
|
391
342
|
if (layout === "list") {
|
|
392
|
-
return /* @__PURE__ */
|
|
343
|
+
return /* @__PURE__ */ React11.createElement("ul", { id: "search-results", className: "space-y-3" }, results.map((r, i) => {
|
|
393
344
|
const hasDims = Number.isFinite(Number(r.thumbnailWidth)) && Number(r.thumbnailWidth) > 0 && Number.isFinite(Number(r.thumbnailHeight)) && Number(r.thumbnailHeight) > 0;
|
|
394
345
|
const aspect = hasDims ? Number(r.thumbnailWidth) / Number(r.thumbnailHeight) : void 0;
|
|
395
|
-
return /* @__PURE__ */
|
|
346
|
+
return /* @__PURE__ */ React11.createElement(
|
|
396
347
|
"li",
|
|
397
348
|
{
|
|
398
349
|
key: i,
|
|
399
350
|
className: `search-result ${r.type}`,
|
|
400
351
|
"data-thumbnail-aspect-ratio": aspect
|
|
401
352
|
},
|
|
402
|
-
/* @__PURE__ */
|
|
353
|
+
/* @__PURE__ */ React11.createElement(
|
|
403
354
|
Card,
|
|
404
355
|
{
|
|
405
356
|
href: r.href,
|
|
@@ -413,17 +364,17 @@ function SearchResults({
|
|
|
413
364
|
);
|
|
414
365
|
}));
|
|
415
366
|
}
|
|
416
|
-
return /* @__PURE__ */
|
|
367
|
+
return /* @__PURE__ */ React11.createElement("div", { id: "search-results" }, /* @__PURE__ */ React11.createElement(Grid, null, results.map((r, i) => {
|
|
417
368
|
const hasDims = Number.isFinite(Number(r.thumbnailWidth)) && Number(r.thumbnailWidth) > 0 && Number.isFinite(Number(r.thumbnailHeight)) && Number(r.thumbnailHeight) > 0;
|
|
418
369
|
const aspect = hasDims ? Number(r.thumbnailWidth) / Number(r.thumbnailHeight) : void 0;
|
|
419
|
-
return /* @__PURE__ */
|
|
370
|
+
return /* @__PURE__ */ React11.createElement(
|
|
420
371
|
GridItem,
|
|
421
372
|
{
|
|
422
373
|
key: i,
|
|
423
374
|
className: `search-result ${r.type}`,
|
|
424
375
|
"data-thumbnail-aspect-ratio": aspect
|
|
425
376
|
},
|
|
426
|
-
/* @__PURE__ */
|
|
377
|
+
/* @__PURE__ */ React11.createElement(
|
|
427
378
|
Card,
|
|
428
379
|
{
|
|
429
380
|
href: r.href,
|
|
@@ -438,95 +389,107 @@ function SearchResults({
|
|
|
438
389
|
})));
|
|
439
390
|
}
|
|
440
391
|
|
|
441
|
-
// ui/src/search/
|
|
442
|
-
import
|
|
443
|
-
function
|
|
444
|
-
const
|
|
445
|
-
const
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
new Set(data.map((r) => String(r && r.type || "page")))
|
|
467
|
-
);
|
|
468
|
-
const order = ["work", "docs", "page"];
|
|
469
|
-
ts.sort((a, b) => {
|
|
470
|
-
const ia = order.indexOf(a);
|
|
471
|
-
const ib = order.indexOf(b);
|
|
472
|
-
return (ia < 0 ? 99 : ia) - (ib < 0 ? 99 : ib) || a.localeCompare(b);
|
|
473
|
-
});
|
|
474
|
-
indexRef.current = idx;
|
|
475
|
-
idToRecRef.current = idToRec;
|
|
476
|
-
setRecords(data);
|
|
477
|
-
setTypes(ts);
|
|
478
|
-
setLoading(false);
|
|
479
|
-
});
|
|
480
|
-
});
|
|
481
|
-
return () => {
|
|
482
|
-
cancelled = true;
|
|
483
|
-
};
|
|
484
|
-
}, []);
|
|
485
|
-
const results = useMemo(() => {
|
|
486
|
-
const all = idToRecRef.current;
|
|
487
|
-
if (!all || !all.length) return [];
|
|
488
|
-
const t = String(type || "all").toLowerCase();
|
|
489
|
-
if (!query) {
|
|
490
|
-
return all.filter((r) => t === "all" ? true : String(r.type).toLowerCase() === t);
|
|
491
|
-
}
|
|
492
|
-
let ids = [];
|
|
493
|
-
try {
|
|
494
|
-
ids = indexRef.current && indexRef.current.search(query, { limit: 200 }) || [];
|
|
495
|
-
} catch (_) {
|
|
496
|
-
ids = [];
|
|
497
|
-
}
|
|
498
|
-
const out = [];
|
|
499
|
-
for (const id of Array.isArray(ids) ? ids : []) {
|
|
500
|
-
const rec = all[id];
|
|
501
|
-
if (!rec) continue;
|
|
502
|
-
if (t !== "all" && String(rec.type).toLowerCase() !== t) continue;
|
|
503
|
-
out.push(rec);
|
|
504
|
-
}
|
|
505
|
-
return out;
|
|
506
|
-
}, [query, type, records]);
|
|
507
|
-
return { results, total: records.length || 0, loading, types };
|
|
392
|
+
// ui/src/search/SearchTabs.jsx
|
|
393
|
+
import React12 from "react";
|
|
394
|
+
function SearchTabs({ type = "all", onTypeChange, types = [], counts = {} }) {
|
|
395
|
+
const orderedTypes = Array.isArray(types) ? types : [];
|
|
396
|
+
const toLabel = (t) => t && t.length ? t.charAt(0).toUpperCase() + t.slice(1) : "";
|
|
397
|
+
return /* @__PURE__ */ React12.createElement("div", { role: "tablist", "aria-label": "Search types", className: "flex items-center gap-2 border-b border-slate-200" }, orderedTypes.map((t) => {
|
|
398
|
+
const active = String(type).toLowerCase() === String(t).toLowerCase();
|
|
399
|
+
const cRaw = counts && Object.prototype.hasOwnProperty.call(counts, t) ? counts[t] : void 0;
|
|
400
|
+
const c = Number.isFinite(Number(cRaw)) ? Number(cRaw) : 0;
|
|
401
|
+
return /* @__PURE__ */ React12.createElement(
|
|
402
|
+
"button",
|
|
403
|
+
{
|
|
404
|
+
key: t,
|
|
405
|
+
role: "tab",
|
|
406
|
+
"aria-selected": active,
|
|
407
|
+
type: "button",
|
|
408
|
+
onClick: () => onTypeChange && onTypeChange(t),
|
|
409
|
+
className: "px-3 py-1.5 text-sm rounded-t-md border-b-2 -mb-px transition-colors " + (active ? "border-brand-600 text-brand-700" : "border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300")
|
|
410
|
+
},
|
|
411
|
+
toLabel(t),
|
|
412
|
+
" (",
|
|
413
|
+
c,
|
|
414
|
+
")"
|
|
415
|
+
);
|
|
416
|
+
}));
|
|
508
417
|
}
|
|
509
418
|
|
|
510
|
-
// ui/src/
|
|
419
|
+
// ui/src/command/MdxCommandPalette.jsx
|
|
420
|
+
import React16 from "react";
|
|
421
|
+
|
|
422
|
+
// ui/src/Icons.jsx
|
|
423
|
+
import React13 from "react";
|
|
424
|
+
var MagnifyingGlassIcon = (props) => /* @__PURE__ */ React13.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512", ...props }, /* @__PURE__ */ React13.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" }));
|
|
425
|
+
|
|
426
|
+
// ui/src/search/SearchPanelForm.jsx
|
|
511
427
|
import React14 from "react";
|
|
512
|
-
function
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
|
|
428
|
+
function SearchPanelForm(props = {}) {
|
|
429
|
+
const {
|
|
430
|
+
placeholder = "Search\u2026",
|
|
431
|
+
buttonLabel = "Search",
|
|
432
|
+
label,
|
|
433
|
+
searchPath = "/search"
|
|
434
|
+
} = props || {};
|
|
435
|
+
const text = typeof label === "string" && label.trim() ? label.trim() : buttonLabel;
|
|
436
|
+
return /* @__PURE__ */ React14.createElement(
|
|
437
|
+
"form",
|
|
521
438
|
{
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
439
|
+
action: searchPath,
|
|
440
|
+
method: "get",
|
|
441
|
+
role: "search",
|
|
442
|
+
autoComplete: "off",
|
|
443
|
+
spellCheck: "false",
|
|
444
|
+
className: "group flex items-center gap-2 px-2 py-1.5 rounded-lg border border-slate-300 bg-white/95 backdrop-blur text-slate-700 shadow-sm hover:shadow transition w-full focus-within:ring-2 focus-within:ring-brand-500"
|
|
445
|
+
},
|
|
446
|
+
/* @__PURE__ */ React14.createElement(MagnifyingGlassIcon, { className: "w-5 h-5 text-slate-400 group-focus-within:text-brand-500" }),
|
|
447
|
+
/* @__PURE__ */ React14.createElement(
|
|
448
|
+
"input",
|
|
449
|
+
{
|
|
450
|
+
type: "search",
|
|
451
|
+
name: "q",
|
|
452
|
+
inputMode: "search",
|
|
453
|
+
"data-canopy-command-input": true,
|
|
454
|
+
placeholder,
|
|
455
|
+
className: "flex-1 bg-transparent outline-none placeholder:text-slate-400 py-0.5 min-w-0",
|
|
456
|
+
"aria-label": "Search"
|
|
457
|
+
}
|
|
458
|
+
),
|
|
459
|
+
/* @__PURE__ */ React14.createElement(
|
|
460
|
+
"button",
|
|
461
|
+
{
|
|
462
|
+
type: "submit",
|
|
463
|
+
"data-canopy-command-link": true,
|
|
464
|
+
className: "inline-flex items-center gap-1 px-2 py-1 rounded-md border border-slate-200 bg-slate-50 hover:bg-slate-100 text-slate-700"
|
|
465
|
+
},
|
|
466
|
+
/* @__PURE__ */ React14.createElement("span", null, text)
|
|
467
|
+
)
|
|
468
|
+
);
|
|
526
469
|
}
|
|
527
470
|
|
|
528
|
-
// ui/src/
|
|
471
|
+
// ui/src/search/SearchPanelTeaserResults.jsx
|
|
529
472
|
import React15 from "react";
|
|
473
|
+
function SearchPanelTeaserResults(props = {}) {
|
|
474
|
+
const { style } = props || {};
|
|
475
|
+
const baseStyle = {
|
|
476
|
+
display: "none",
|
|
477
|
+
position: "absolute",
|
|
478
|
+
left: 0,
|
|
479
|
+
right: 0,
|
|
480
|
+
top: "calc(100% + 4px)",
|
|
481
|
+
background: "#fff",
|
|
482
|
+
border: "1px solid #e5e7eb",
|
|
483
|
+
borderRadius: 8,
|
|
484
|
+
boxShadow: "0 10px 25px rgba(0,0,0,0.12)",
|
|
485
|
+
zIndex: 1e3,
|
|
486
|
+
overflow: "auto",
|
|
487
|
+
maxHeight: "60vh"
|
|
488
|
+
};
|
|
489
|
+
return /* @__PURE__ */ React15.createElement("div", { "data-canopy-command-panel": true, style: { ...baseStyle, ...style || {} } }, /* @__PURE__ */ React15.createElement("div", { id: "cplist" }));
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// ui/src/command/MdxCommandPalette.jsx
|
|
530
493
|
function MdxCommandPalette(props = {}) {
|
|
531
494
|
const {
|
|
532
495
|
placeholder = "Search\u2026",
|
|
@@ -534,20 +497,34 @@ function MdxCommandPalette(props = {}) {
|
|
|
534
497
|
maxResults = 8,
|
|
535
498
|
groupOrder = ["work", "page"],
|
|
536
499
|
button = true,
|
|
537
|
-
|
|
500
|
+
// kept for backward compat; ignored by teaser form
|
|
501
|
+
buttonLabel = "Search",
|
|
502
|
+
label,
|
|
503
|
+
searchPath = "/search"
|
|
538
504
|
} = props || {};
|
|
539
|
-
const
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
505
|
+
const text = typeof label === "string" && label.trim() ? label.trim() : buttonLabel;
|
|
506
|
+
const data = { placeholder, hotkey, maxResults, groupOrder, label: text, searchPath };
|
|
507
|
+
return /* @__PURE__ */ React16.createElement("div", { "data-canopy-command": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React16.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React16.createElement("style", null, `.relative[data-canopy-panel-auto='1']:focus-within [data-canopy-command-panel]{display:block}`), /* @__PURE__ */ React16.createElement(SearchPanelForm, { placeholder, buttonLabel, label, searchPath }), /* @__PURE__ */ React16.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React16.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// ui/src/search/SearchPanel.jsx
|
|
511
|
+
import React17 from "react";
|
|
512
|
+
function SearchPanel(props = {}) {
|
|
513
|
+
const {
|
|
514
|
+
placeholder = "Search\u2026",
|
|
515
|
+
hotkey = "mod+k",
|
|
516
|
+
maxResults = 8,
|
|
517
|
+
groupOrder = ["work", "page"],
|
|
518
|
+
// Kept for backward compat; form always renders submit
|
|
519
|
+
button = true,
|
|
520
|
+
// eslint-disable-line no-unused-vars
|
|
521
|
+
buttonLabel = "Search",
|
|
522
|
+
label,
|
|
523
|
+
searchPath = "/search"
|
|
524
|
+
} = props || {};
|
|
525
|
+
const text = typeof label === "string" && label.trim() ? label.trim() : buttonLabel;
|
|
526
|
+
const data = { placeholder, hotkey, maxResults, groupOrder, label: text, searchPath };
|
|
527
|
+
return /* @__PURE__ */ React17.createElement("div", { "data-canopy-command": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React17.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React17.createElement("style", null, `.relative[data-canopy-panel-auto='1']:focus-within [data-canopy-command-panel]{display:block}`), /* @__PURE__ */ React17.createElement(SearchPanelForm, { placeholder, buttonLabel, label, searchPath }), /* @__PURE__ */ React17.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React17.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
|
|
551
528
|
}
|
|
552
529
|
export {
|
|
553
530
|
Card,
|
|
@@ -557,15 +534,15 @@ export {
|
|
|
557
534
|
GridItem,
|
|
558
535
|
HelloWorld,
|
|
559
536
|
MdxRelatedItems as RelatedItems,
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
537
|
+
SearchPanel,
|
|
538
|
+
SearchPanelForm,
|
|
539
|
+
SearchPanelTeaserResults,
|
|
563
540
|
MdxSearchResults as SearchResults,
|
|
564
541
|
SearchResults as SearchResultsUI,
|
|
565
542
|
SearchSummary,
|
|
566
|
-
|
|
543
|
+
MdxSearchTabs as SearchTabs,
|
|
544
|
+
SearchTabs as SearchTabsUI,
|
|
567
545
|
Slider,
|
|
568
|
-
Viewer
|
|
569
|
-
useSearch
|
|
546
|
+
Viewer
|
|
570
547
|
};
|
|
571
548
|
//# sourceMappingURL=index.mjs.map
|
package/ui/dist/index.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/Fallback.jsx", "../src/HelloWorld.jsx", "../src/layout/Card.jsx", "../src/layout/Grid.jsx", "../src/iiif/Viewer.jsx", "../src/iiif/Slider.jsx", "../src/iiif/MdxRelatedItems.jsx", "../src/search/
|
|
4
|
-
"sourcesContent": ["import React from 'react';\n\nexport function Fallback({ name, ...props }) {\n const style = {\n padding: '0.75rem 1rem',\n border: '1px dashed #d1d5db',\n color: '#6b7280',\n borderRadius: 6,\n background: '#f9fafb',\n fontSize: 14,\n };\n return (\n <div style={style} data-fallback-component={name || 'Unknown'}>\n <strong>{name || 'Unknown component'}</strong> not available in UI.\n </div>\n );\n}\n\n", "import React from \"react\";\n\nexport const HelloWorld = () => {\n return <div>Hello, World!</div>;\n};\n", "import React, { useEffect, useRef, useState } from \"react\";\n\n/**\n * Card\n *\n * Renders an anchor wrapping a figure with an image and caption.\n * Minimal styling; consumers can override via className/style.\n *\n * Props:\n * - href: string (required) \u2014 link target\n * - src: string (optional) \u2014 image source\n * - alt: string (optional) \u2014 image alt text (falls back to title)\n * - title: string (optional) \u2014 primary caption text\n * - subtitle: string (optional) \u2014 secondary caption text\n * - className: string (optional)\n * - style: object (optional)\n * - children: ReactNode (optional) \u2014 appended inside figcaption\n */\nexport default function Card({\n href,\n src,\n alt,\n title,\n subtitle,\n // Optional intrinsic dimensions or aspect ratio to compute a responsive height\n imgWidth,\n imgHeight,\n aspectRatio,\n className,\n style,\n children,\n ...rest\n}) {\n const containerRef = useRef(null);\n const [inView, setInView] = useState(false);\n const [imageLoaded, setImageLoaded] = useState(false);\n\n /**\n * Use IntersectionObserver to detect when the card enters the viewport.\n * When in view, setInView(true) to trigger image loading.\n * If IntersectionObserver is not supported, default to inView=true.\n */\n useEffect(() => {\n if (!containerRef.current) return;\n if (typeof IntersectionObserver !== \"function\") {\n setInView(true);\n return;\n }\n const el = containerRef.current;\n const obs = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (entry.isIntersecting) {\n setInView(true);\n try {\n obs.unobserve(el);\n } catch (_) {}\n break;\n }\n }\n },\n { root: null, rootMargin: \"100px\", threshold: 0.1 }\n );\n try {\n obs.observe(el);\n } catch (_) {}\n return () => {\n try {\n obs.disconnect();\n } catch (_) {}\n };\n }, []);\n\n /**\n * Calculate aspect ratio and padding percent for responsive image container.\n */\n const w = Number(imgWidth);\n const h = Number(imgHeight);\n const ratio =\n Number.isFinite(Number(aspectRatio)) && Number(aspectRatio) > 0\n ? Number(aspectRatio)\n : Number.isFinite(w) && w > 0 && Number.isFinite(h) && h > 0\n ? w / h\n : undefined;\n const paddingPercent = ratio ? 100 / ratio : 100;\n\n /**\n * Caption element (figcaption), rendered if title, subtitle, or children are provided.\n */\n const caption = (\n <figcaption>\n {title && <span>{title}</span>}\n {subtitle && <span>{subtitle}</span>}\n {children}\n </figcaption>\n );\n\n return (\n <a\n href={href}\n className={[\"canopy-card\", className].filter(Boolean).join(\" \")}\n style={style}\n ref={containerRef}\n data-aspect-ratio={ratio}\n data-in-view={inView ? \"true\" : \"false\"}\n data-image-loaded={imageLoaded ? \"true\" : \"false\"}\n {...rest}\n >\n <figure>\n {src ? (\n ratio ? (\n <div\n className=\"canopy-card-media\"\n style={{ \"--canopy-card-padding\": `${paddingPercent}%` }}\n >\n {inView ? (\n <img\n src={src}\n alt={alt || title || \"\"}\n loading=\"lazy\"\n onLoad={() => setImageLoaded(true)}\n onError={() => setImageLoaded(true)}\n />\n ) : null}\n </div>\n ) : (\n <img\n src={src}\n alt={alt || title || \"\"}\n loading=\"lazy\"\n onLoad={() => setImageLoaded(true)}\n onError={() => setImageLoaded(true)}\n className=\"canopy-card-image\"\n />\n )\n ) : null}\n {caption}\n </figure>\n </a>\n );\n}\n", "import Masonry from \"react-masonry-css\";\nimport React from \"react\";\n\n// Simple item wrapper to provide consistent spacing between items.\nexport function GridItem({ children, className = \"\", style = {}, ...rest }) {\n return (\n <div\n className={`canopy-grid-item ${className}`.trim()}\n style={style}\n {...rest}\n >\n {children}\n </div>\n );\n}\n\n/**\n * Grid (Masonry)\n *\n * Lightweight wrapper around `react-masonry-css` with sensible defaults\n * and inline styles so it works without a global CSS pipeline.\n *\n * Props:\n * - breakpointCols: number | object \u2014 columns per breakpoint (react-masonry-css prop)\n * - gap: CSS length string \u2014 spacing between items/columns (default '1rem')\n * - paddingY: CSS length string \u2014 vertical padding for the grid (default '0')\n * - className, style \u2014 forwarded to container\n * - columnClassName \u2014 forwarded to Masonry (defaults to 'canopy-grid-column')\n * - children \u2014 usually a list of <GridItem> elements\n */\nexport default function Grid({\n breakpointCols,\n gap = \"2rem\",\n paddingY = \"0\",\n className = \"\",\n style = {},\n columnClassName = \"canopy-grid-column\",\n children,\n ...rest\n}) {\n const cols = breakpointCols || {\n default: 6,\n 1280: 5,\n 1024: 4,\n 768: 3,\n 640: 2,\n };\n const vars = { \"--grid-gap\": gap, \"--grid-padding-y\": paddingY };\n\n return (\n <div className=\"canopy-grid-wrap\">\n {/* Scoped styles so the component works standalone */}\n <style\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{\n __html: `\n .canopy-grid { display: flex; width: auto; position: relative; padding: var(--grid-padding-y, 0) 0; z-index: 1; }\n .canopy-grid .${columnClassName} { margin-left: var(--grid-gap, 1rem); }\n .canopy-grid .${columnClassName}:first-child { margin-left: 0; }\n .canopy-grid-item { margin-bottom: var(--grid-gap, 1rem); }\n `,\n }}\n />\n <Masonry\n breakpointCols={cols}\n className={`canopy-grid ${className}`.trim()}\n columnClassName={columnClassName}\n style={{ ...vars, ...style }}\n {...rest}\n >\n {children}\n </Masonry>\n </div>\n );\n}\n", "import React, { useEffect, useState } from \"react\";\n\n// SSR-safe wrapper around Clover's viewer. Clover touches the DOM at import time,\n// so we dynamically import it only in the browser.\n\n// Default Clover viewer options; can be overridden per-usage via props.options\nconst DEFAULT_VIEWER_OPTIONS = {\n showDownload: false,\n showIIIFBadge: false,\n showTitle: false,\n informationPanel: {\n open: false,\n renderAbout: false,\n renderToggle: false,\n },\n};\n\nfunction isPlainObject(val) {\n return val && typeof val === \"object\" && !Array.isArray(val);\n}\n\nfunction deepMerge(base, override) {\n if (!isPlainObject(base)) return override;\n const out = { ...base };\n if (!isPlainObject(override)) return out;\n for (const key of Object.keys(override)) {\n const a = base[key];\n const b = override[key];\n if (isPlainObject(a) && isPlainObject(b)) out[key] = deepMerge(a, b);\n else out[key] = b;\n }\n return out;\n}\n\nexport const Viewer = (props) => {\n const [CloverViewer, setCloverViewer] = useState(null);\n const mergedOptions = deepMerge(\n DEFAULT_VIEWER_OPTIONS,\n props && props.options\n );\n\n useEffect(() => {\n let mounted = true;\n const canUseDom =\n typeof window !== \"undefined\" && typeof document !== \"undefined\";\n if (canUseDom) {\n import(\"@samvera/clover-iiif/viewer\")\n .then((mod) => {\n if (!mounted) return;\n // Loaded Clover viewer dynamically in the browser\n const Comp = mod && (mod.default || mod.Viewer || mod);\n setCloverViewer(() => Comp);\n })\n .catch(() => {\n // Silently ignore load errors on the server or if Clover is unavailable\n });\n }\n return () => {\n mounted = false;\n };\n }, []);\n\n if (!CloverViewer) {\n // SSR placeholder for client hydration; props provided as JSON\n let json = \"{}\";\n try {\n const p = { ...(props || {}) };\n if (mergedOptions) p.options = mergedOptions;\n json = JSON.stringify(p);\n } catch (_) {\n json = \"{}\";\n }\n return (\n <div data-canopy-viewer=\"1\" className=\"not-prose\">\n <script\n type=\"application/json\"\n dangerouslySetInnerHTML={{ __html: json }}\n />\n </div>\n );\n }\n return <CloverViewer {...props} options={mergedOptions} />;\n};\n", "import React, { useEffect, useState } from \"react\";\n\n// SSR-safe wrapper around Clover's slider. Clover touches the DOM at import time,\n// so we dynamically import it only in the browser.\nexport const Slider = (props) => {\n const [CloverSlider, setCloverSlider] = useState(null);\n\n useEffect(() => {\n let mounted = true;\n const canUseDom =\n typeof window !== \"undefined\" && typeof document !== \"undefined\";\n if (canUseDom) {\n import(\"@samvera/clover-iiif/slider\")\n .then((mod) => {\n if (!mounted) return;\n console.log(mod);\n const Comp = mod && (mod.default || mod.Slider || mod);\n setCloverSlider(() => Comp);\n })\n .catch(() => {\n // Silently ignore load errors on the server or if Clover is unavailable\n });\n }\n return () => {\n mounted = false;\n };\n }, []);\n\n if (!CloverSlider) {\n // SSR placeholder for client hydration; props provided as JSON\n let json = \"{}\";\n try {\n json = JSON.stringify(props || {});\n } catch (_) {\n json = \"{}\";\n }\n return (\n <div data-canopy-slider=\"1\" className=\"not-prose\">\n <script\n type=\"application/json\"\n dangerouslySetInnerHTML={{ __html: json }}\n />\n </div>\n );\n }\n return <CloverSlider {...props} />;\n};\n", "import React from 'react';\n\n// SSR-safe placeholder for RelatedItems. Hydrated by canopy-related-items.js + canopy-slider.js\nexport default function MdxRelatedItems(props) {\n let json = '{}';\n try {\n json = JSON.stringify(props || {});\n } catch (_) {\n json = '{}';\n }\n return (\n <div data-canopy-related-items=\"1\" className=\"not-prose\">\n <script type=\"application/json\" dangerouslySetInnerHTML={{ __html: json }} />\n </div>\n );\n}\n", "import React from 'react';\n\nexport default function MdxSearchForm(props) {\n let json = '{}';\n try { json = JSON.stringify(props || {}); } catch (_) { json = '{}'; }\n return (\n <div data-canopy-search-form=\"1\">\n <script type=\"application/json\" dangerouslySetInnerHTML={{ __html: json }} />\n </div>\n );\n}\n\n", "import React from 'react';\n\nexport default function MdxSearchResults(props) {\n let json = '{}';\n try { json = JSON.stringify(props || {}); } catch (_) { json = '{}'; }\n return (\n <div data-canopy-search-results=\"1\">\n <script type=\"application/json\" dangerouslySetInnerHTML={{ __html: json }} />\n </div>\n );\n}\n\n", "import React from 'react';\n\nexport default function SearchSummary(props) {\n let json = '{}';\n try { json = JSON.stringify(props || {}); } catch (_) { json = '{}'; }\n return (\n <div data-canopy-search-summary=\"1\">\n <script type=\"application/json\" dangerouslySetInnerHTML={{ __html: json }} />\n </div>\n );\n}\n\n", "import React from 'react';\n\nexport default function SearchTotal(props) {\n let json = '{}';\n try { json = JSON.stringify(props || {}); } catch (_) { json = '{}'; }\n return (\n <div data-canopy-search-total=\"1\">\n <script type=\"application/json\" dangerouslySetInnerHTML={{ __html: json }} />\n </div>\n );\n}\n\n", "import React from 'react';\n\nexport default function SearchForm({ query, onQueryChange, type = 'all', onTypeChange, types = [], counts = {} }) {\n const orderedTypes = Array.isArray(types) ? types : [];\n const toLabel = (t) => (t && t.length ? t.charAt(0).toUpperCase() + t.slice(1) : '');\n return (\n <form onSubmit={(e) => e.preventDefault()} className=\"space-y-3\">\n <input\n id=\"search-input\"\n type=\"search\"\n value={query}\n placeholder=\"Type to search\u2026\"\n onChange={(e) => onQueryChange && onQueryChange(e.target.value)}\n className=\"w-full px-3 py-2 border border-slate-300 rounded-md focus:outline-none focus:ring-2 focus:ring-brand-500 focus:border-brand-500\"\n />\n <div role=\"tablist\" aria-label=\"Search types\" className=\"flex items-center gap-2 border-b border-slate-200\">\n {orderedTypes.map((t) => {\n const active = String(type).toLowerCase() === String(t).toLowerCase();\n const cRaw = (counts && Object.prototype.hasOwnProperty.call(counts, t)) ? counts[t] : undefined;\n const c = Number.isFinite(Number(cRaw)) ? Number(cRaw) : 0;\n return (\n <button\n key={t}\n role=\"tab\"\n aria-selected={active}\n type=\"button\"\n onClick={() => onTypeChange && onTypeChange(t)}\n className={\n 'px-3 py-1.5 text-sm rounded-t-md border-b-2 -mb-px transition-colors ' +\n (active\n ? 'border-brand-600 text-brand-700'\n : 'border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300')\n }\n >\n {toLabel(t)} ({c})\n </button>\n );\n })}\n </div>\n </form>\n );\n}\n", "import Grid, { GridItem } from \"../layout/Grid.jsx\";\n\nimport Card from \"../layout/Card.jsx\";\nimport React from \"react\";\n\nexport default function SearchResults({\n results = [],\n type = \"all\",\n layout = \"grid\",\n}) {\n if (!results.length) {\n return (\n <div className=\"text-slate-600\">\n <em>No results</em>\n </div>\n );\n }\n\n if (layout === \"list\") {\n return (\n <ul id=\"search-results\" className=\"space-y-3\">\n {results.map((r, i) => {\n const hasDims =\n Number.isFinite(Number(r.thumbnailWidth)) &&\n Number(r.thumbnailWidth) > 0 &&\n Number.isFinite(Number(r.thumbnailHeight)) &&\n Number(r.thumbnailHeight) > 0;\n const aspect = hasDims\n ? Number(r.thumbnailWidth) / Number(r.thumbnailHeight)\n : undefined;\n return (\n <li\n key={i}\n className={`search-result ${r.type}`}\n data-thumbnail-aspect-ratio={aspect}\n >\n <Card\n href={r.href}\n title={r.title || r.href}\n src={r.type === \"work\" ? r.thumbnail : undefined}\n imgWidth={r.thumbnailWidth}\n imgHeight={r.thumbnailHeight}\n aspectRatio={aspect}\n />\n </li>\n );\n })}\n </ul>\n );\n }\n\n // Default: grid (masonry)\n return (\n <div id=\"search-results\">\n <Grid>\n {results.map((r, i) => {\n const hasDims =\n Number.isFinite(Number(r.thumbnailWidth)) &&\n Number(r.thumbnailWidth) > 0 &&\n Number.isFinite(Number(r.thumbnailHeight)) &&\n Number(r.thumbnailHeight) > 0;\n const aspect = hasDims\n ? Number(r.thumbnailWidth) / Number(r.thumbnailHeight)\n : undefined;\n return (\n <GridItem\n key={i}\n className={`search-result ${r.type}`}\n data-thumbnail-aspect-ratio={aspect}\n >\n <Card\n href={r.href}\n title={r.title || r.href}\n src={r.type === \"work\" ? r.thumbnail : undefined}\n imgWidth={r.thumbnailWidth}\n imgHeight={r.thumbnailHeight}\n aspectRatio={aspect}\n />\n </GridItem>\n );\n })}\n </Grid>\n </div>\n );\n}\n", "import { useEffect, useMemo, useRef, useState } from 'react';\n\n// Minimal search hook using FlexSearch to index titles and filter by type.\n// Usage: const { results, total, loading, types } = useSearch(query, type);\n// - query: string\n// - type: string ('all' | 'work' | 'page' | 'docs' | ...)\n// Returns:\n// - results: array of records { title, href, type, thumbnail? }\n// - total: total records in index\n// - loading: boolean\n// - types: array of available types (sorted)\nexport function useSearch(query, type) {\n const [records, setRecords] = useState([]);\n const [loading, setLoading] = useState(true);\n const indexRef = useRef(null);\n const idToRecRef = useRef([]);\n const [types, setTypes] = useState([]);\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n import('flexsearch').then((mod) => {\n const FlexSearch = mod.default || mod;\n return fetch('./search-index.json')\n .then((r) => (r.ok ? r.json() : []))\n .catch(() => [])\n .then((data) => {\n if (cancelled) return;\n const idx = new FlexSearch.Index({ tokenize: 'forward' });\n const idToRec = [];\n data.forEach((rec, i) => {\n try {\n idx.add(i, rec && rec.title ? String(rec.title) : '');\n } catch (_) {}\n idToRec[i] = rec || {};\n });\n const ts = Array.from(\n new Set(data.map((r) => String((r && r.type) || 'page')))\n );\n const order = ['work', 'docs', 'page'];\n ts.sort((a, b) => {\n const ia = order.indexOf(a);\n const ib = order.indexOf(b);\n return (ia < 0 ? 99 : ia) - (ib < 0 ? 99 : ib) || a.localeCompare(b);\n });\n indexRef.current = idx;\n idToRecRef.current = idToRec;\n setRecords(data);\n setTypes(ts);\n setLoading(false);\n });\n });\n return () => {\n cancelled = true;\n };\n }, []);\n\n const results = useMemo(() => {\n const all = idToRecRef.current;\n if (!all || !all.length) return [];\n const t = String(type || 'all').toLowerCase();\n if (!query) {\n return all.filter((r) => (t === 'all' ? true : String(r.type).toLowerCase() === t));\n }\n let ids = [];\n try {\n ids = (indexRef.current && indexRef.current.search(query, { limit: 200 })) || [];\n } catch (_) {\n ids = [];\n }\n const out = [];\n for (const id of Array.isArray(ids) ? ids : []) {\n const rec = all[id];\n if (!rec) continue;\n if (t !== 'all' && String(rec.type).toLowerCase() !== t) continue;\n out.push(rec);\n }\n return out;\n }, [query, type, records]);\n\n return { results, total: records.length || 0, loading, types };\n}\n\n", "import React from \"react\";\n\n// SSR-friendly placeholder for the React Search app.\n// The actual app mounts from site/search.js into this element.\nexport default function Search(props) {\n let json = \"{}\";\n try {\n json = JSON.stringify(props || {});\n } catch (_) {\n json = \"{}\";\n }\n return (\n <div data-canopy-search=\"1\" className=\"not-prose\">\n <script\n type=\"application/json\"\n dangerouslySetInnerHTML={{ __html: json }}\n />\n </div>\n );\n}\n", "import React from 'react';\n\n// SSR-safe placeholder for the command palette. The real UI mounts client-side.\nexport default function MdxCommandPalette(props = {}) {\n const {\n placeholder = 'Search\u2026',\n hotkey = 'mod+k',\n maxResults = 8,\n groupOrder = ['work', 'page'],\n button = true,\n buttonLabel = 'Search',\n } = props || {};\n\n const data = { placeholder, hotkey, maxResults, groupOrder };\n return (\n <div data-canopy-command>\n {/* Optional trigger button shown in the header layout */}\n {button && (\n <button\n type=\"button\"\n data-canopy-command-trigger\n className=\"inline-flex items-center gap-1 px-2 py-1 rounded border border-slate-300 text-slate-700 hover:bg-slate-50\"\n aria-label=\"Open search\"\n >\n <span aria-hidden>\u2318K</span>\n <span className=\"sr-only\">{buttonLabel}</span>\n </button>\n )}\n <script type=\"application/json\" dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }} />\n </div>\n );\n}\n\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["React", "React", "React", "React", "useEffect", "useState", "React", "useEffect", "useState", "React", "React", "React", "React", "React", "React", "React", "
|
|
3
|
+
"sources": ["../src/Fallback.jsx", "../src/HelloWorld.jsx", "../src/layout/Card.jsx", "../src/layout/Grid.jsx", "../src/iiif/Viewer.jsx", "../src/iiif/Slider.jsx", "../src/iiif/MdxRelatedItems.jsx", "../src/search/MdxSearchResults.jsx", "../src/search/SearchSummary.jsx", "../src/search/MdxSearchTabs.jsx", "../src/search/SearchResults.jsx", "../src/search/SearchTabs.jsx", "../src/command/MdxCommandPalette.jsx", "../src/Icons.jsx", "../src/search/SearchPanelForm.jsx", "../src/search/SearchPanelTeaserResults.jsx", "../src/search/SearchPanel.jsx"],
|
|
4
|
+
"sourcesContent": ["import React from 'react';\n\nexport function Fallback({ name, ...props }) {\n const style = {\n padding: '0.75rem 1rem',\n border: '1px dashed #d1d5db',\n color: '#6b7280',\n borderRadius: 6,\n background: '#f9fafb',\n fontSize: 14,\n };\n return (\n <div style={style} data-fallback-component={name || 'Unknown'}>\n <strong>{name || 'Unknown component'}</strong> not available in UI.\n </div>\n );\n}\n\n", "import React from \"react\";\n\nexport const HelloWorld = () => {\n return <div>Hello, World!</div>;\n};\n", "import React, { useEffect, useRef, useState } from \"react\";\n\n/**\n * Card\n *\n * Renders an anchor wrapping a figure with an image and caption.\n * Minimal styling; consumers can override via className/style.\n *\n * Props:\n * - href: string (required) \u2014 link target\n * - src: string (optional) \u2014 image source\n * - alt: string (optional) \u2014 image alt text (falls back to title)\n * - title: string (optional) \u2014 primary caption text\n * - subtitle: string (optional) \u2014 secondary caption text\n * - className: string (optional)\n * - style: object (optional)\n * - children: ReactNode (optional) \u2014 appended inside figcaption\n */\nexport default function Card({\n href,\n src,\n alt,\n title,\n subtitle,\n // Optional intrinsic dimensions or aspect ratio to compute a responsive height\n imgWidth,\n imgHeight,\n aspectRatio,\n className,\n style,\n children,\n ...rest\n}) {\n const containerRef = useRef(null);\n const [inView, setInView] = useState(false);\n const [imageLoaded, setImageLoaded] = useState(false);\n\n /**\n * Use IntersectionObserver to detect when the card enters the viewport.\n * When in view, setInView(true) to trigger image loading.\n * If IntersectionObserver is not supported, default to inView=true.\n */\n useEffect(() => {\n if (!containerRef.current) return;\n if (typeof IntersectionObserver !== \"function\") {\n setInView(true);\n return;\n }\n const el = containerRef.current;\n const obs = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (entry.isIntersecting) {\n setInView(true);\n try {\n obs.unobserve(el);\n } catch (_) {}\n break;\n }\n }\n },\n { root: null, rootMargin: \"100px\", threshold: 0.1 }\n );\n try {\n obs.observe(el);\n } catch (_) {}\n return () => {\n try {\n obs.disconnect();\n } catch (_) {}\n };\n }, []);\n\n /**\n * Calculate aspect ratio and padding percent for responsive image container.\n */\n const w = Number(imgWidth);\n const h = Number(imgHeight);\n const ratio =\n Number.isFinite(Number(aspectRatio)) && Number(aspectRatio) > 0\n ? Number(aspectRatio)\n : Number.isFinite(w) && w > 0 && Number.isFinite(h) && h > 0\n ? w / h\n : undefined;\n const paddingPercent = ratio ? 100 / ratio : 100;\n\n /**\n * Caption element (figcaption), rendered if title, subtitle, or children are provided.\n */\n const caption = (\n <figcaption>\n {title && <span>{title}</span>}\n {subtitle && <span>{subtitle}</span>}\n {children}\n </figcaption>\n );\n\n return (\n <a\n href={href}\n className={[\"canopy-card\", className].filter(Boolean).join(\" \")}\n style={style}\n ref={containerRef}\n data-aspect-ratio={ratio}\n data-in-view={inView ? \"true\" : \"false\"}\n data-image-loaded={imageLoaded ? \"true\" : \"false\"}\n {...rest}\n >\n <figure>\n {src ? (\n ratio ? (\n <div\n className=\"canopy-card-media\"\n style={{ \"--canopy-card-padding\": `${paddingPercent}%` }}\n >\n {inView ? (\n <img\n src={src}\n alt={alt || title || \"\"}\n loading=\"lazy\"\n onLoad={() => setImageLoaded(true)}\n onError={() => setImageLoaded(true)}\n />\n ) : null}\n </div>\n ) : (\n <img\n src={src}\n alt={alt || title || \"\"}\n loading=\"lazy\"\n onLoad={() => setImageLoaded(true)}\n onError={() => setImageLoaded(true)}\n className=\"canopy-card-image\"\n />\n )\n ) : null}\n {caption}\n </figure>\n </a>\n );\n}\n", "import Masonry from \"react-masonry-css\";\nimport React from \"react\";\n\n// Simple item wrapper to provide consistent spacing between items.\nexport function GridItem({ children, className = \"\", style = {}, ...rest }) {\n return (\n <div\n className={`canopy-grid-item ${className}`.trim()}\n style={style}\n {...rest}\n >\n {children}\n </div>\n );\n}\n\n/**\n * Grid (Masonry)\n *\n * Lightweight wrapper around `react-masonry-css` with sensible defaults\n * and inline styles so it works without a global CSS pipeline.\n *\n * Props:\n * - breakpointCols: number | object \u2014 columns per breakpoint (react-masonry-css prop)\n * - gap: CSS length string \u2014 spacing between items/columns (default '1rem')\n * - paddingY: CSS length string \u2014 vertical padding for the grid (default '0')\n * - className, style \u2014 forwarded to container\n * - columnClassName \u2014 forwarded to Masonry (defaults to 'canopy-grid-column')\n * - children \u2014 usually a list of <GridItem> elements\n */\nexport default function Grid({\n breakpointCols,\n gap = \"2rem\",\n paddingY = \"0\",\n className = \"\",\n style = {},\n columnClassName = \"canopy-grid-column\",\n children,\n ...rest\n}) {\n const cols = breakpointCols || {\n default: 6,\n 1280: 5,\n 1024: 4,\n 768: 3,\n 640: 2,\n };\n const vars = { \"--grid-gap\": gap, \"--grid-padding-y\": paddingY };\n\n return (\n <div className=\"canopy-grid-wrap\">\n {/* Scoped styles so the component works standalone */}\n <style\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{\n __html: `\n .canopy-grid { display: flex; width: auto; position: relative; padding: var(--grid-padding-y, 0) 0; z-index: 1; }\n .canopy-grid .${columnClassName} { margin-left: var(--grid-gap, 1rem); }\n .canopy-grid .${columnClassName}:first-child { margin-left: 0; }\n .canopy-grid-item { margin-bottom: var(--grid-gap, 1rem); }\n `,\n }}\n />\n <Masonry\n breakpointCols={cols}\n className={`canopy-grid ${className}`.trim()}\n columnClassName={columnClassName}\n style={{ ...vars, ...style }}\n {...rest}\n >\n {children}\n </Masonry>\n </div>\n );\n}\n", "import React, { useEffect, useState } from \"react\";\n\n// SSR-safe wrapper around Clover's viewer. Clover touches the DOM at import time,\n// so we dynamically import it only in the browser.\n\n// Default Clover viewer options; can be overridden per-usage via props.options\nconst DEFAULT_VIEWER_OPTIONS = {\n showDownload: false,\n showIIIFBadge: false,\n showTitle: false,\n informationPanel: {\n open: false,\n renderAbout: false,\n renderToggle: false,\n },\n};\n\nfunction isPlainObject(val) {\n return val && typeof val === \"object\" && !Array.isArray(val);\n}\n\nfunction deepMerge(base, override) {\n if (!isPlainObject(base)) return override;\n const out = { ...base };\n if (!isPlainObject(override)) return out;\n for (const key of Object.keys(override)) {\n const a = base[key];\n const b = override[key];\n if (isPlainObject(a) && isPlainObject(b)) out[key] = deepMerge(a, b);\n else out[key] = b;\n }\n return out;\n}\n\nexport const Viewer = (props) => {\n const [CloverViewer, setCloverViewer] = useState(null);\n const mergedOptions = deepMerge(\n DEFAULT_VIEWER_OPTIONS,\n props && props.options\n );\n\n useEffect(() => {\n let mounted = true;\n const canUseDom =\n typeof window !== \"undefined\" && typeof document !== \"undefined\";\n if (canUseDom) {\n import(\"@samvera/clover-iiif/viewer\")\n .then((mod) => {\n if (!mounted) return;\n // Loaded Clover viewer dynamically in the browser\n const Comp = mod && (mod.default || mod.Viewer || mod);\n setCloverViewer(() => Comp);\n })\n .catch(() => {\n // Silently ignore load errors on the server or if Clover is unavailable\n });\n }\n return () => {\n mounted = false;\n };\n }, []);\n\n if (!CloverViewer) {\n // SSR placeholder for client hydration; props provided as JSON\n let json = \"{}\";\n try {\n const p = { ...(props || {}) };\n if (mergedOptions) p.options = mergedOptions;\n json = JSON.stringify(p);\n } catch (_) {\n json = \"{}\";\n }\n return (\n <div data-canopy-viewer=\"1\" className=\"not-prose\">\n <script\n type=\"application/json\"\n dangerouslySetInnerHTML={{ __html: json }}\n />\n </div>\n );\n }\n return <CloverViewer {...props} options={mergedOptions} />;\n};\n", "import React, { useEffect, useState } from \"react\";\n\n// SSR-safe wrapper around Clover's slider. Clover touches the DOM at import time,\n// so we dynamically import it only in the browser.\nexport const Slider = (props) => {\n const [CloverSlider, setCloverSlider] = useState(null);\n\n useEffect(() => {\n let mounted = true;\n const canUseDom =\n typeof window !== \"undefined\" && typeof document !== \"undefined\";\n if (canUseDom) {\n import(\"@samvera/clover-iiif/slider\")\n .then((mod) => {\n if (!mounted) return;\n console.log(mod);\n const Comp = mod && (mod.default || mod.Slider || mod);\n setCloverSlider(() => Comp);\n })\n .catch(() => {\n // Silently ignore load errors on the server or if Clover is unavailable\n });\n }\n return () => {\n mounted = false;\n };\n }, []);\n\n if (!CloverSlider) {\n // SSR placeholder for client hydration; props provided as JSON\n let json = \"{}\";\n try {\n json = JSON.stringify(props || {});\n } catch (_) {\n json = \"{}\";\n }\n return (\n <div data-canopy-slider=\"1\" className=\"not-prose\">\n <script\n type=\"application/json\"\n dangerouslySetInnerHTML={{ __html: json }}\n />\n </div>\n );\n }\n return <CloverSlider {...props} />;\n};\n", "import React from 'react';\n\n// SSR-safe placeholder for RelatedItems. Hydrated by canopy-related-items.js + canopy-slider.js\nexport default function MdxRelatedItems(props) {\n let json = '{}';\n try {\n json = JSON.stringify(props || {});\n } catch (_) {\n json = '{}';\n }\n return (\n <div data-canopy-related-items=\"1\" className=\"not-prose\">\n <script type=\"application/json\" dangerouslySetInnerHTML={{ __html: json }} />\n </div>\n );\n}\n", "import React from 'react';\n\nexport default function MdxSearchResults(props) {\n let json = '{}';\n try { json = JSON.stringify(props || {}); } catch (_) { json = '{}'; }\n return (\n <div data-canopy-search-results=\"1\">\n <script type=\"application/json\" dangerouslySetInnerHTML={{ __html: json }} />\n </div>\n );\n}\n\n", "import React from 'react';\n\nexport default function SearchSummary(props) {\n let json = '{}';\n try { json = JSON.stringify(props || {}); } catch (_) { json = '{}'; }\n return (\n <div data-canopy-search-summary=\"1\">\n <script type=\"application/json\" dangerouslySetInnerHTML={{ __html: json }} />\n </div>\n );\n}\n\n", "import React from 'react';\n\nexport default function MdxSearchTabs(props) {\n let json = '{}';\n try { json = JSON.stringify(props || {}); } catch (_) { json = '{}'; }\n return (\n <div data-canopy-search-tabs=\"1\">\n <script type=\"application/json\" dangerouslySetInnerHTML={{ __html: json }} />\n </div>\n );\n}\n\n", "import Grid, { GridItem } from \"../layout/Grid.jsx\";\n\nimport Card from \"../layout/Card.jsx\";\nimport React from \"react\";\n\nexport default function SearchResults({\n results = [],\n type = \"all\",\n layout = \"grid\",\n}) {\n if (!results.length) {\n return (\n <div className=\"text-slate-600\">\n <em>No results</em>\n </div>\n );\n }\n\n if (layout === \"list\") {\n return (\n <ul id=\"search-results\" className=\"space-y-3\">\n {results.map((r, i) => {\n const hasDims =\n Number.isFinite(Number(r.thumbnailWidth)) &&\n Number(r.thumbnailWidth) > 0 &&\n Number.isFinite(Number(r.thumbnailHeight)) &&\n Number(r.thumbnailHeight) > 0;\n const aspect = hasDims\n ? Number(r.thumbnailWidth) / Number(r.thumbnailHeight)\n : undefined;\n return (\n <li\n key={i}\n className={`search-result ${r.type}`}\n data-thumbnail-aspect-ratio={aspect}\n >\n <Card\n href={r.href}\n title={r.title || r.href}\n src={r.type === \"work\" ? r.thumbnail : undefined}\n imgWidth={r.thumbnailWidth}\n imgHeight={r.thumbnailHeight}\n aspectRatio={aspect}\n />\n </li>\n );\n })}\n </ul>\n );\n }\n\n // Default: grid (masonry)\n return (\n <div id=\"search-results\">\n <Grid>\n {results.map((r, i) => {\n const hasDims =\n Number.isFinite(Number(r.thumbnailWidth)) &&\n Number(r.thumbnailWidth) > 0 &&\n Number.isFinite(Number(r.thumbnailHeight)) &&\n Number(r.thumbnailHeight) > 0;\n const aspect = hasDims\n ? Number(r.thumbnailWidth) / Number(r.thumbnailHeight)\n : undefined;\n return (\n <GridItem\n key={i}\n className={`search-result ${r.type}`}\n data-thumbnail-aspect-ratio={aspect}\n >\n <Card\n href={r.href}\n title={r.title || r.href}\n src={r.type === \"work\" ? r.thumbnail : undefined}\n imgWidth={r.thumbnailWidth}\n imgHeight={r.thumbnailHeight}\n aspectRatio={aspect}\n />\n </GridItem>\n );\n })}\n </Grid>\n </div>\n );\n}\n", "import React from 'react';\n\nexport default function SearchTabs({ type = 'all', onTypeChange, types = [], counts = {} }) {\n const orderedTypes = Array.isArray(types) ? types : [];\n const toLabel = (t) => (t && t.length ? t.charAt(0).toUpperCase() + t.slice(1) : '');\n return (\n <div role=\"tablist\" aria-label=\"Search types\" className=\"flex items-center gap-2 border-b border-slate-200\">\n {orderedTypes.map((t) => {\n const active = String(type).toLowerCase() === String(t).toLowerCase();\n const cRaw = (counts && Object.prototype.hasOwnProperty.call(counts, t)) ? counts[t] : undefined;\n const c = Number.isFinite(Number(cRaw)) ? Number(cRaw) : 0;\n return (\n <button\n key={t}\n role=\"tab\"\n aria-selected={active}\n type=\"button\"\n onClick={() => onTypeChange && onTypeChange(t)}\n className={\n 'px-3 py-1.5 text-sm rounded-t-md border-b-2 -mb-px transition-colors ' +\n (active\n ? 'border-brand-600 text-brand-700'\n : 'border-transparent text-slate-600 hover:text-slate-900 hover:border-slate-300')\n }\n >\n {toLabel(t)} ({c})\n </button>\n );\n })}\n </div>\n );\n}\n\n", "import React from 'react';\nimport SearchPanelForm from '../search/SearchPanelForm.jsx';\nimport SearchPanelTeaserResults from '../search/SearchPanelTeaserResults.jsx';\n\n// SSR-safe placeholder for the command palette, composed from SearchPanel parts.\n// This ensures a single JSX source of truth for form/panel markup.\nexport default function MdxCommandPalette(props = {}) {\n const {\n placeholder = 'Search\u2026',\n hotkey = 'mod+k',\n maxResults = 8,\n groupOrder = ['work', 'page'],\n button = true, // kept for backward compat; ignored by teaser form\n buttonLabel = 'Search',\n label,\n searchPath = '/search',\n } = props || {};\n\n const text = typeof label === 'string' && label.trim() ? label.trim() : buttonLabel;\n const data = { placeholder, hotkey, maxResults, groupOrder, label: text, searchPath };\n return (\n <div data-canopy-command className=\"flex-1 min-w-0\">\n <div className=\"relative w-full\">\n <style>{`.relative[data-canopy-panel-auto='1']:focus-within [data-canopy-command-panel]{display:block}`}</style>\n <SearchPanelForm placeholder={placeholder} buttonLabel={buttonLabel} label={label} searchPath={searchPath} />\n <SearchPanelTeaserResults />\n </div>\n <script type=\"application/json\" dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }} />\n </div>\n );\n}\n", "import React from \"react\";\n\nexport const MagnifyingGlassIcon = (props) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" {...props}>\n <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\" />\n </svg>\n);\n", "import { MagnifyingGlassIcon } from \"../Icons\";\nimport React from \"react\";\n\nexport default function SearchPanelForm(props = {}) {\n const {\n placeholder = \"Search\u2026\",\n buttonLabel = \"Search\",\n label,\n searchPath = \"/search\",\n } = props || {};\n\n const text =\n typeof label === \"string\" && label.trim() ? label.trim() : buttonLabel;\n\n return (\n <form\n action={searchPath}\n method=\"get\"\n role=\"search\"\n autoComplete=\"off\"\n spellCheck=\"false\"\n className=\"group flex items-center gap-2 px-2 py-1.5 rounded-lg border border-slate-300 bg-white/95 backdrop-blur text-slate-700 shadow-sm hover:shadow transition w-full focus-within:ring-2 focus-within:ring-brand-500\"\n >\n <MagnifyingGlassIcon className=\"w-5 h-5 text-slate-400 group-focus-within:text-brand-500\" />\n <input\n type=\"search\"\n name=\"q\"\n inputMode=\"search\"\n data-canopy-command-input\n placeholder={placeholder}\n className=\"flex-1 bg-transparent outline-none placeholder:text-slate-400 py-0.5 min-w-0\"\n aria-label=\"Search\"\n />\n <button\n type=\"submit\"\n data-canopy-command-link\n className=\"inline-flex items-center gap-1 px-2 py-1 rounded-md border border-slate-200 bg-slate-50 hover:bg-slate-100 text-slate-700\"\n >\n <span>{text}</span>\n </button>\n </form>\n );\n}\n", "import React from \"react\";\n\n// SSR placeholder for teaser results panel; the runtime controls visibility and content.\nexport default function SearchPanelTeaserResults(props = {}) {\n const { style } = props || {};\n const baseStyle = {\n display: \"none\",\n position: \"absolute\",\n left: 0,\n right: 0,\n top: \"calc(100% + 4px)\",\n background: \"#fff\",\n border: \"1px solid #e5e7eb\",\n borderRadius: 8,\n boxShadow: \"0 10px 25px rgba(0,0,0,0.12)\",\n zIndex: 1000,\n overflow: \"auto\",\n maxHeight: \"60vh\",\n };\n return (\n <div data-canopy-command-panel style={{ ...baseStyle, ...(style || {}) }}>\n <div id=\"cplist\" />\n </div>\n );\n}\n", "import React from 'react';\nimport SearchPanelForm from './SearchPanelForm.jsx';\nimport SearchPanelTeaserResults from './SearchPanelTeaserResults.jsx';\n\n// High-level SearchPanel composed of a teaser form and teaser results panel.\n// Encodes configuration as JSON for the client runtime.\nexport default function SearchPanel(props = {}) {\n const {\n placeholder = 'Search\u2026',\n hotkey = 'mod+k',\n maxResults = 8,\n groupOrder = ['work', 'page'],\n // Kept for backward compat; form always renders submit\n button = true, // eslint-disable-line no-unused-vars\n buttonLabel = 'Search',\n label,\n searchPath = '/search',\n } = props || {};\n\n const text = typeof label === 'string' && label.trim() ? label.trim() : buttonLabel;\n const data = { placeholder, hotkey, maxResults, groupOrder, label: text, searchPath };\n\n return (\n <div data-canopy-command className=\"flex-1 min-w-0\">\n <div className=\"relative w-full\">\n <style>{`.relative[data-canopy-panel-auto='1']:focus-within [data-canopy-command-panel]{display:block}`}</style>\n <SearchPanelForm placeholder={placeholder} buttonLabel={buttonLabel} label={label} searchPath={searchPath} />\n <SearchPanelTeaserResults />\n </div>\n <script type=\"application/json\" dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }} />\n </div>\n );\n}\n\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["React", "React", "React", "React", "useEffect", "useState", "React", "useEffect", "useState", "React", "React", "React", "React", "React", "React", "React", "React", "React", "React", "React", "React", "React"]
|
|
7
7
|
}
|