@ai-matrx/media 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.js CHANGED
@@ -465,9 +465,10 @@ function FileIcon2({
465
465
 
466
466
  // src/react/inline-media-ref.tsx
467
467
  import {
468
- useCallback,
468
+ useCallback as useCallback2,
469
+ useEffect as useEffect4,
469
470
  useMemo as useMemo2,
470
- useRef as useRef2,
471
+ useRef as useRef3,
471
472
  useState as useState3
472
473
  } from "react";
473
474
 
@@ -503,6 +504,54 @@ function useMediaHostPorts() {
503
504
  return useContext(portsContext());
504
505
  }
505
506
 
507
+ // src/core/diagnostics.ts
508
+ import { useCallback, useRef } from "react";
509
+ var LATCH_SLOT = /* @__PURE__ */ Symbol.for("ai-matrx.media.failure-latch");
510
+ function latch() {
511
+ const host = globalThis;
512
+ host[LATCH_SLOT] ??= /* @__PURE__ */ new Set();
513
+ return host[LATCH_SLOT];
514
+ }
515
+ function failureMediaIdentity(ref, src) {
516
+ if (ref && typeof ref === "object" && ref.file_id) return `file:${ref.file_id}`;
517
+ const raw = typeof ref === "string" ? ref : (ref && typeof ref === "object" ? ref.url ?? null : null) ?? src ?? null;
518
+ if (!raw) return "<unknown-media>";
519
+ if (raw.startsWith("blob:")) return "blob:object-url";
520
+ try {
521
+ const u = new URL(raw);
522
+ return `url:${u.origin}${u.pathname}`;
523
+ } catch {
524
+ const clean = raw.split(/[?#]/, 1)[0] ?? raw;
525
+ return `ref:${clean}`;
526
+ }
527
+ }
528
+ function emitMediaFailure(capture, info) {
529
+ const key = `${info.terminal ? "terminal" : "warning"}|${info.mediaRef}`;
530
+ const seen = latch();
531
+ if (seen.has(key)) return;
532
+ seen.add(key);
533
+ if (capture) {
534
+ try {
535
+ capture(info);
536
+ return;
537
+ } catch {
538
+ }
539
+ }
540
+ console.error(
541
+ "[@ai-matrx/media] media failure (no diagnostics sink captured it \u2014 bind MediaHostPorts.diagnostics.capture to your error system)",
542
+ info
543
+ );
544
+ }
545
+ function useMediaFailureCapture() {
546
+ const ports = useMediaHostPorts();
547
+ const capture = ports.diagnostics?.capture;
548
+ const captureRef = useRef(capture);
549
+ captureRef.current = capture;
550
+ return useCallback((info) => {
551
+ emitMediaFailure(captureRef.current, { source: "media", ...info });
552
+ }, []);
553
+ }
554
+
506
555
  // src/core/use-media-blob.ts
507
556
  import { useEffect, useState } from "react";
508
557
 
@@ -516,8 +565,16 @@ function stableRefKey(ref) {
516
565
  }
517
566
 
518
567
  // src/core/use-media-blob.ts
568
+ function statusOf(err) {
569
+ if (err && typeof err === "object") {
570
+ const candidate = err.status ?? err.statusCode;
571
+ if (typeof candidate === "number") return candidate;
572
+ }
573
+ return void 0;
574
+ }
519
575
  function useMediaBlob(ref) {
520
576
  const client = useMediaClient();
577
+ const capture = useMediaFailureCapture();
521
578
  const refKey = stableRefKey(ref);
522
579
  const [state, setState] = useState({ url: null, blob: null, loading: !!ref, error: null });
523
580
  const [retryToken, setRetryToken] = useState(0);
@@ -542,6 +599,14 @@ function useMediaBlob(ref) {
542
599
  if (cancelled) return;
543
600
  const message = err instanceof Error ? err.message : String(err ?? "Failed to load file");
544
601
  setState({ url: null, blob: null, loading: false, error: message });
602
+ const status = statusOf(err);
603
+ capture({
604
+ phase: "blob",
605
+ mediaRef: failureMediaIdentity(ref),
606
+ terminal: true,
607
+ message: `getBlob() failed: ${message}`,
608
+ ...status !== void 0 ? { status } : {}
609
+ });
545
610
  }
546
611
  );
547
612
  return () => {
@@ -556,7 +621,7 @@ function useMediaBlob(ref) {
556
621
  }
557
622
 
558
623
  // src/core/use-media-load-recovery.ts
559
- import { useEffect as useEffect2, useRef, useState as useState2 } from "react";
624
+ import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
560
625
 
561
626
  // src/types.ts
562
627
  function mintDurableSrc(url) {
@@ -564,26 +629,51 @@ function mintDurableSrc(url) {
564
629
  }
565
630
 
566
631
  // src/core/use-media-load-recovery.ts
632
+ function normalizeOutcome(outcome) {
633
+ return typeof outcome === "string" ? { verdict: outcome } : outcome;
634
+ }
635
+ var EPHEMERAL_SECRET_IDENTITY = "server:files-session-secret";
567
636
  function useMediaLoadRecovery(src, options) {
568
637
  const client = useMediaClient();
638
+ const capture = useMediaFailureCapture();
569
639
  const recoverable = options?.recoverable !== false;
570
640
  const onTerminal = options?.onTerminal;
641
+ const failureRef = options?.failureRef;
571
642
  const [result, setResult] = useState2({ source: src, retryKey: 0, failed: false });
572
- const attemptRef = useRef(0);
643
+ const attemptRef = useRef2(0);
573
644
  useEffect2(() => {
574
645
  attemptRef.current = 0;
575
646
  }, [src]);
647
+ const identity = () => failureMediaIdentity(failureRef ?? null, src);
576
648
  const onLoadError = (event) => {
577
649
  if (!src || !recoverable) {
578
650
  setResult({ source: src, retryKey: 0, failed: true });
651
+ if (src) {
652
+ capture({
653
+ phase: "element-load",
654
+ mediaRef: identity(),
655
+ terminal: true,
656
+ retryOutcome: "not-attempted",
657
+ message: "media element failed to load and the source is unrecoverable (foreign/object URL \u2014 a session refresh cannot fix it)"
658
+ });
659
+ }
579
660
  onTerminal?.(event);
580
661
  return;
581
662
  }
582
663
  attemptRef.current += 1;
583
664
  const attempt = attemptRef.current;
584
665
  client.recoverLoadError(mintDurableSrc(src), attempt).then(
585
- (verdict) => {
586
- if (verdict === "retry") {
666
+ (outcome) => {
667
+ const report = normalizeOutcome(outcome);
668
+ if (report.secretSource === "ephemeral") {
669
+ capture({
670
+ phase: "session",
671
+ mediaRef: EPHEMERAL_SECRET_IDENTITY,
672
+ terminal: false,
673
+ message: "server cookie secret is ephemeral \u2014 private renders will break across restarts/instances (set a persistent files-session secret on the server)"
674
+ });
675
+ }
676
+ if (report.verdict === "retry") {
587
677
  setResult((current) => ({
588
678
  source: src,
589
679
  retryKey: current.source === src ? current.retryKey + 1 : 1,
@@ -591,11 +681,26 @@ function useMediaLoadRecovery(src, options) {
591
681
  }));
592
682
  } else {
593
683
  setResult({ source: src, retryKey: 0, failed: true });
684
+ capture({
685
+ phase: attempt > 1 ? "element-load" : "recovery",
686
+ mediaRef: identity(),
687
+ terminal: true,
688
+ retryOutcome: attempt > 1 ? "retried" : "not-attempted",
689
+ message: attempt > 1 ? "media element failed to load after the session-refresh retry" : "media load recovery declined on the first attempt (session refresh did not produce a usable session)",
690
+ ...report.status !== void 0 ? { status: report.status } : {}
691
+ });
594
692
  onTerminal?.(event);
595
693
  }
596
694
  },
597
- () => {
695
+ (err) => {
598
696
  setResult({ source: src, retryKey: 0, failed: true });
697
+ capture({
698
+ phase: "session",
699
+ mediaRef: identity(),
700
+ terminal: true,
701
+ retryOutcome: "recovery-failed",
702
+ message: `session recovery failed: ${err instanceof Error ? err.message : String(err ?? "unknown error")}`
703
+ });
599
704
  onTerminal?.(event);
600
705
  }
601
706
  );
@@ -608,24 +713,51 @@ function useMediaLoadRecovery(src, options) {
608
713
  }
609
714
 
610
715
  // src/core/use-media-resolution.ts
611
- import { useMemo } from "react";
716
+ import { useEffect as useEffect3, useMemo } from "react";
612
717
  function useMediaResolution(ref) {
613
718
  const client = useMediaClient();
719
+ const capture = useMediaFailureCapture();
614
720
  const refKey = stableRefKey(ref);
615
- return useMemo(() => {
616
- if (!ref) return { resolution: null, status: "empty", reason: null };
721
+ const { state, failureMessage } = useMemo(() => {
722
+ if (!ref) {
723
+ return {
724
+ state: { resolution: null, status: "empty", reason: null },
725
+ failureMessage: null
726
+ };
727
+ }
617
728
  try {
618
729
  const resolution = client.resolve(ref);
619
- if (!resolution) return { resolution: null, status: "empty", reason: null };
620
- return { resolution, status: "ready", reason: null };
730
+ if (!resolution) {
731
+ return {
732
+ state: { resolution: null, status: "empty", reason: null },
733
+ failureMessage: null
734
+ };
735
+ }
736
+ return {
737
+ state: { resolution, status: "ready", reason: null },
738
+ failureMessage: null
739
+ };
621
740
  } catch (err) {
622
741
  return {
623
- resolution: null,
624
- status: "unavailable",
625
- reason: client.classifyError(err)
742
+ state: {
743
+ resolution: null,
744
+ status: "unavailable",
745
+ reason: client.classifyError(err)
746
+ },
747
+ failureMessage: err instanceof Error ? err.message : String(err ?? "resolve() failed")
626
748
  };
627
749
  }
628
750
  }, [client, refKey]);
751
+ useEffect3(() => {
752
+ if (state.status !== "unavailable") return;
753
+ capture({
754
+ phase: "resolve",
755
+ mediaRef: failureMediaIdentity(ref ?? null),
756
+ terminal: true,
757
+ message: `resolve() refused (${state.reason ?? "unknown"}): ${failureMessage ?? "no error message"}`
758
+ });
759
+ }, [refKey, state.status]);
760
+ return state;
629
761
  }
630
762
 
631
763
  // src/react/inline-media-ref.tsx
@@ -671,7 +803,7 @@ function prettifyUrl(url) {
671
803
  }
672
804
  var INERT_PLAYBACK = {
673
805
  useMediaElementSink(forward) {
674
- return useCallback(
806
+ return useCallback2(
675
807
  (node) => {
676
808
  if (!forward) return;
677
809
  if (typeof forward === "function") forward(node);
@@ -715,10 +847,21 @@ function InformativeErrorFallback({
715
847
  alt,
716
848
  elementType,
717
849
  mediaRef,
850
+ failurePhase,
718
851
  dimensions,
719
852
  rounded,
720
853
  className
721
854
  }) {
855
+ const capture = useMediaFailureCapture();
856
+ const identity = failureMediaIdentity(mediaRef ?? null, url);
857
+ useEffect4(() => {
858
+ capture({
859
+ phase: failurePhase,
860
+ mediaRef: identity,
861
+ terminal: true,
862
+ message: `media unavailable panel rendered for ${elementType} (${failurePhase} failure)`
863
+ });
864
+ }, [identity, failurePhase]);
722
865
  const shortAxis = dimensions === "fill" ? Number.POSITIVE_INFINITY : Math.min(dimensions.width, dimensions.height);
723
866
  const isCompact = dimensions !== "fill" && shortAxis < 64;
724
867
  const isMidsize = shortAxis < 140;
@@ -778,7 +921,7 @@ function InformativeErrorPanel({
778
921
  const [copied, setCopied] = useState3(false);
779
922
  const isFill = dimensions === "fill";
780
923
  const { host, tail } = prettifyUrl(url);
781
- const handleCopy = useCallback(
924
+ const handleCopy = useCallback2(
782
925
  (event) => {
783
926
  event.stopPropagation();
784
927
  event.preventDefault();
@@ -897,12 +1040,13 @@ function InlineMediaRef({
897
1040
  const url = needsBlob ? blob.url : resolution?.src ?? null;
898
1041
  const recovery = useMediaLoadRecovery(url, {
899
1042
  recoverable: !needsBlob && resolution?.recoverable !== false,
1043
+ failureRef: mediaRef,
900
1044
  onTerminal: (event) => onError?.(
901
1045
  event
902
1046
  )
903
1047
  });
904
1048
  const playback = ports.playbackSession ?? INERT_PLAYBACK;
905
- const sessionElRef = useRef2(null);
1049
+ const sessionElRef = useRef3(null);
906
1050
  const [isMediaPlaying, setIsMediaPlaying] = useState3(false);
907
1051
  const portSinkRef = playback.useMediaElementSink(
908
1052
  mediaElementRef
@@ -949,6 +1093,7 @@ function InlineMediaRef({
949
1093
  alt,
950
1094
  elementType,
951
1095
  mediaRef,
1096
+ failurePhase: status === "unavailable" ? "resolve" : "blob",
952
1097
  dimensions,
953
1098
  rounded,
954
1099
  className
@@ -1003,6 +1148,7 @@ function InlineMediaRef({
1003
1148
  alt,
1004
1149
  elementType,
1005
1150
  mediaRef,
1151
+ failurePhase: "element-load",
1006
1152
  dimensions,
1007
1153
  rounded,
1008
1154
  className
@@ -1129,7 +1275,7 @@ function InlineMediaRef({
1129
1275
  }
1130
1276
 
1131
1277
  // src/react/media-thumbnail.tsx
1132
- import { useEffect as useEffect3, useRef as useRef3 } from "react";
1278
+ import { useEffect as useEffect5, useRef as useRef4 } from "react";
1133
1279
 
1134
1280
  // src/core/use-thumbnail-source.ts
1135
1281
  import { useMemo as useMemo3 } from "react";
@@ -1227,6 +1373,7 @@ function MediaThumbnail({
1227
1373
  VideoPosterThumb,
1228
1374
  {
1229
1375
  url: source.src,
1376
+ mediaRef,
1230
1377
  recoverable: source.recoverable,
1231
1378
  fallback
1232
1379
  }
@@ -1237,6 +1384,7 @@ function MediaThumbnail({
1237
1384
  {
1238
1385
  url: source.src,
1239
1386
  alt: fileName,
1387
+ mediaRef,
1240
1388
  recoverable: source.recoverable,
1241
1389
  fallback
1242
1390
  }
@@ -1254,11 +1402,13 @@ function MediaThumbnail({
1254
1402
  function ImageThumb({
1255
1403
  url,
1256
1404
  alt,
1405
+ mediaRef,
1257
1406
  recoverable,
1258
1407
  fallback
1259
1408
  }) {
1260
1409
  const { retryKey, onLoadError, failed } = useMediaLoadRecovery(url, {
1261
- recoverable
1410
+ recoverable,
1411
+ failureRef: mediaRef
1262
1412
  });
1263
1413
  if (failed) return /* @__PURE__ */ jsx4(Fragment2, { children: fallback });
1264
1414
  return /* @__PURE__ */ jsx4(
@@ -1275,14 +1425,16 @@ function ImageThumb({
1275
1425
  }
1276
1426
  function VideoPosterThumb({
1277
1427
  url,
1428
+ mediaRef,
1278
1429
  recoverable,
1279
1430
  fallback
1280
1431
  }) {
1281
1432
  const { retryKey, onLoadError, failed } = useMediaLoadRecovery(url, {
1282
- recoverable
1433
+ recoverable,
1434
+ failureRef: mediaRef
1283
1435
  });
1284
- const ref = useRef3(null);
1285
- useEffect3(() => {
1436
+ const ref = useRef4(null);
1437
+ useEffect5(() => {
1286
1438
  const v = ref.current;
1287
1439
  if (!v) return void 0;
1288
1440
  const onMeta = () => {
@@ -1312,10 +1464,10 @@ function VideoPosterThumb({
1312
1464
 
1313
1465
  // src/react/use-media-dropzone.ts
1314
1466
  import {
1315
- useCallback as useCallback2,
1316
- useEffect as useEffect4,
1467
+ useCallback as useCallback3,
1468
+ useEffect as useEffect6,
1317
1469
  useMemo as useMemo4,
1318
- useRef as useRef4,
1470
+ useRef as useRef5,
1319
1471
  useState as useState4
1320
1472
  } from "react";
1321
1473
  function matchesAccept(file, accept) {
@@ -1343,14 +1495,14 @@ function useMediaDropzone(options) {
1343
1495
  } = options;
1344
1496
  const [isDragActive, setIsDragActive] = useState4(false);
1345
1497
  const [pasteHighlight, setPasteHighlight] = useState4(false);
1346
- const dragDepth = useRef4(0);
1347
- const inputRef = useRef4(null);
1348
- const onFilesRef = useRef4(onFiles);
1498
+ const dragDepth = useRef5(0);
1499
+ const inputRef = useRef5(null);
1500
+ const onFilesRef = useRef5(onFiles);
1349
1501
  onFilesRef.current = onFiles;
1350
- const onRejectedRef = useRef4(onRejected);
1502
+ const onRejectedRef = useRef5(onRejected);
1351
1503
  onRejectedRef.current = onRejected;
1352
1504
  const acceptKey = accept?.join(",") ?? "";
1353
- const filterFiles = useCallback2(
1505
+ const filterFiles = useCallback3(
1354
1506
  (files) => {
1355
1507
  const accepted = [];
1356
1508
  const rejected = [];
@@ -1368,23 +1520,23 @@ function useMediaDropzone(options) {
1368
1520
  },
1369
1521
  [acceptKey, maxSize]
1370
1522
  );
1371
- const emit = useCallback2(
1523
+ const emit = useCallback3(
1372
1524
  (files) => {
1373
1525
  const accepted = filterFiles(files);
1374
1526
  if (accepted.length) onFilesRef.current(accepted);
1375
1527
  },
1376
1528
  [filterFiles]
1377
1529
  );
1378
- const openPicker = useCallback2(() => {
1530
+ const openPicker = useCallback3(() => {
1379
1531
  if (!disabled) inputRef.current?.click();
1380
1532
  }, [disabled]);
1381
- useEffect4(() => {
1533
+ useEffect6(() => {
1382
1534
  if (!pickerEventName || typeof window === "undefined") return void 0;
1383
1535
  const handler = () => openPicker();
1384
1536
  window.addEventListener(pickerEventName, handler);
1385
1537
  return () => window.removeEventListener(pickerEventName, handler);
1386
1538
  }, [openPicker, pickerEventName]);
1387
- useEffect4(() => {
1539
+ useEffect6(() => {
1388
1540
  if (!enablePaste || disabled || typeof window === "undefined") {
1389
1541
  return void 0;
1390
1542
  }
@@ -1410,7 +1562,7 @@ function useMediaDropzone(options) {
1410
1562
  window.addEventListener("paste", handler);
1411
1563
  return () => window.removeEventListener("paste", handler);
1412
1564
  }, [enablePaste, disabled, emit]);
1413
- const getRootProps = useCallback2(
1565
+ const getRootProps = useCallback3(
1414
1566
  () => ({
1415
1567
  onDragEnter: (event) => {
1416
1568
  if (disabled) return;
@@ -1443,7 +1595,7 @@ function useMediaDropzone(options) {
1443
1595
  () => acceptKey.length ? acceptKey : void 0,
1444
1596
  [acceptKey]
1445
1597
  );
1446
- const getInputProps = useCallback2(
1598
+ const getInputProps = useCallback3(
1447
1599
  () => ({
1448
1600
  ref: (node) => {
1449
1601
  inputRef.current = node;
@@ -1465,10 +1617,10 @@ function useMediaDropzone(options) {
1465
1617
  }
1466
1618
 
1467
1619
  // src/react/file-upload-dropzone.tsx
1468
- import { useCallback as useCallback4 } from "react";
1620
+ import { useCallback as useCallback5 } from "react";
1469
1621
 
1470
1622
  // src/core/use-media-upload.ts
1471
- import { useCallback as useCallback3, useRef as useRef5, useState as useState5 } from "react";
1623
+ import { useCallback as useCallback4, useRef as useRef6, useState as useState5 } from "react";
1472
1624
  var entrySeq = 0;
1473
1625
  function useMediaUpload() {
1474
1626
  const client = useMediaClient();
@@ -1477,8 +1629,8 @@ function useMediaUpload() {
1477
1629
  const [result, setResult] = useState5(null);
1478
1630
  const [error, setError] = useState5(null);
1479
1631
  const [entries, setEntries] = useState5([]);
1480
- const activeCount = useRef5(0);
1481
- const patchEntry = useCallback3(
1632
+ const activeCount = useRef6(0);
1633
+ const patchEntry = useCallback4(
1482
1634
  (id, patch) => {
1483
1635
  setEntries(
1484
1636
  (current) => current.map((e) => e.id === id ? { ...e, ...patch } : e)
@@ -1486,7 +1638,7 @@ function useMediaUpload() {
1486
1638
  },
1487
1639
  []
1488
1640
  );
1489
- const upload = useCallback3(
1641
+ const upload = useCallback4(
1490
1642
  async (file, opts = {}) => {
1491
1643
  const id = `up-${++entrySeq}`;
1492
1644
  const fileName = opts.fileName ?? (file instanceof File ? file.name : "file");
@@ -1540,7 +1692,7 @@ function useMediaUpload() {
1540
1692
  },
1541
1693
  [client, patchEntry]
1542
1694
  );
1543
- const uploadMany = useCallback3(
1695
+ const uploadMany = useCallback4(
1544
1696
  async (files, opts = {}) => {
1545
1697
  if (client.uploadMany) {
1546
1698
  activeCount.current += 1;
@@ -1569,10 +1721,10 @@ function useMediaUpload() {
1569
1721
  },
1570
1722
  [client, upload]
1571
1723
  );
1572
- const clearEntry = useCallback3((id) => {
1724
+ const clearEntry = useCallback4((id) => {
1573
1725
  setEntries((current) => current.filter((e) => e.id !== id));
1574
1726
  }, []);
1575
- const reset = useCallback3(() => {
1727
+ const reset = useCallback4(() => {
1576
1728
  setResult(null);
1577
1729
  setError(null);
1578
1730
  setProgress(null);
@@ -1592,7 +1744,7 @@ function useMediaUpload() {
1592
1744
  }
1593
1745
 
1594
1746
  // src/react/upload-progress-list.tsx
1595
- import { memo, useEffect as useEffect5, useRef as useRef6, useState as useState6 } from "react";
1747
+ import { memo, useEffect as useEffect7, useRef as useRef7, useState as useState6 } from "react";
1596
1748
  import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
1597
1749
  var AUTO_DISMISS_MS = 1e4;
1598
1750
  function formatFileSize(bytes) {
@@ -1617,12 +1769,12 @@ function UploadProgressListImpl({
1617
1769
  const activeCount = uploads.filter((u) => u.status === "uploading").length;
1618
1770
  const successCount = uploads.filter((u) => u.status === "success").length;
1619
1771
  const errorCount = uploads.filter((u) => u.status === "error").length;
1620
- const timersRef = useRef6(
1772
+ const timersRef = useRef7(
1621
1773
  /* @__PURE__ */ new Map()
1622
1774
  );
1623
- const onDismissRef = useRef6(onDismiss);
1775
+ const onDismissRef = useRef7(onDismiss);
1624
1776
  onDismissRef.current = onDismiss;
1625
- useEffect5(() => {
1777
+ useEffect7(() => {
1626
1778
  const timers = timersRef.current;
1627
1779
  if (hovered) {
1628
1780
  timers.forEach((t) => clearTimeout(t));
@@ -1650,7 +1802,7 @@ function UploadProgressListImpl({
1650
1802
  }
1651
1803
  }
1652
1804
  }, [uploads, hovered]);
1653
- useEffect5(() => {
1805
+ useEffect7(() => {
1654
1806
  const timers = timersRef.current;
1655
1807
  return () => {
1656
1808
  timers.forEach((t) => clearTimeout(t));
@@ -1782,7 +1934,7 @@ function FileUploadDropzone({
1782
1934
  pickerEventName
1783
1935
  }) {
1784
1936
  const { uploadMany, entries, clearEntry } = useMediaUpload();
1785
- const handleUpload = useCallback4(
1937
+ const handleUpload = useCallback5(
1786
1938
  async (files) => {
1787
1939
  if (!files.length) return;
1788
1940
  try {
@@ -1892,7 +2044,7 @@ function FileUploadDropzone({
1892
2044
  import { useState as useState8 } from "react";
1893
2045
 
1894
2046
  // src/core/use-media-actions.ts
1895
- import { useCallback as useCallback5, useMemo as useMemo5, useState as useState7 } from "react";
2047
+ import { useCallback as useCallback6, useMemo as useMemo5, useState as useState7 } from "react";
1896
2048
  function useMediaActions(ref, options = {}) {
1897
2049
  const ports = useMediaHostPorts();
1898
2050
  const { resolution } = useMediaResolution(ref);
@@ -1904,7 +2056,7 @@ function useMediaActions(ref, options = {}) {
1904
2056
  if (!ref) return null;
1905
2057
  return { ref, resolution, fileName, alt };
1906
2058
  }, [ref, resolution, fileName, alt]);
1907
- const isAvailable = useCallback5(
2059
+ const isAvailable = useCallback6(
1908
2060
  (kind) => {
1909
2061
  if (!context || !actions) return false;
1910
2062
  if (kind === "share") return Boolean(actions.share || actions.SharePopover);
@@ -1912,7 +2064,7 @@ function useMediaActions(ref, options = {}) {
1912
2064
  },
1913
2065
  [context, actions]
1914
2066
  );
1915
- const run = useCallback5(
2067
+ const run = useCallback6(
1916
2068
  async (kind) => {
1917
2069
  if (!context || !actions) return;
1918
2070
  const handler = actions[kind];
@@ -2018,7 +2170,7 @@ function MediaActionToolbar({
2018
2170
  }
2019
2171
 
2020
2172
  // src/react/media-lightbox.tsx
2021
- import { useEffect as useEffect6 } from "react";
2173
+ import { useEffect as useEffect8 } from "react";
2022
2174
  import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
2023
2175
  function MediaLightbox({
2024
2176
  open,
@@ -2036,7 +2188,7 @@ function MediaLightbox({
2036
2188
  headerExtra,
2037
2189
  className
2038
2190
  }) {
2039
- useEffect6(() => {
2191
+ useEffect8(() => {
2040
2192
  if (!open || typeof window === "undefined") return void 0;
2041
2193
  const handler = (event) => {
2042
2194
  if (event.key === "Escape") {