sanity-plugin-mux-input 4.0.3 → 4.1.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/index.d.ts CHANGED
@@ -214,6 +214,7 @@ interface MuxAsset {
214
214
  status: 'preparing' | 'ready' | 'errored';
215
215
  duration: number;
216
216
  max_stored_resolution: 'Audio only' | 'SD' | 'HD' | 'FHD' | 'UHD';
217
+ max_resolution_tier?: '2160p' | '1440p' | '1080p';
217
218
  max_stored_frame_rate: -1 | number;
218
219
  aspect_ratio: `${number}:${number}`;
219
220
  playback_ids: MuxPlaybackId[];
@@ -225,7 +226,7 @@ interface MuxAsset {
225
226
  live_stream_id?: string;
226
227
  master?: {
227
228
  status: 'ready' | 'preparing' | 'errored';
228
- url: string;
229
+ url?: string;
229
230
  };
230
231
  master_access: 'temporary' | 'none';
231
232
  mp4_support: 'standard' | 'none';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/util/types.ts","../src/_exports/index.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/util/types.ts","../src/_exports/index.ts"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { useClient as useClient$1, createHookFromObservableFactory, useDocumentStore, collate, useDocumentValues, truncateString, useFormattedDuration, SanityDefaultPreview, useTimeAgo, TextWithTone, isRecord, getPreviewStateObservable, getPreviewValueWithFallback, DocumentPreviewPresence, useDocumentPreviewStore, useSchema, useDocumentPresence, PreviewCard, useCurrentUser, isReference, useProjectId, useDataset, PatchEvent, unset, setIfMissing, set, LinearProgress, FormField as FormField$2, definePlugin } from "sanity";
2
2
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
3
- import { ErrorOutlineIcon, InfoOutlineIcon, RetryIcon, CheckmarkCircleIcon, RetrieveIcon, ChevronLeftIcon, ChevronRightIcon, SyncIcon, SortIcon, UploadIcon, TranslateIcon, DownloadIcon, AddIcon, ChevronUpIcon, ChevronDownIcon, TrashIcon, EditIcon, WarningOutlineIcon, PublishIcon, DocumentIcon, RevertIcon, SearchIcon, ClockIcon, CropIcon, CalendarIcon, TagIcon, CheckmarkIcon, LockIcon, PlayIcon, PlugIcon, EllipsisHorizontalIcon, ImageIcon, ResetIcon, WarningFilledIcon, DocumentVideoIcon } from "@sanity/icons";
3
+ import { ErrorOutlineIcon, InfoOutlineIcon, RetryIcon, CheckmarkCircleIcon, RetrieveIcon, ChevronLeftIcon, ChevronRightIcon, SyncIcon, SortIcon, DownloadIcon, UploadIcon, TranslateIcon, AddIcon, ChevronUpIcon, ChevronDownIcon, TrashIcon, EditIcon, WarningOutlineIcon, PublishIcon, DocumentIcon, RevertIcon, SearchIcon, ClockIcon, CropIcon, CalendarIcon, TagIcon, CheckmarkIcon, LockIcon, PlayIcon, PlugIcon, EllipsisHorizontalIcon, ImageIcon, ResetIcon, WarningFilledIcon, DocumentVideoIcon } from "@sanity/icons";
4
4
  import { Dialog, Stack, Card, Text, Button, useTheme_v2, Flex, Box, TextInput, Checkbox, Code, Inline, Spinner, Heading, Label as Label$1, Radio, MenuButton, Menu, MenuItem, useToast, Autocomplete, Tooltip, TabList, Tab, TabPanel, Grid, useClickOutsideEvent, Popover, MenuDivider, rem } from "@sanity/ui";
5
5
  import { createContext, useState, useCallback, useMemo, useContext, useReducer, useId, memo, useRef, useEffect, Suspense, isValidElement, forwardRef } from "react";
6
6
  import compact from "lodash/compact.js";
@@ -142,7 +142,7 @@ function useDialogState() {
142
142
  const PLUGIN_VERSION_QUERY = {
143
143
  sanityVersion: (
144
144
  // @ts-expect-error - this constant is search/replaced so must be exact, not accessed with an index signature
145
- "4.0.3"
145
+ "4.1.0"
146
146
  )
147
147
  };
148
148
  function saveSecrets(client, token, secretKey, enableSignedUrls, signingKeyId, signingKeyPrivate, drmConfigId) {
@@ -250,7 +250,7 @@ const useSaveSecrets = (client, secrets) => useCallback(async ({
250
250
  signingKeyPrivate,
251
251
  drmConfigId
252
252
  };
253
- }, [client, secrets]), name = "mux-input", cacheNs = "sanity-plugin-mux-input", muxSecretsDocumentId = "secrets.mux", DIALOGS_Z_INDEX = 6e4, THUMBNAIL_ASPECT_RATIO = 1.7777777777777777, MIN_ASPECT_RATIO = 5 / 4, AUDIO_ASPECT_RATIO = 5 / 1, path$1 = ["token", "secretKey", "enableSignedUrls", "signingKeyId", "signingKeyPrivate", "drmConfigId"], useSecretsDocumentValues = () => {
253
+ }, [client, secrets]), name = "mux-input", cacheNs = "sanity-plugin-mux-input", muxSecretsDocumentId = "secrets.mux", DIALOGS_Z_INDEX = 6e4, MEZZANINE_LEARN_MORE_URL = "https://www.mux.com/docs/guides/download-for-offline-editing#enable-master-access", THUMBNAIL_ASPECT_RATIO = 1.7777777777777777, MIN_ASPECT_RATIO = 5 / 4, AUDIO_ASPECT_RATIO = 5 / 1, path$1 = ["token", "secretKey", "enableSignedUrls", "signingKeyId", "signingKeyPrivate", "drmConfigId"], useSecretsDocumentValues = () => {
254
254
  const {
255
255
  error,
256
256
  isLoading,
@@ -638,6 +638,23 @@ function deleteTextTrack(client, assetId, trackId) {
638
638
  query: PLUGIN_VERSION_QUERY
639
639
  });
640
640
  }
641
+ function updateMasterAccess(client, assetId, masterAccess) {
642
+ const {
643
+ dataset
644
+ } = client.config();
645
+ return client.request({
646
+ url: `/addons/mux/assets/${dataset}/${assetId}/master-access`,
647
+ withCredentials: !0,
648
+ method: "PUT",
649
+ body: {
650
+ master_access: masterAccess
651
+ },
652
+ headers: {
653
+ "Content-Type": "application/json"
654
+ },
655
+ query: PLUGIN_VERSION_QUERY
656
+ });
657
+ }
641
658
  const ASSETS_PER_PAGE = 100;
642
659
  async function fetchMuxAssetsPage(client, cursor) {
643
660
  try {
@@ -1135,19 +1152,19 @@ const PageSelector = (props) => {
1135
1152
  function addKeysToMuxData(data) {
1136
1153
  return {
1137
1154
  ...data,
1138
- tracks: data.tracks?.map((track) => ({
1155
+ tracks: data.tracks?.map((track, index) => ({
1139
1156
  ...track,
1140
- _key: uuid()
1157
+ _key: track.id || `track-${index}`
1141
1158
  })),
1142
- playback_ids: data.playback_ids?.map((playbackId) => ({
1159
+ playback_ids: data.playback_ids?.map((playbackId, index) => ({
1143
1160
  ...playbackId,
1144
- _key: uuid()
1161
+ _key: playbackId.id || `playback-${index}`
1145
1162
  })),
1146
1163
  static_renditions: data.static_renditions ? {
1147
1164
  ...data.static_renditions,
1148
- files: data.static_renditions.files?.map((file) => ({
1165
+ files: data.static_renditions.files?.map((file, index) => ({
1149
1166
  ...file,
1150
- _key: uuid()
1167
+ _key: file.id || `rendition-${index}`
1151
1168
  }))
1152
1169
  } : void 0
1153
1170
  };
@@ -1393,6 +1410,144 @@ function StopWatchIcon(props) {
1393
1410
  /* @__PURE__ */ jsx("path", { d: "M192 32h128v48H192z", fill: "currentColor" })
1394
1411
  ] });
1395
1412
  }
1413
+ const POLL_INTERVAL_MS = 3e3;
1414
+ function getMezzanineStatus(asset) {
1415
+ const master = asset.data?.master;
1416
+ return master?.status === "preparing" ? "preparing" : master?.status === "ready" && master.url ? "ready" : master?.status === "errored" ? "errored" : "disabled";
1417
+ }
1418
+ function useMezzanine(asset) {
1419
+ const client = useClient(), toast = useToast(), master = asset.data?.master, [busy, setBusy] = useState(!1), [expired, setExpired] = useState(!1), [prevAssetId, setPrevAssetId] = useState(asset.assetId);
1420
+ prevAssetId !== asset.assetId && (setPrevAssetId(asset.assetId), setExpired(!1));
1421
+ const resolution = useMemo(() => asset.data?.max_resolution_tier || asset.data?.max_stored_resolution || void 0, [asset.data?.max_resolution_tier, asset.data?.max_stored_resolution]), status = getMezzanineStatus(asset), persist = useCallback(async (data) => {
1422
+ asset._id && await client.patch(asset._id).set({
1423
+ status: data.status,
1424
+ data: addKeysToMuxData(data)
1425
+ }).commit({
1426
+ returnDocuments: !1
1427
+ });
1428
+ }, [asset._id, client]), refresh = useCallback(async () => {
1429
+ if (!asset.assetId || !asset._id) return;
1430
+ const {
1431
+ data
1432
+ } = await getAsset(client, asset.assetId);
1433
+ return await persist(data), data;
1434
+ }, [asset.assetId, asset._id, client, persist]);
1435
+ useEffect(() => {
1436
+ if (master?.status !== "preparing" || !asset.assetId || !asset._id) return;
1437
+ let cancelled = !1, running = !1;
1438
+ const interval = setInterval(async () => {
1439
+ if (!running) {
1440
+ running = !0;
1441
+ try {
1442
+ const data = await refresh();
1443
+ if (cancelled) return;
1444
+ (!data || data.master?.status !== "preparing") && clearInterval(interval);
1445
+ } catch (error) {
1446
+ console.error("Failed to poll mezzanine status:", error);
1447
+ } finally {
1448
+ running = !1;
1449
+ }
1450
+ }
1451
+ }, POLL_INTERVAL_MS);
1452
+ return () => {
1453
+ cancelled = !0, clearInterval(interval);
1454
+ };
1455
+ }, [master?.status, asset.assetId, asset._id, refresh]);
1456
+ const enable = useCallback(async () => {
1457
+ if (!(!asset.assetId || !asset._id)) {
1458
+ setBusy(!0), setExpired(!1);
1459
+ try {
1460
+ const {
1461
+ data
1462
+ } = await updateMasterAccess(client, asset.assetId, "temporary");
1463
+ await persist(data);
1464
+ } catch (error) {
1465
+ toast.push({
1466
+ status: "error",
1467
+ title: "Could not enable the mezzanine file",
1468
+ description: error instanceof Error ? error.message : "Please try again"
1469
+ });
1470
+ } finally {
1471
+ setBusy(!1);
1472
+ }
1473
+ }
1474
+ }, [asset.assetId, asset._id, client, persist, toast]), download = useCallback(async () => {
1475
+ if (asset.assetId) {
1476
+ setBusy(!0);
1477
+ try {
1478
+ const data = await refresh(), url = data?.master?.status === "ready" ? data.master.url : void 0;
1479
+ url ? (setExpired(!1), triggerMezzanineDownload(url)) : setExpired(!0);
1480
+ } catch (error) {
1481
+ toast.push({
1482
+ status: "error",
1483
+ title: "Could not download the mezzanine file",
1484
+ description: error instanceof Error ? error.message : "Please try again"
1485
+ });
1486
+ } finally {
1487
+ setBusy(!1);
1488
+ }
1489
+ }
1490
+ }, [asset.assetId, refresh, toast]);
1491
+ return {
1492
+ status,
1493
+ busy,
1494
+ expired,
1495
+ resolution,
1496
+ enable,
1497
+ download
1498
+ };
1499
+ }
1500
+ function triggerMezzanineDownload(masterUrl) {
1501
+ if (typeof window > "u") return;
1502
+ const anchor = document.createElement("a");
1503
+ anchor.href = masterUrl, anchor.target = "_blank", anchor.rel = "noopener noreferrer", document.body.appendChild(anchor), anchor.click(), document.body.removeChild(anchor);
1504
+ }
1505
+ function MezzanineExplanation() {
1506
+ return /* @__PURE__ */ jsxs(Stack, { space: 3, children: [
1507
+ /* @__PURE__ */ jsx(Text, { size: 1, muted: !0, children: "When you enable the mezzanine file, Mux creates a copy equivalent in quality to your original video \u2014 ideal for offline editing or archiving. Unlike the streamable MP4 (static) renditions, it is not meant for streaming." }),
1508
+ /* @__PURE__ */ jsx(Text, { size: 1, muted: !0, children: "The file is prepared in the background and may take a few minutes depending on the asset's duration and resolution. Enabling is free and the download stays available for 24 hours." })
1509
+ ] });
1510
+ }
1511
+ function Mezzanine({
1512
+ asset,
1513
+ withExplanation = !0
1514
+ }) {
1515
+ const {
1516
+ status,
1517
+ busy,
1518
+ expired,
1519
+ resolution,
1520
+ enable,
1521
+ download
1522
+ } = useMezzanine(asset), assetReady = asset.status === "ready" || asset.data?.status === "ready", isReady = status === "ready" && !expired, isPreparing = status === "preparing", showExplanation = !isReady && !isPreparing;
1523
+ return /* @__PURE__ */ jsx(Card, { padding: 3, radius: 2, tone: "transparent", border: !0, children: /* @__PURE__ */ jsxs(Stack, { space: 4, children: [
1524
+ /* @__PURE__ */ jsxs(Flex, { align: "center", justify: "space-between", gap: 3, children: [
1525
+ /* @__PURE__ */ jsx(Label$1, { muted: !0, size: 1, children: "Mezzanine" }),
1526
+ /* @__PURE__ */ jsx(Text, { size: 1, children: /* @__PURE__ */ jsx("a", { href: MEZZANINE_LEARN_MORE_URL, target: "_blank", rel: "noopener noreferrer", children: "Learn more" }) })
1527
+ ] }),
1528
+ /* @__PURE__ */ jsxs(Stack, { space: 2, children: [
1529
+ /* @__PURE__ */ jsx(Text, { size: 1, muted: !isReady, children: "mezzanine.mp4" }),
1530
+ resolution && /* @__PURE__ */ jsx(Text, { size: 1, muted: !0, children: resolution })
1531
+ ] }),
1532
+ withExplanation && showExplanation && /* @__PURE__ */ jsx(MezzanineExplanation, {}),
1533
+ showExplanation && (expired || status === "errored") && /* @__PURE__ */ jsxs(Stack, { space: 2, children: [
1534
+ expired && /* @__PURE__ */ jsx(Text, { size: 1, muted: !0, children: "The previous mezzanine file expired. Enable it again to download." }),
1535
+ status === "errored" && /* @__PURE__ */ jsx(Text, { size: 1, style: {
1536
+ color: "var(--card-critical-color)"
1537
+ }, children: "Mux could not prepare the mezzanine file. Please try again." })
1538
+ ] }),
1539
+ isPreparing && /* @__PURE__ */ jsx(Text, { size: 1, muted: !0, children: "Preparing the mezzanine file\u2026 this can take a few minutes. You can close this and come back later." }),
1540
+ isReady && /* @__PURE__ */ jsx(Text, { size: 1, muted: !0, children: "Ready to download. The link stays available for about 24 hours." }),
1541
+ /* @__PURE__ */ jsx(Flex, { justify: "flex-end", gap: 2, children: isPreparing ? /* @__PURE__ */ jsxs(Flex, { align: "center", gap: 2, children: [
1542
+ /* @__PURE__ */ jsx(Spinner, { muted: !0, size: 1 }),
1543
+ /* @__PURE__ */ jsx(Text, { size: 1, muted: !0, children: "Preparing\u2026" })
1544
+ ] }) : isReady ? /* @__PURE__ */ jsx(Button, { icon: DownloadIcon, text: "Download", tone: "positive", fontSize: 1, padding: 3, loading: busy, disabled: busy, onClick: () => {
1545
+ download();
1546
+ } }) : /* @__PURE__ */ jsx(Button, { text: status === "errored" ? "Try again" : "Enable", tone: "primary", fontSize: 1, padding: 3, loading: busy, disabled: busy || !assetReady, onClick: () => {
1547
+ enable();
1548
+ } }) })
1549
+ ] }) });
1550
+ }
1396
1551
  function useResyncAsset(options) {
1397
1552
  const client = useClient(), toast = useToast(), [resyncState, setResyncState] = useState("idle"), [resyncError, setResyncError] = useState(null), showToast = options?.showToast ?? !1, resyncAsset = useCallback(async (asset) => {
1398
1553
  if (!asset.assetId) {
@@ -2472,6 +2627,20 @@ function AudioIcon(props) {
2472
2627
  opacity: "0.65"
2473
2628
  }, d: "M10.75 19q.95 0 1.6-.65t.65-1.6V13h3v-2h-4v3.875q-.275-.2-.587-.288t-.663-.087q-.95 0-1.6.65t-.65 1.6t.65 1.6t1.6.65M6 22q-.825 0-1.412-.587T4 20V4q0-.825.588-1.412T6 2h8l6 6v12q0 .825-.587 1.413T18 22zm7-13V4H6v16h12V9zM6 4v5zv16z" }) });
2474
2629
  }
2630
+ function MezzanineDialog({
2631
+ asset,
2632
+ onClose
2633
+ }) {
2634
+ const {
2635
+ setDialogState
2636
+ } = useDialogStateContext(), dialogId = `MezzanineDialog${useId()}`, closing = () => {
2637
+ onClose?.(), setDialogState(!1);
2638
+ }, status = getMezzanineStatus(asset);
2639
+ return /* @__PURE__ */ jsx(Dialog, { id: dialogId, header: "Mezzanine file", onClose: closing, zOffset: DIALOGS_Z_INDEX, width: 1, children: /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsxs(Stack, { space: 4, children: [
2640
+ status !== "preparing" && status !== "ready" && /* @__PURE__ */ jsx(MezzanineExplanation, {}),
2641
+ /* @__PURE__ */ jsx(Mezzanine, { asset, withExplanation: !1 })
2642
+ ] }) }) });
2643
+ }
2475
2644
  function VideoPlayer({
2476
2645
  asset,
2477
2646
  thumbnailWidth = 250,
@@ -2560,7 +2729,7 @@ function VideoPlayer({
2560
2729
  /* @__PURE__ */ jsx(MuxPlayer, { poster: isAudio ? void 0 : poster, ref: muxPlayer, ...props, playsInline: !0, playbackId, tokens, preload: "metadata", crossOrigin: "anonymous", metadata: {
2561
2730
  player_name: "Sanity Admin Dashboard",
2562
2731
  // @ts-expect-error - this constant is search/replaced so must be exact, not accessed with an index signature
2563
- player_version: "4.0.3",
2732
+ player_version: "4.1.0",
2564
2733
  page_type: "Preview Player"
2565
2734
  }, audio: isAudio, _hlsConfig: hlsConfig, style: {
2566
2735
  ...!isAudio && {
@@ -2596,7 +2765,8 @@ function VideoPlayer({
2596
2765
  currentTime: muxPlayer?.current?.currentTime
2597
2766
  }
2598
2767
  ),
2599
- dialogState === "edit-captions" && /* @__PURE__ */ jsx(CaptionsDialog, { asset })
2768
+ dialogState === "edit-captions" && /* @__PURE__ */ jsx(CaptionsDialog, { asset }),
2769
+ dialogState === "mezzanine" && /* @__PURE__ */ jsx(MezzanineDialog, { asset })
2600
2770
  ] });
2601
2771
  }
2602
2772
  function assetIsAudio(asset) {
@@ -2943,7 +3113,10 @@ const AssetInput = (props) => /* @__PURE__ */ jsx(FormField, { title: props.labe
2943
3113
  } : void 0, children: [
2944
3114
  /* @__PURE__ */ jsxs(Stack, { space: 4, flex: 1, sizing: "border", children: [
2945
3115
  /* @__PURE__ */ jsx(VideoPlayer, { asset: props.asset, autoPlay: props.asset.autoPlay || !1 }),
2946
- tab === "details" && /* @__PURE__ */ jsx(TextTracksManager, { asset: props.asset, iconOnly: !0, collapseTracks: !0, tracks: displayInfo?.text_tracks || props.asset.data?.tracks?.filter((track) => track.type === "text") || [] })
3116
+ tab === "details" && /* @__PURE__ */ jsxs(Fragment, { children: [
3117
+ /* @__PURE__ */ jsx(TextTracksManager, { asset: props.asset, iconOnly: !0, collapseTracks: !0, tracks: displayInfo?.text_tracks || props.asset.data?.tracks?.filter((track) => track.type === "text") || [] }),
3118
+ /* @__PURE__ */ jsx(Mezzanine, { asset: props.asset })
3119
+ ] })
2947
3120
  ] }),
2948
3121
  /* @__PURE__ */ jsxs(Stack, { space: 4, flex: 1, sizing: "border", children: [
2949
3122
  /* @__PURE__ */ jsxs(TabList, { space: 2, children: [
@@ -3142,22 +3315,31 @@ const useAccessControl = (config) => {
3142
3315
  return !1;
3143
3316
  const files = asset?.data?.static_renditions?.files;
3144
3317
  return !files || files.length === 0 ? !1 : files.some((file) => file.status === "preparing");
3145
- }, [asset?.data?.static_renditions?.status, asset?.data?.static_renditions?.files]), shouldFetch = useMemo(() => !!asset?.assetId && (asset?.status === "preparing" || isPreparingStaticRenditions), [asset?.assetId, asset?.status, isPreparingStaticRenditions]);
3318
+ }, [asset?.data?.static_renditions?.status, asset?.data?.static_renditions?.files]), shouldFetch = useMemo(() => !!asset?.assetId && (asset?.status === "preparing" || isPreparingStaticRenditions), [asset?.assetId, asset?.status, isPreparingStaticRenditions]), errorLoggedRef = useRef(!1);
3146
3319
  return useSWR(shouldFetch ? `/${projectId}/addons/mux/assets/${dataset}/data/${asset?.assetId}` : null, async () => {
3147
- const {
3148
- data
3149
- } = await client.request({
3150
- url: `/addons/mux/assets/${dataset}/data/${asset.assetId}`,
3151
- withCredentials: !0,
3152
- method: "GET",
3153
- query: PLUGIN_VERSION_QUERY
3154
- });
3155
- await client.patch(asset._id).set({
3156
- status: data.status,
3157
- data
3158
- }).commit({
3159
- returnDocuments: !1
3160
- });
3320
+ try {
3321
+ const {
3322
+ data
3323
+ } = await client.request({
3324
+ url: `/addons/mux/assets/${dataset}/data/${asset.assetId}`,
3325
+ withCredentials: !0,
3326
+ method: "GET",
3327
+ query: PLUGIN_VERSION_QUERY
3328
+ });
3329
+ if (!asset?._id || !data) return;
3330
+ await client.patch(asset._id).set({
3331
+ status: data.status,
3332
+ data: addKeysToMuxData(data)
3333
+ }).commit({
3334
+ returnDocuments: !1
3335
+ }), errorLoggedRef.current = !1;
3336
+ } catch (error) {
3337
+ errorLoggedRef.current || (errorLoggedRef.current = !0, console.error("[sanity-plugin-mux-input] Mux polling failed", {
3338
+ assetId: asset?.assetId,
3339
+ documentId: asset?._id,
3340
+ error
3341
+ }));
3342
+ }
3161
3343
  }, {
3162
3344
  refreshInterval: 2e3,
3163
3345
  refreshWhenHidden: !0,
@@ -3748,6 +3930,8 @@ function PlayerActionsMenu$1(props) {
3748
3930
  /* @__PURE__ */ jsx(MenuItem, { icon: SyncIcon, text: "Resync from Mux", onClick: handleResync, disabled: readOnly || isResyncing })
3749
3931
  ] }),
3750
3932
  /* @__PURE__ */ jsx(MenuDivider, {}),
3933
+ /* @__PURE__ */ jsx(MenuItem, { icon: DownloadIcon, text: "Mezzanine", onClick: () => setDialogState("mezzanine") }),
3934
+ /* @__PURE__ */ jsx(MenuDivider, {}),
3751
3935
  hasConfigAccess && /* @__PURE__ */ jsxs(Fragment, { children: [
3752
3936
  /* @__PURE__ */ jsx(MenuItem, { icon: PlugIcon, text: "Configure API", onClick: () => setDialogState("secrets") }),
3753
3937
  /* @__PURE__ */ jsx(MenuDivider, {})
@@ -5538,6 +5722,16 @@ const muxVideoSchema = {
5538
5722
  type: "mux.staticRenditionFile"
5539
5723
  }]
5540
5724
  }]
5725
+ }, muxMasterFile = {
5726
+ name: "mux.masterFile",
5727
+ type: "object",
5728
+ fields: [{
5729
+ type: "string",
5730
+ name: "status"
5731
+ }, {
5732
+ type: "string",
5733
+ name: "url"
5734
+ }]
5541
5735
  }, muxAssetData = {
5542
5736
  name: "mux.assetData",
5543
5737
  title: "Mux asset data",
@@ -5602,6 +5796,9 @@ const muxVideoSchema = {
5602
5796
  }, {
5603
5797
  name: "static_renditions",
5604
5798
  type: "mux.staticRenditions"
5799
+ }, {
5800
+ name: "master",
5801
+ type: "mux.masterFile"
5605
5802
  }]
5606
5803
  }, muxVideoAsset = {
5607
5804
  name: "mux.videoAsset",
@@ -5626,7 +5823,7 @@ const muxVideoSchema = {
5626
5823
  type: "mux.assetData",
5627
5824
  name: "data"
5628
5825
  }]
5629
- }, schemaTypes = [muxTrack, muxPlaybackId, muxStaticRenditionFile, muxStaticRenditions, muxAssetData, muxVideoAsset], defaultConfig = {
5826
+ }, schemaTypes = [muxTrack, muxPlaybackId, muxStaticRenditionFile, muxStaticRenditions, muxMasterFile, muxAssetData, muxVideoAsset], defaultConfig = {
5630
5827
  static_renditions: [],
5631
5828
  mp4_support: "none",
5632
5829
  video_quality: "plus",