@canopy-iiif/app 0.9.13 → 0.9.15

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/ui/dist/index.mjs CHANGED
@@ -226,18 +226,67 @@ function Grid({
226
226
  ));
227
227
  }
228
228
 
229
+ // ui/src/layout/Container.jsx
230
+ import React5 from "react";
231
+ function Container({ className = "", children, ...rest }) {
232
+ const classes = ["mx-auto", "max-w-content", "w-full", "px-6", className].filter(Boolean).join(" ");
233
+ return /* @__PURE__ */ React5.createElement("div", { className: classes, ...rest }, children);
234
+ }
235
+
236
+ // ui/src/layout/Button.jsx
237
+ import React6 from "react";
238
+ var VARIANTS = /* @__PURE__ */ new Set(["primary", "secondary"]);
239
+ function Button({
240
+ label,
241
+ href = "#",
242
+ target,
243
+ rel,
244
+ variant = "primary",
245
+ className = "",
246
+ children,
247
+ ...rest
248
+ }) {
249
+ const resolvedVariant = VARIANTS.has(variant) ? variant : "primary";
250
+ const computedRel = target === "_blank" && !rel ? "noopener noreferrer" : rel;
251
+ const content = children != null ? children : label;
252
+ if (!content) return null;
253
+ const classes = [
254
+ "canopy-button",
255
+ `canopy-button--${resolvedVariant}`,
256
+ className
257
+ ].filter(Boolean).join(" ");
258
+ return /* @__PURE__ */ React6.createElement(
259
+ "a",
260
+ {
261
+ href,
262
+ className: classes,
263
+ target,
264
+ rel: computedRel,
265
+ ...rest
266
+ },
267
+ content
268
+ );
269
+ }
270
+
271
+ // ui/src/layout/ButtonWrapper.jsx
272
+ import React7 from "react";
273
+ function ButtonWrapper({ className = "", children, ...rest }) {
274
+ const classes = ["canopy-button-group", className].filter(Boolean).join(" ");
275
+ return /* @__PURE__ */ React7.createElement("div", { className: classes, ...rest }, children);
276
+ }
277
+
229
278
  // ui/src/layout/CanopyHeader.jsx
230
- import React11 from "react";
279
+ import React14 from "react";
231
280
 
232
281
  // ui/src/search/SearchPanel.jsx
233
- import React8 from "react";
282
+ import React11 from "react";
234
283
 
235
284
  // ui/src/Icons.jsx
236
- import React5 from "react";
237
- var MagnifyingGlassIcon = (props) => /* @__PURE__ */ React5.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512", ...props }, /* @__PURE__ */ React5.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" }));
285
+ import React8 from "react";
286
+ var MagnifyingGlassIcon = (props) => /* @__PURE__ */ React8.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 512 512", ...props }, /* @__PURE__ */ React8.createElement("path", { d: "M456.69 421.39L362.6 327.3a173.81 173.81 0 0034.84-104.58C397.44 126.38 319.06 48 222.72 48S48 126.38 48 222.72s78.38 174.72 174.72 174.72A173.81 173.81 0 00327.3 362.6l94.09 94.09a25 25 0 0035.3-35.3zM97.92 222.72a124.8 124.8 0 11124.8 124.8 124.95 124.95 0 01-124.8-124.8z" }));
238
287
 
239
288
  // ui/src/search/SearchPanelForm.jsx
240
- import React6 from "react";
289
+ import React9 from "react";
241
290
  function readBasePath() {
242
291
  const normalize = (val) => {
243
292
  const raw = typeof val === "string" ? val.trim() : "";
@@ -300,18 +349,18 @@ function SearchPanelForm(props = {}) {
300
349
  clearLabel = "Clear search"
301
350
  } = props || {};
302
351
  const text = typeof label === "string" && label.trim() ? label.trim() : buttonLabel;
303
- const action = React6.useMemo(
352
+ const action = React9.useMemo(
304
353
  () => resolveSearchPath(searchPath),
305
354
  [searchPath]
306
355
  );
307
- const autoId = typeof React6.useId === "function" ? React6.useId() : void 0;
308
- const [fallbackId] = React6.useState(
356
+ const autoId = typeof React9.useId === "function" ? React9.useId() : void 0;
357
+ const [fallbackId] = React9.useState(
309
358
  () => `canopy-search-form-${Math.random().toString(36).slice(2, 10)}`
310
359
  );
311
360
  const inputId = inputIdProp || autoId || fallbackId;
312
- const inputRef = React6.useRef(null);
313
- const [hasValue, setHasValue] = React6.useState(false);
314
- const focusInput = React6.useCallback(() => {
361
+ const inputRef = React9.useRef(null);
362
+ const [hasValue, setHasValue] = React9.useState(false);
363
+ const focusInput = React9.useCallback(() => {
315
364
  const el = inputRef.current;
316
365
  if (!el) return;
317
366
  if (document.activeElement === el) return;
@@ -324,7 +373,7 @@ function SearchPanelForm(props = {}) {
324
373
  }
325
374
  }
326
375
  }, []);
327
- const handlePointerDown = React6.useCallback(
376
+ const handlePointerDown = React9.useCallback(
328
377
  (event) => {
329
378
  const target = event.target;
330
379
  if (target && typeof target.closest === "function") {
@@ -336,23 +385,23 @@ function SearchPanelForm(props = {}) {
336
385
  },
337
386
  [focusInput]
338
387
  );
339
- React6.useEffect(() => {
388
+ React9.useEffect(() => {
340
389
  const el = inputRef.current;
341
390
  if (!el) return;
342
391
  if (el.value && el.value.trim()) {
343
392
  setHasValue(true);
344
393
  }
345
394
  }, []);
346
- const handleInputChange = React6.useCallback((event) => {
395
+ const handleInputChange = React9.useCallback((event) => {
347
396
  var _a;
348
397
  const nextHasValue = Boolean(
349
398
  ((_a = event == null ? void 0 : event.target) == null ? void 0 : _a.value) && event.target.value.trim()
350
399
  );
351
400
  setHasValue(nextHasValue);
352
401
  }, []);
353
- const handleClear = React6.useCallback((event) => {
402
+ const handleClear = React9.useCallback((event) => {
354
403
  }, []);
355
- const handleClearKey = React6.useCallback(
404
+ const handleClearKey = React9.useCallback(
356
405
  (event) => {
357
406
  if (event.key === "Enter" || event.key === " ") {
358
407
  event.preventDefault();
@@ -361,7 +410,7 @@ function SearchPanelForm(props = {}) {
361
410
  },
362
411
  [handleClear]
363
412
  );
364
- return /* @__PURE__ */ React6.createElement(
413
+ return /* @__PURE__ */ React9.createElement(
365
414
  "form",
366
415
  {
367
416
  action,
@@ -373,7 +422,7 @@ function SearchPanelForm(props = {}) {
373
422
  onPointerDown: handlePointerDown,
374
423
  "data-has-value": hasValue ? "1" : "0"
375
424
  },
376
- /* @__PURE__ */ React6.createElement("label", { htmlFor: inputId, className: "canopy-search-form__label" }, /* @__PURE__ */ React6.createElement(MagnifyingGlassIcon, { className: "canopy-search-form__icon" }), /* @__PURE__ */ React6.createElement(
425
+ /* @__PURE__ */ React9.createElement("label", { htmlFor: inputId, className: "canopy-search-form__label" }, /* @__PURE__ */ React9.createElement(MagnifyingGlassIcon, { className: "canopy-search-form__icon" }), /* @__PURE__ */ React9.createElement(
377
426
  "input",
378
427
  {
379
428
  id: inputId,
@@ -389,7 +438,7 @@ function SearchPanelForm(props = {}) {
389
438
  onInput: handleInputChange
390
439
  }
391
440
  )),
392
- hasValue ? /* @__PURE__ */ React6.createElement(
441
+ hasValue ? /* @__PURE__ */ React9.createElement(
393
442
  "button",
394
443
  {
395
444
  type: "button",
@@ -402,32 +451,31 @@ function SearchPanelForm(props = {}) {
402
451
  },
403
452
  "\xD7"
404
453
  ) : null,
405
- /* @__PURE__ */ React6.createElement(
454
+ /* @__PURE__ */ React9.createElement(
406
455
  "button",
407
456
  {
408
457
  type: "submit",
409
458
  "data-canopy-search-form-trigger": "submit",
410
459
  className: "canopy-search-form__submit"
411
460
  },
412
- /* @__PURE__ */ React6.createElement("span", null, text),
413
- /* @__PURE__ */ React6.createElement("span", { "aria-hidden": true, className: "canopy-search-form__shortcut" }, /* @__PURE__ */ React6.createElement("span", null, "\u2318"), /* @__PURE__ */ React6.createElement("span", null, "K"))
461
+ text
414
462
  )
415
463
  );
416
464
  }
417
465
 
418
466
  // ui/src/search/SearchPanelTeaserResults.jsx
419
- import React7 from "react";
467
+ import React10 from "react";
420
468
  function SearchPanelTeaserResults(props = {}) {
421
469
  const { style, className } = props || {};
422
470
  const classes = ["canopy-search-teaser", className].filter(Boolean).join(" ");
423
- return /* @__PURE__ */ React7.createElement(
471
+ return /* @__PURE__ */ React10.createElement(
424
472
  "div",
425
473
  {
426
474
  "data-canopy-search-form-panel": true,
427
475
  className: classes || void 0,
428
476
  style
429
477
  },
430
- /* @__PURE__ */ React7.createElement("div", { id: "cplist" })
478
+ /* @__PURE__ */ React10.createElement("div", { id: "cplist" })
431
479
  );
432
480
  }
433
481
 
@@ -448,11 +496,11 @@ function SearchPanel(props = {}) {
448
496
  const text = typeof label === "string" && label.trim() ? label.trim() : buttonLabel;
449
497
  const resolvedSearchPath = resolveSearchPath(searchPath);
450
498
  const data = { placeholder, hotkey, maxResults, groupOrder, label: text, searchPath: resolvedSearchPath };
451
- return /* @__PURE__ */ React8.createElement("div", { "data-canopy-search-form": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React8.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React8.createElement(SearchPanelForm, { placeholder, buttonLabel, label, searchPath: resolvedSearchPath }), /* @__PURE__ */ React8.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React8.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
499
+ return /* @__PURE__ */ React11.createElement("div", { "data-canopy-search-form": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React11.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React11.createElement(SearchPanelForm, { placeholder, buttonLabel, label, searchPath: resolvedSearchPath }), /* @__PURE__ */ React11.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React11.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
452
500
  }
453
501
 
454
502
  // ui/src/layout/CanopyBrand.jsx
455
- import React9 from "react";
503
+ import React12 from "react";
456
504
  function CanopyBrand(props = {}) {
457
505
  const {
458
506
  labelId,
@@ -463,11 +511,11 @@ function CanopyBrand(props = {}) {
463
511
  } = props || {};
464
512
  const spanProps = labelId ? { id: labelId } : {};
465
513
  const classes = ["canopy-logo", className].filter(Boolean).join(" ");
466
- return /* @__PURE__ */ React9.createElement("a", { href, className: classes }, typeof Logo === "function" ? /* @__PURE__ */ React9.createElement(Logo, null) : null, /* @__PURE__ */ React9.createElement("span", { ...spanProps }, label));
514
+ return /* @__PURE__ */ React12.createElement("a", { href, className: classes }, typeof Logo === "function" ? /* @__PURE__ */ React12.createElement(Logo, null) : null, /* @__PURE__ */ React12.createElement("span", { ...spanProps }, label));
467
515
  }
468
516
 
469
517
  // ui/src/layout/CanopyModal.jsx
470
- import React10 from "react";
518
+ import React13 from "react";
471
519
  function CanopyModal(props = {}) {
472
520
  const {
473
521
  id,
@@ -518,7 +566,7 @@ function CanopyModal(props = {}) {
518
566
  if (padded) bodyClasses.push("canopy-modal__body--padded");
519
567
  if (bodyClassName) bodyClasses.push(bodyClassName);
520
568
  const bodyClassNameValue = bodyClasses.join(" ");
521
- return /* @__PURE__ */ React10.createElement("div", { ...modalProps }, /* @__PURE__ */ React10.createElement("div", { className: "canopy-modal__panel" }, /* @__PURE__ */ React10.createElement("button", { ...closeButtonProps }, /* @__PURE__ */ React10.createElement(
569
+ return /* @__PURE__ */ React13.createElement("div", { ...modalProps }, /* @__PURE__ */ React13.createElement("div", { className: "canopy-modal__panel" }, /* @__PURE__ */ React13.createElement("button", { ...closeButtonProps }, /* @__PURE__ */ React13.createElement(
522
570
  "svg",
523
571
  {
524
572
  xmlns: "http://www.w3.org/2000/svg",
@@ -528,8 +576,8 @@ function CanopyModal(props = {}) {
528
576
  strokeWidth: "1.5",
529
577
  className: "canopy-modal__close-icon"
530
578
  },
531
- /* @__PURE__ */ React10.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 6l12 12M6 18L18 6" })
532
- ), /* @__PURE__ */ React10.createElement("span", { className: "sr-only" }, closeLabel)), /* @__PURE__ */ React10.createElement("div", { className: bodyClassNameValue }, label ? /* @__PURE__ */ React10.createElement("div", { className: "canopy-modal__brand" }, /* @__PURE__ */ React10.createElement(
579
+ /* @__PURE__ */ React13.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 6l12 12M6 18L18 6" })
580
+ ), /* @__PURE__ */ React13.createElement("span", { className: "sr-only" }, closeLabel)), /* @__PURE__ */ React13.createElement("div", { className: bodyClassNameValue }, label ? /* @__PURE__ */ React13.createElement("div", { className: "canopy-modal__brand" }, /* @__PURE__ */ React13.createElement(
533
581
  CanopyBrand,
534
582
  {
535
583
  labelId: resolvedLabelId,
@@ -733,7 +781,7 @@ function HeaderScript() {
733
781
  });
734
782
  })();
735
783
  `;
736
- return /* @__PURE__ */ React11.createElement(
784
+ return /* @__PURE__ */ React14.createElement(
737
785
  "script",
738
786
  {
739
787
  dangerouslySetInnerHTML: {
@@ -744,7 +792,9 @@ function HeaderScript() {
744
792
  }
745
793
  function ensureArray(navLinks) {
746
794
  if (!Array.isArray(navLinks)) return [];
747
- return navLinks.filter((link) => link && typeof link === "object" && typeof link.href === "string");
795
+ return navLinks.filter(
796
+ (link) => link && typeof link === "object" && typeof link.href === "string"
797
+ );
748
798
  }
749
799
  function CanopyHeader(props = {}) {
750
800
  const {
@@ -757,59 +807,98 @@ function CanopyHeader(props = {}) {
757
807
  logo: SiteLogo
758
808
  } = props;
759
809
  const navLinks = ensureArray(navLinksProp);
760
- return /* @__PURE__ */ React11.createElement(React11.Fragment, null, /* @__PURE__ */ React11.createElement("header", { className: "canopy-header", "data-mobile-nav": "closed", "data-mobile-search": "closed" }, /* @__PURE__ */ React11.createElement("div", { className: "canopy-header__brand" }, /* @__PURE__ */ React11.createElement(
761
- CanopyBrand,
810
+ return /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(
811
+ "header",
762
812
  {
763
- label: title,
764
- href: brandHref,
765
- className: "canopy-header__brand-link",
766
- Logo: SiteLogo
767
- }
768
- )), /* @__PURE__ */ React11.createElement("div", { className: "canopy-header__desktop-search" }, /* @__PURE__ */ React11.createElement(SearchPanel, { label: searchLabel, hotkey: searchHotkey, placeholder: searchPlaceholder })), /* @__PURE__ */ React11.createElement("nav", { className: "canopy-nav-links canopy-header__desktop-nav", "aria-label": "Primary navigation" }, navLinks.map((link) => /* @__PURE__ */ React11.createElement("a", { key: link.href, href: link.href }, link.label || link.href))), /* @__PURE__ */ React11.createElement("div", { className: "canopy-header__actions" }, /* @__PURE__ */ React11.createElement(
769
- "button",
770
- {
771
- type: "button",
772
- className: "canopy-header__icon-button canopy-header__search-trigger",
773
- "aria-label": "Open search",
774
- "aria-controls": "canopy-modal-search",
775
- "aria-expanded": "false",
776
- "data-canopy-header-toggle": "search"
813
+ className: "canopy-header",
814
+ "data-mobile-nav": "closed",
815
+ "data-mobile-search": "closed"
777
816
  },
778
- /* @__PURE__ */ React11.createElement(
779
- "svg",
817
+ /* @__PURE__ */ React14.createElement("div", { className: "canopy-header__brand" }, /* @__PURE__ */ React14.createElement(
818
+ CanopyBrand,
780
819
  {
781
- xmlns: "http://www.w3.org/2000/svg",
782
- viewBox: "0 0 24 24",
783
- fill: "none",
784
- stroke: "currentColor",
785
- strokeWidth: "1.5",
786
- className: "canopy-header__search-icon"
820
+ label: title,
821
+ href: brandHref,
822
+ className: "canopy-header__brand-link",
823
+ Logo: SiteLogo
824
+ }
825
+ )),
826
+ /* @__PURE__ */ React14.createElement("div", { className: "canopy-header__desktop-search" }, /* @__PURE__ */ React14.createElement(
827
+ SearchPanel,
828
+ {
829
+ label: searchLabel,
830
+ hotkey: searchHotkey,
831
+ placeholder: searchPlaceholder
832
+ }
833
+ )),
834
+ /* @__PURE__ */ React14.createElement(
835
+ "nav",
836
+ {
837
+ className: "canopy-nav-links canopy-header__desktop-nav",
838
+ "aria-label": "Primary navigation"
787
839
  },
788
- /* @__PURE__ */ React11.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" })
789
- )
790
- ), /* @__PURE__ */ React11.createElement(
791
- "button",
792
- {
793
- type: "button",
794
- className: "canopy-header__icon-button canopy-header__menu",
795
- "aria-label": "Open navigation",
796
- "aria-controls": "canopy-modal-nav",
797
- "aria-expanded": "false",
798
- "data-canopy-header-toggle": "nav"
799
- },
800
- /* @__PURE__ */ React11.createElement(
801
- "svg",
840
+ navLinks.map((link) => /* @__PURE__ */ React14.createElement("a", { key: link.href, href: link.href }, link.label || link.href))
841
+ ),
842
+ /* @__PURE__ */ React14.createElement("div", { className: "canopy-header__actions" }, /* @__PURE__ */ React14.createElement(
843
+ "button",
802
844
  {
803
- xmlns: "http://www.w3.org/2000/svg",
804
- fill: "none",
805
- viewBox: "0 0 24 24",
806
- strokeWidth: "1.5",
807
- stroke: "currentColor",
808
- className: "canopy-header__menu-icon"
845
+ type: "button",
846
+ className: "canopy-header__icon-button canopy-header__search-trigger",
847
+ "aria-label": "Open search",
848
+ "aria-controls": "canopy-modal-search",
849
+ "aria-expanded": "false",
850
+ "data-canopy-header-toggle": "search"
809
851
  },
810
- /* @__PURE__ */ React11.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" })
811
- )
812
- ))), /* @__PURE__ */ React11.createElement(
852
+ /* @__PURE__ */ React14.createElement(
853
+ "svg",
854
+ {
855
+ xmlns: "http://www.w3.org/2000/svg",
856
+ viewBox: "0 0 24 24",
857
+ fill: "none",
858
+ stroke: "currentColor",
859
+ strokeWidth: "1.5",
860
+ className: "canopy-header__search-icon"
861
+ },
862
+ /* @__PURE__ */ React14.createElement(
863
+ "path",
864
+ {
865
+ strokeLinecap: "round",
866
+ strokeLinejoin: "round",
867
+ d: "m21 21-3.8-3.8M10.5 18a7.5 7.5 0 1 1 0-15 7.5 7.5 0 0 1 0 15Z"
868
+ }
869
+ )
870
+ )
871
+ ), /* @__PURE__ */ React14.createElement(
872
+ "button",
873
+ {
874
+ type: "button",
875
+ className: "canopy-header__icon-button canopy-header__menu",
876
+ "aria-label": "Open navigation",
877
+ "aria-controls": "canopy-modal-nav",
878
+ "aria-expanded": "false",
879
+ "data-canopy-header-toggle": "nav"
880
+ },
881
+ /* @__PURE__ */ React14.createElement(
882
+ "svg",
883
+ {
884
+ xmlns: "http://www.w3.org/2000/svg",
885
+ fill: "none",
886
+ viewBox: "0 0 24 24",
887
+ strokeWidth: "1.5",
888
+ stroke: "currentColor",
889
+ className: "canopy-header__menu-icon"
890
+ },
891
+ /* @__PURE__ */ React14.createElement(
892
+ "path",
893
+ {
894
+ strokeLinecap: "round",
895
+ strokeLinejoin: "round",
896
+ d: "M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"
897
+ }
898
+ )
899
+ )
900
+ ))
901
+ ), /* @__PURE__ */ React14.createElement(
813
902
  CanopyModal,
814
903
  {
815
904
  id: "canopy-modal-nav",
@@ -821,8 +910,15 @@ function CanopyHeader(props = {}) {
821
910
  closeLabel: "Close navigation",
822
911
  closeDataAttr: "nav"
823
912
  },
824
- /* @__PURE__ */ React11.createElement("nav", { className: "canopy-nav-links canopy-modal__nav", "aria-label": "Primary navigation" }, navLinks.map((link) => /* @__PURE__ */ React11.createElement("a", { key: link.href, href: link.href }, link.label || link.href)))
825
- ), /* @__PURE__ */ React11.createElement(
913
+ /* @__PURE__ */ React14.createElement(
914
+ "nav",
915
+ {
916
+ className: "canopy-nav-links canopy-modal__nav",
917
+ "aria-label": "Primary navigation"
918
+ },
919
+ navLinks.map((link) => /* @__PURE__ */ React14.createElement("a", { key: link.href, href: link.href }, link.label || link.href))
920
+ )
921
+ ), /* @__PURE__ */ React14.createElement(
826
922
  CanopyModal,
827
923
  {
828
924
  id: "canopy-modal-search",
@@ -835,19 +931,26 @@ function CanopyHeader(props = {}) {
835
931
  closeDataAttr: "search",
836
932
  bodyClassName: "canopy-modal__body--search"
837
933
  },
838
- /* @__PURE__ */ React11.createElement(SearchPanel, { label: searchLabel, hotkey: searchHotkey, placeholder: searchPlaceholder })
839
- ), /* @__PURE__ */ React11.createElement(HeaderScript, null));
934
+ /* @__PURE__ */ React14.createElement(
935
+ SearchPanel,
936
+ {
937
+ label: searchLabel,
938
+ hotkey: searchHotkey,
939
+ placeholder: searchPlaceholder
940
+ }
941
+ )
942
+ ), /* @__PURE__ */ React14.createElement(HeaderScript, null));
840
943
  }
841
944
 
842
945
  // ui/src/layout/CanopyFooter.jsx
843
- import React12 from "react";
946
+ import React15 from "react";
844
947
  function CanopyFooter({ className = "", children }) {
845
948
  const footerClassName = ["canopy-footer", className].filter(Boolean).join(" ");
846
- return /* @__PURE__ */ React12.createElement("footer", { className: footerClassName }, /* @__PURE__ */ React12.createElement("div", { className: "canopy-footer__inner" }, children));
949
+ return /* @__PURE__ */ React15.createElement("footer", { className: footerClassName }, /* @__PURE__ */ React15.createElement("div", { className: "canopy-footer__inner" }, children));
847
950
  }
848
951
 
849
952
  // ui/src/iiif/Viewer.jsx
850
- import React13, { useEffect as useEffect2, useState as useState2 } from "react";
953
+ import React16, { useEffect as useEffect2, useState as useState2 } from "react";
851
954
  var DEFAULT_VIEWER_OPTIONS = {
852
955
  showDownload: false,
853
956
  showIIIFBadge: false,
@@ -903,7 +1006,7 @@ var Viewer = (props) => {
903
1006
  } catch (_) {
904
1007
  json = "{}";
905
1008
  }
906
- return /* @__PURE__ */ React13.createElement("div", { "data-canopy-viewer": "1", className: "not-prose" }, /* @__PURE__ */ React13.createElement(
1009
+ return /* @__PURE__ */ React16.createElement("div", { "data-canopy-viewer": "1", className: "not-prose" }, /* @__PURE__ */ React16.createElement(
907
1010
  "script",
908
1011
  {
909
1012
  type: "application/json",
@@ -911,11 +1014,11 @@ var Viewer = (props) => {
911
1014
  }
912
1015
  ));
913
1016
  }
914
- return /* @__PURE__ */ React13.createElement(CloverViewer, { ...props, options: mergedOptions });
1017
+ return /* @__PURE__ */ React16.createElement(CloverViewer, { ...props, options: mergedOptions });
915
1018
  };
916
1019
 
917
1020
  // ui/src/iiif/Slider.jsx
918
- import React14, { useEffect as useEffect3, useState as useState3 } from "react";
1021
+ import React17, { useEffect as useEffect3, useState as useState3 } from "react";
919
1022
  var Slider = (props) => {
920
1023
  const [CloverSlider, setCloverSlider] = useState3(null);
921
1024
  useEffect3(() => {
@@ -941,7 +1044,7 @@ var Slider = (props) => {
941
1044
  } catch (_) {
942
1045
  json = "{}";
943
1046
  }
944
- return /* @__PURE__ */ React14.createElement("div", { "data-canopy-slider": "1", className: "not-prose" }, /* @__PURE__ */ React14.createElement(
1047
+ return /* @__PURE__ */ React17.createElement("div", { "data-canopy-slider": "1", className: "not-prose" }, /* @__PURE__ */ React17.createElement(
945
1048
  "script",
946
1049
  {
947
1050
  type: "application/json",
@@ -949,11 +1052,11 @@ var Slider = (props) => {
949
1052
  }
950
1053
  ));
951
1054
  }
952
- return /* @__PURE__ */ React14.createElement(CloverSlider, { ...props });
1055
+ return /* @__PURE__ */ React17.createElement(CloverSlider, { ...props });
953
1056
  };
954
1057
 
955
1058
  // ui/src/iiif/Scroll.jsx
956
- import React15, { useEffect as useEffect4, useState as useState4 } from "react";
1059
+ import React18, { useEffect as useEffect4, useState as useState4 } from "react";
957
1060
  var Scroll = (props) => {
958
1061
  const [CloverScroll, setCloverScroll] = useState4(null);
959
1062
  useEffect4(() => {
@@ -978,7 +1081,7 @@ var Scroll = (props) => {
978
1081
  } catch (_) {
979
1082
  json = "{}";
980
1083
  }
981
- return /* @__PURE__ */ React15.createElement("div", { "data-canopy-scroll": "1", className: "not-prose" }, /* @__PURE__ */ React15.createElement(
1084
+ return /* @__PURE__ */ React18.createElement("div", { "data-canopy-scroll": "1", className: "not-prose" }, /* @__PURE__ */ React18.createElement(
982
1085
  "script",
983
1086
  {
984
1087
  type: "application/json",
@@ -986,11 +1089,48 @@ var Scroll = (props) => {
986
1089
  }
987
1090
  ));
988
1091
  }
989
- return /* @__PURE__ */ React15.createElement(CloverScroll, { ...props });
1092
+ return /* @__PURE__ */ React18.createElement(CloverScroll, { ...props });
1093
+ };
1094
+
1095
+ // ui/src/iiif/Image.jsx
1096
+ import React19, { useEffect as useEffect5, useState as useState5 } from "react";
1097
+ var Image = (props) => {
1098
+ const [CloverImage, setCloverImage] = useState5(null);
1099
+ useEffect5(() => {
1100
+ let mounted = true;
1101
+ const canUseDom = typeof window !== "undefined" && typeof document !== "undefined";
1102
+ if (canUseDom) {
1103
+ import("@samvera/clover-iiif/image").then((mod) => {
1104
+ if (!mounted) return;
1105
+ const Comp = mod && (mod.default || mod.Image || mod);
1106
+ setCloverImage(() => Comp);
1107
+ }).catch(() => {
1108
+ });
1109
+ }
1110
+ return () => {
1111
+ mounted = false;
1112
+ };
1113
+ }, []);
1114
+ if (!CloverImage) {
1115
+ let json = "{}";
1116
+ try {
1117
+ json = JSON.stringify(props || {});
1118
+ } catch (_) {
1119
+ json = "{}";
1120
+ }
1121
+ return /* @__PURE__ */ React19.createElement("div", { "data-canopy-image": "1", className: "not-prose" }, /* @__PURE__ */ React19.createElement(
1122
+ "script",
1123
+ {
1124
+ type: "application/json",
1125
+ dangerouslySetInnerHTML: { __html: json }
1126
+ }
1127
+ ));
1128
+ }
1129
+ return /* @__PURE__ */ React19.createElement(CloverImage, { ...props });
990
1130
  };
991
1131
 
992
1132
  // ui/src/iiif/MdxRelatedItems.jsx
993
- import React16 from "react";
1133
+ import React20 from "react";
994
1134
  function MdxRelatedItems(props) {
995
1135
  let json = "{}";
996
1136
  try {
@@ -998,11 +1138,11 @@ function MdxRelatedItems(props) {
998
1138
  } catch (_) {
999
1139
  json = "{}";
1000
1140
  }
1001
- return /* @__PURE__ */ React16.createElement("div", { "data-canopy-related-items": "1", className: "not-prose" }, /* @__PURE__ */ React16.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
1141
+ return /* @__PURE__ */ React20.createElement("div", { "data-canopy-related-items": "1", className: "not-prose" }, /* @__PURE__ */ React20.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
1002
1142
  }
1003
1143
 
1004
1144
  // ui/src/search/MdxSearchResults.jsx
1005
- import React17 from "react";
1145
+ import React21 from "react";
1006
1146
  function MdxSearchResults(props) {
1007
1147
  let json = "{}";
1008
1148
  try {
@@ -1010,11 +1150,11 @@ function MdxSearchResults(props) {
1010
1150
  } catch (_) {
1011
1151
  json = "{}";
1012
1152
  }
1013
- return /* @__PURE__ */ React17.createElement("div", { "data-canopy-search-results": "1" }, /* @__PURE__ */ React17.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
1153
+ return /* @__PURE__ */ React21.createElement("div", { "data-canopy-search-results": "1" }, /* @__PURE__ */ React21.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
1014
1154
  }
1015
1155
 
1016
1156
  // ui/src/search/SearchSummary.jsx
1017
- import React18 from "react";
1157
+ import React22 from "react";
1018
1158
  function SearchSummary(props) {
1019
1159
  let json = "{}";
1020
1160
  try {
@@ -1022,11 +1162,11 @@ function SearchSummary(props) {
1022
1162
  } catch (_) {
1023
1163
  json = "{}";
1024
1164
  }
1025
- return /* @__PURE__ */ React18.createElement("div", { "data-canopy-search-summary": "1" }, /* @__PURE__ */ React18.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
1165
+ return /* @__PURE__ */ React22.createElement("div", { "data-canopy-search-summary": "1" }, /* @__PURE__ */ React22.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
1026
1166
  }
1027
1167
 
1028
1168
  // ui/src/search/MdxSearchTabs.jsx
1029
- import React19 from "react";
1169
+ import React23 from "react";
1030
1170
  function MdxSearchTabs(props) {
1031
1171
  let json = "{}";
1032
1172
  try {
@@ -1034,11 +1174,11 @@ function MdxSearchTabs(props) {
1034
1174
  } catch (_) {
1035
1175
  json = "{}";
1036
1176
  }
1037
- return /* @__PURE__ */ React19.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React19.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
1177
+ return /* @__PURE__ */ React23.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React23.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
1038
1178
  }
1039
1179
 
1040
1180
  // ui/src/search/SearchResults.jsx
1041
- import React20 from "react";
1181
+ import React24 from "react";
1042
1182
  function SearchResults({
1043
1183
  results = [],
1044
1184
  type = "all",
@@ -1046,19 +1186,19 @@ function SearchResults({
1046
1186
  query = ""
1047
1187
  }) {
1048
1188
  if (!results.length) {
1049
- return /* @__PURE__ */ React20.createElement("div", { className: "text-slate-600" }, /* @__PURE__ */ React20.createElement("em", null, "No results"));
1189
+ return /* @__PURE__ */ React24.createElement("div", { className: "text-slate-600" }, /* @__PURE__ */ React24.createElement("em", null, "No results"));
1050
1190
  }
1051
1191
  const normalizedType = String(type || "all").toLowerCase();
1052
1192
  const isAnnotationView = normalizedType === "annotation";
1053
1193
  if (isAnnotationView) {
1054
- return /* @__PURE__ */ React20.createElement("div", { id: "search-results", className: "space-y-4" }, results.map((r, i) => {
1194
+ return /* @__PURE__ */ React24.createElement("div", { id: "search-results", className: "space-y-4" }, results.map((r, i) => {
1055
1195
  if (!r) return null;
1056
1196
  return renderTextCard(r, r.id || i);
1057
1197
  }));
1058
1198
  }
1059
1199
  const renderTextCard = (record, key) => {
1060
1200
  if (!record) return null;
1061
- return /* @__PURE__ */ React20.createElement(
1201
+ return /* @__PURE__ */ React24.createElement(
1062
1202
  TextCard,
1063
1203
  {
1064
1204
  key,
@@ -1074,20 +1214,20 @@ function SearchResults({
1074
1214
  const isWorkRecord = (record) => String(record && record.type).toLowerCase() === "work";
1075
1215
  const shouldRenderAsTextCard = (record) => !isWorkRecord(record) || normalizedType !== "work";
1076
1216
  if (layout === "list") {
1077
- return /* @__PURE__ */ React20.createElement("ul", { id: "search-results", className: "space-y-3" }, results.map((r, i) => {
1217
+ return /* @__PURE__ */ React24.createElement("ul", { id: "search-results", className: "space-y-3" }, results.map((r, i) => {
1078
1218
  if (shouldRenderAsTextCard(r)) {
1079
- return /* @__PURE__ */ React20.createElement("li", { key: i, className: `search-result ${r && r.type}` }, renderTextCard(r, i));
1219
+ return /* @__PURE__ */ React24.createElement("li", { key: i, className: `search-result ${r && r.type}` }, renderTextCard(r, i));
1080
1220
  }
1081
1221
  const hasDims = Number.isFinite(Number(r.thumbnailWidth)) && Number(r.thumbnailWidth) > 0 && Number.isFinite(Number(r.thumbnailHeight)) && Number(r.thumbnailHeight) > 0;
1082
1222
  const aspect = hasDims ? Number(r.thumbnailWidth) / Number(r.thumbnailHeight) : void 0;
1083
- return /* @__PURE__ */ React20.createElement(
1223
+ return /* @__PURE__ */ React24.createElement(
1084
1224
  "li",
1085
1225
  {
1086
1226
  key: i,
1087
1227
  className: `search-result ${r.type}`,
1088
1228
  "data-thumbnail-aspect-ratio": aspect
1089
1229
  },
1090
- /* @__PURE__ */ React20.createElement(
1230
+ /* @__PURE__ */ React24.createElement(
1091
1231
  Card,
1092
1232
  {
1093
1233
  href: r.href,
@@ -1101,20 +1241,20 @@ function SearchResults({
1101
1241
  );
1102
1242
  }));
1103
1243
  }
1104
- return /* @__PURE__ */ React20.createElement("div", { id: "search-results" }, /* @__PURE__ */ React20.createElement(Grid, null, results.map((r, i) => {
1244
+ return /* @__PURE__ */ React24.createElement("div", { id: "search-results" }, /* @__PURE__ */ React24.createElement(Grid, null, results.map((r, i) => {
1105
1245
  if (shouldRenderAsTextCard(r)) {
1106
- return /* @__PURE__ */ React20.createElement(GridItem, { key: i, className: `search-result ${r && r.type}` }, renderTextCard(r, i));
1246
+ return /* @__PURE__ */ React24.createElement(GridItem, { key: i, className: `search-result ${r && r.type}` }, renderTextCard(r, i));
1107
1247
  }
1108
1248
  const hasDims = Number.isFinite(Number(r.thumbnailWidth)) && Number(r.thumbnailWidth) > 0 && Number.isFinite(Number(r.thumbnailHeight)) && Number(r.thumbnailHeight) > 0;
1109
1249
  const aspect = hasDims ? Number(r.thumbnailWidth) / Number(r.thumbnailHeight) : void 0;
1110
- return /* @__PURE__ */ React20.createElement(
1250
+ return /* @__PURE__ */ React24.createElement(
1111
1251
  GridItem,
1112
1252
  {
1113
1253
  key: i,
1114
1254
  className: `search-result ${r.type}`,
1115
1255
  "data-thumbnail-aspect-ratio": aspect
1116
1256
  },
1117
- /* @__PURE__ */ React20.createElement(
1257
+ /* @__PURE__ */ React24.createElement(
1118
1258
  Card,
1119
1259
  {
1120
1260
  href: r.href,
@@ -1130,7 +1270,7 @@ function SearchResults({
1130
1270
  }
1131
1271
 
1132
1272
  // ui/src/search/SearchTabs.jsx
1133
- import React21 from "react";
1273
+ import React25 from "react";
1134
1274
  function SearchTabs({
1135
1275
  type = "all",
1136
1276
  onTypeChange,
@@ -1145,7 +1285,7 @@ function SearchTabs({
1145
1285
  const toLabel = (t) => t && t.length ? t.charAt(0).toUpperCase() + t.slice(1) : "";
1146
1286
  const hasFilters = typeof onOpenFilters === "function";
1147
1287
  const filterBadge = activeFilterCount > 0 ? ` (${activeFilterCount})` : "";
1148
- return /* @__PURE__ */ React21.createElement("div", { className: "canopy-search-tabs-wrapper" }, /* @__PURE__ */ React21.createElement(
1288
+ return /* @__PURE__ */ React25.createElement("div", { className: "canopy-search-tabs-wrapper" }, /* @__PURE__ */ React25.createElement(
1149
1289
  "div",
1150
1290
  {
1151
1291
  role: "tablist",
@@ -1156,7 +1296,7 @@ function SearchTabs({
1156
1296
  const active = String(type).toLowerCase() === String(t).toLowerCase();
1157
1297
  const cRaw = counts && Object.prototype.hasOwnProperty.call(counts, t) ? counts[t] : void 0;
1158
1298
  const c = Number.isFinite(Number(cRaw)) ? Number(cRaw) : 0;
1159
- return /* @__PURE__ */ React21.createElement(
1299
+ return /* @__PURE__ */ React25.createElement(
1160
1300
  "button",
1161
1301
  {
1162
1302
  key: t,
@@ -1171,7 +1311,7 @@ function SearchTabs({
1171
1311
  ")"
1172
1312
  );
1173
1313
  })
1174
- ), hasFilters ? /* @__PURE__ */ React21.createElement(
1314
+ ), hasFilters ? /* @__PURE__ */ React25.createElement(
1175
1315
  "button",
1176
1316
  {
1177
1317
  type: "button",
@@ -1179,12 +1319,12 @@ function SearchTabs({
1179
1319
  "aria-expanded": filtersOpen ? "true" : "false",
1180
1320
  className: "inline-flex items-center gap-2 rounded-md border border-slate-200 bg-white px-3 py-1.5 text-sm font-medium text-slate-700 shadow-sm transition hover:border-brand-200 hover:bg-brand-50 hover:text-brand-700"
1181
1321
  },
1182
- /* @__PURE__ */ React21.createElement("span", null, filtersLabel, filterBadge)
1322
+ /* @__PURE__ */ React25.createElement("span", null, filtersLabel, filterBadge)
1183
1323
  ) : null);
1184
1324
  }
1185
1325
 
1186
1326
  // ui/src/search/SearchFiltersDialog.jsx
1187
- import React22 from "react";
1327
+ import React26 from "react";
1188
1328
  function toArray(input) {
1189
1329
  if (!input) return [];
1190
1330
  if (Array.isArray(input)) return input;
@@ -1223,20 +1363,20 @@ function FacetSection({ facet, selected, onToggle }) {
1223
1363
  const selectedValues = selected.get(String(slug)) || /* @__PURE__ */ new Set();
1224
1364
  const checkboxId = (valueSlug) => `filter-${slug}-${valueSlug}`;
1225
1365
  const hasSelection = selectedValues.size > 0;
1226
- const [quickQuery, setQuickQuery] = React22.useState("");
1366
+ const [quickQuery, setQuickQuery] = React26.useState("");
1227
1367
  const hasQuery = quickQuery.trim().length > 0;
1228
- const filteredValues = React22.useMemo(
1368
+ const filteredValues = React26.useMemo(
1229
1369
  () => facetMatches(values, quickQuery),
1230
1370
  [values, quickQuery]
1231
1371
  );
1232
- return /* @__PURE__ */ React22.createElement(
1372
+ return /* @__PURE__ */ React26.createElement(
1233
1373
  "details",
1234
1374
  {
1235
1375
  className: "canopy-search-filters__facet",
1236
1376
  open: hasSelection
1237
1377
  },
1238
- /* @__PURE__ */ React22.createElement("summary", { className: "canopy-search-filters__facet-summary" }, /* @__PURE__ */ React22.createElement("span", null, label), /* @__PURE__ */ React22.createElement("span", { className: "canopy-search-filters__facet-count" }, values.length)),
1239
- /* @__PURE__ */ React22.createElement("div", { className: "canopy-search-filters__facet-content" }, /* @__PURE__ */ React22.createElement("div", { className: "canopy-search-filters__quick" }, /* @__PURE__ */ React22.createElement(
1378
+ /* @__PURE__ */ React26.createElement("summary", { className: "canopy-search-filters__facet-summary" }, /* @__PURE__ */ React26.createElement("span", null, label), /* @__PURE__ */ React26.createElement("span", { className: "canopy-search-filters__facet-count" }, values.length)),
1379
+ /* @__PURE__ */ React26.createElement("div", { className: "canopy-search-filters__facet-content" }, /* @__PURE__ */ React26.createElement("div", { className: "canopy-search-filters__quick" }, /* @__PURE__ */ React26.createElement(
1240
1380
  "input",
1241
1381
  {
1242
1382
  type: "search",
@@ -1246,7 +1386,7 @@ function FacetSection({ facet, selected, onToggle }) {
1246
1386
  className: "canopy-search-filters__quick-input",
1247
1387
  "aria-label": `Filter ${label} values`
1248
1388
  }
1249
- ), quickQuery ? /* @__PURE__ */ React22.createElement(
1389
+ ), quickQuery ? /* @__PURE__ */ React26.createElement(
1250
1390
  "button",
1251
1391
  {
1252
1392
  type: "button",
@@ -1254,11 +1394,11 @@ function FacetSection({ facet, selected, onToggle }) {
1254
1394
  className: "canopy-search-filters__quick-clear"
1255
1395
  },
1256
1396
  "Clear"
1257
- ) : null), hasQuery && !filteredValues.length ? /* @__PURE__ */ React22.createElement("p", { className: "canopy-search-filters__facet-notice" }, "No matches found.") : null, /* @__PURE__ */ React22.createElement("ul", { className: "canopy-search-filters__facet-list" }, filteredValues.map((entry) => {
1397
+ ) : null), hasQuery && !filteredValues.length ? /* @__PURE__ */ React26.createElement("p", { className: "canopy-search-filters__facet-notice" }, "No matches found.") : null, /* @__PURE__ */ React26.createElement("ul", { className: "canopy-search-filters__facet-list" }, filteredValues.map((entry) => {
1258
1398
  const valueSlug = String(entry.slug || entry.value || "");
1259
1399
  const isChecked = selectedValues.has(valueSlug);
1260
1400
  const inputId = checkboxId(valueSlug);
1261
- return /* @__PURE__ */ React22.createElement("li", { key: valueSlug, className: "canopy-search-filters__facet-item" }, /* @__PURE__ */ React22.createElement(
1401
+ return /* @__PURE__ */ React26.createElement("li", { key: valueSlug, className: "canopy-search-filters__facet-item" }, /* @__PURE__ */ React26.createElement(
1262
1402
  "input",
1263
1403
  {
1264
1404
  id: inputId,
@@ -1270,15 +1410,15 @@ function FacetSection({ facet, selected, onToggle }) {
1270
1410
  if (onToggle) onToggle(slug, valueSlug, nextChecked);
1271
1411
  }
1272
1412
  }
1273
- ), /* @__PURE__ */ React22.createElement(
1413
+ ), /* @__PURE__ */ React26.createElement(
1274
1414
  "label",
1275
1415
  {
1276
1416
  htmlFor: inputId,
1277
1417
  className: "canopy-search-filters__facet-label"
1278
1418
  },
1279
- /* @__PURE__ */ React22.createElement("span", null, entry.value, " ", Number.isFinite(entry.doc_count) ? /* @__PURE__ */ React22.createElement("span", { className: "canopy-search-filters__facet-count" }, "(", entry.doc_count, ")") : null)
1419
+ /* @__PURE__ */ React26.createElement("span", null, entry.value, " ", Number.isFinite(entry.doc_count) ? /* @__PURE__ */ React26.createElement("span", { className: "canopy-search-filters__facet-count" }, "(", entry.doc_count, ")") : null)
1280
1420
  ));
1281
- }), !filteredValues.length && !hasQuery ? /* @__PURE__ */ React22.createElement("li", { className: "canopy-search-filters__facet-empty" }, "No values available.") : null))
1421
+ }), !filteredValues.length && !hasQuery ? /* @__PURE__ */ React26.createElement("li", { className: "canopy-search-filters__facet-empty" }, "No values available.") : null))
1282
1422
  );
1283
1423
  }
1284
1424
  function SearchFiltersDialog(props = {}) {
@@ -1300,7 +1440,7 @@ function SearchFiltersDialog(props = {}) {
1300
1440
  (total, set) => total + set.size,
1301
1441
  0
1302
1442
  );
1303
- React22.useEffect(() => {
1443
+ React26.useEffect(() => {
1304
1444
  if (!open) return void 0;
1305
1445
  if (typeof document === "undefined") return void 0;
1306
1446
  const body = document.body;
@@ -1317,7 +1457,7 @@ function SearchFiltersDialog(props = {}) {
1317
1457
  if (!open) return null;
1318
1458
  const brandId = "canopy-modal-filters-label";
1319
1459
  const subtitleText = subtitle != null ? subtitle : title;
1320
- return /* @__PURE__ */ React22.createElement(
1460
+ return /* @__PURE__ */ React26.createElement(
1321
1461
  CanopyModal,
1322
1462
  {
1323
1463
  id: "canopy-modal-filters",
@@ -1332,8 +1472,8 @@ function SearchFiltersDialog(props = {}) {
1332
1472
  onBackgroundClick: () => onOpenChange && onOpenChange(false),
1333
1473
  bodyClassName: "canopy-modal__body--filters"
1334
1474
  },
1335
- subtitleText ? /* @__PURE__ */ React22.createElement("p", { className: "canopy-search-filters__subtitle" }, subtitleText) : null,
1336
- /* @__PURE__ */ React22.createElement("div", { className: "canopy-search-filters__body" }, Array.isArray(facets) && facets.length ? /* @__PURE__ */ React22.createElement("div", { className: "canopy-search-filters__facets" }, facets.map((facet) => /* @__PURE__ */ React22.createElement(
1475
+ subtitleText ? /* @__PURE__ */ React26.createElement("p", { className: "canopy-search-filters__subtitle" }, subtitleText) : null,
1476
+ /* @__PURE__ */ React26.createElement("div", { className: "canopy-search-filters__body" }, Array.isArray(facets) && facets.length ? /* @__PURE__ */ React26.createElement("div", { className: "canopy-search-filters__facets" }, facets.map((facet) => /* @__PURE__ */ React26.createElement(
1337
1477
  FacetSection,
1338
1478
  {
1339
1479
  key: facet.slug || facet.label,
@@ -1341,8 +1481,8 @@ function SearchFiltersDialog(props = {}) {
1341
1481
  selected: selectedMap,
1342
1482
  onToggle
1343
1483
  }
1344
- ))) : /* @__PURE__ */ React22.createElement("p", { className: "canopy-search-filters__empty" }, "No filters are available for this collection.")),
1345
- /* @__PURE__ */ React22.createElement("footer", { className: "canopy-search-filters__footer" }, /* @__PURE__ */ React22.createElement("div", null, activeCount ? `${activeCount} filter${activeCount === 1 ? "" : "s"} applied` : "No filters applied"), /* @__PURE__ */ React22.createElement("div", { className: "canopy-search-filters__footer-actions" }, /* @__PURE__ */ React22.createElement(
1484
+ ))) : /* @__PURE__ */ React26.createElement("p", { className: "canopy-search-filters__empty" }, "No filters are available for this collection.")),
1485
+ /* @__PURE__ */ React26.createElement("footer", { className: "canopy-search-filters__footer" }, /* @__PURE__ */ React26.createElement("div", null, activeCount ? `${activeCount} filter${activeCount === 1 ? "" : "s"} applied` : "No filters applied"), /* @__PURE__ */ React26.createElement("div", { className: "canopy-search-filters__footer-actions" }, /* @__PURE__ */ React26.createElement(
1346
1486
  "button",
1347
1487
  {
1348
1488
  type: "button",
@@ -1353,7 +1493,7 @@ function SearchFiltersDialog(props = {}) {
1353
1493
  className: "canopy-search-filters__button canopy-search-filters__button--secondary"
1354
1494
  },
1355
1495
  "Clear all"
1356
- ), /* @__PURE__ */ React22.createElement(
1496
+ ), /* @__PURE__ */ React26.createElement(
1357
1497
  "button",
1358
1498
  {
1359
1499
  type: "button",
@@ -1366,7 +1506,7 @@ function SearchFiltersDialog(props = {}) {
1366
1506
  }
1367
1507
 
1368
1508
  // ui/src/search-form/MdxSearchFormModal.jsx
1369
- import React23 from "react";
1509
+ import React27 from "react";
1370
1510
  function MdxSearchFormModal(props = {}) {
1371
1511
  const {
1372
1512
  placeholder = "Search\u2026",
@@ -1382,17 +1522,29 @@ function MdxSearchFormModal(props = {}) {
1382
1522
  const text = typeof label === "string" && label.trim() ? label.trim() : buttonLabel;
1383
1523
  const resolvedSearchPath = resolveSearchPath(searchPath);
1384
1524
  const data = { placeholder, hotkey, maxResults, groupOrder, label: text, searchPath: resolvedSearchPath };
1385
- return /* @__PURE__ */ React23.createElement("div", { "data-canopy-search-form": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React23.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React23.createElement(SearchPanelForm, { placeholder, buttonLabel, label, searchPath: resolvedSearchPath }), /* @__PURE__ */ React23.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React23.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
1525
+ return /* @__PURE__ */ React27.createElement("div", { "data-canopy-search-form": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React27.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React27.createElement(SearchPanelForm, { placeholder, buttonLabel, label, searchPath: resolvedSearchPath }), /* @__PURE__ */ React27.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React27.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
1526
+ }
1527
+
1528
+ // ui/src/docs/MarkdownTable.jsx
1529
+ import React28 from "react";
1530
+ function MarkdownTable({ className = "", ...rest }) {
1531
+ const merged = ["markdown-table", className].filter(Boolean).join(" ");
1532
+ return /* @__PURE__ */ React28.createElement("div", { className: "markdown-table__frame" }, /* @__PURE__ */ React28.createElement("table", { className: merged, ...rest }));
1386
1533
  }
1387
1534
  export {
1535
+ Button,
1536
+ ButtonWrapper,
1388
1537
  CanopyBrand,
1389
1538
  CanopyFooter,
1390
1539
  CanopyHeader,
1391
1540
  CanopyModal,
1392
1541
  Card,
1542
+ Container,
1543
+ MarkdownTable as DocsMarkdownTable,
1393
1544
  Grid,
1394
1545
  GridItem,
1395
1546
  HelloWorld,
1547
+ Image,
1396
1548
  MdxRelatedItems as RelatedItems,
1397
1549
  Scroll,
1398
1550
  SearchFiltersDialog,