sanity-plugin-mux-input 2.10.0 → 2.11.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.mjs CHANGED
@@ -1488,14 +1488,18 @@ function VideoPlayer({
1488
1488
  children,
1489
1489
  ...props
1490
1490
  }) {
1491
- const client = useClient(), { dialogState } = useDialogStateContext(), isAudio = assetIsAudio(asset), muxPlayer = useRef(null), thumbnail = getPosterSrc({ asset, client, width: thumbnailWidth }), { src: videoSrc, error } = useMemo(() => {
1491
+ const client = useClient(), { dialogState } = useDialogStateContext(), isAudio = assetIsAudio(asset), muxPlayer = useRef(null), {
1492
+ src: videoSrc,
1493
+ thumbnail: thumbnailSrc,
1494
+ error
1495
+ } = useMemo(() => {
1492
1496
  try {
1493
- const src = asset?.playbackId && getVideoSrc({ client, asset });
1494
- return src ? { src } : { error: new TypeError("Asset has no playback ID") };
1497
+ const thumbnail = getPosterSrc({ asset, client, width: thumbnailWidth }), src = asset?.playbackId && getVideoSrc({ client, asset });
1498
+ return src ? { src, thumbnail } : { error: new TypeError("Asset has no playback ID") };
1495
1499
  } catch (error2) {
1496
1500
  return { error: error2 };
1497
1501
  }
1498
- }, [asset, client]), signedToken = useMemo(() => {
1502
+ }, [asset, client, thumbnailWidth]), signedToken = useMemo(() => {
1499
1503
  try {
1500
1504
  return new URL(videoSrc).searchParams.get("token");
1501
1505
  } catch {
@@ -1512,7 +1516,7 @@ function VideoPlayer({
1512
1516
  /* @__PURE__ */ jsx(
1513
1517
  MuxPlayer,
1514
1518
  {
1515
- poster: thumbnail,
1519
+ poster: thumbnailSrc,
1516
1520
  ref: muxPlayer,
1517
1521
  ...props,
1518
1522
  playsInline: !0,
@@ -1522,7 +1526,7 @@ function VideoPlayer({
1522
1526
  crossOrigin: "anonymous",
1523
1527
  metadata: {
1524
1528
  player_name: "Sanity Admin Dashboard",
1525
- player_version: "2.10.0",
1529
+ player_version: "2.11.0",
1526
1530
  page_type: "Preview Player"
1527
1531
  },
1528
1532
  audio: isAudio,
@@ -2899,25 +2903,29 @@ const TopControls = styled.div`
2899
2903
  onCancel,
2900
2904
  filename,
2901
2905
  text = "Uploading"
2902
- }) => /* @__PURE__ */ jsx(CardWrapper, { tone: "primary", padding: 4, border: !0, height: "fill", children: /* @__PURE__ */ jsxs(FlexWrapper, { align: "center", justify: "space-between", height: "fill", direction: "row", gap: 2, children: [
2903
- /* @__PURE__ */ jsxs(LeftSection, { children: [
2904
- /* @__PURE__ */ jsx(Flex, { justify: "center", gap: [3, 3, 2, 2], direction: ["column", "column", "row"], children: /* @__PURE__ */ jsx(Text, { size: 1, children: /* @__PURE__ */ jsxs(Inline, { space: 2, children: [
2905
- text,
2906
- /* @__PURE__ */ jsx(CodeWrapper, { size: 1, children: filename || "..." })
2907
- ] }) }) }),
2908
- /* @__PURE__ */ jsx(Card, { marginTop: 3, radius: 5, shadow: 1, children: /* @__PURE__ */ jsx(LinearProgress, { value: progress }) })
2909
- ] }),
2910
- onCancel ? /* @__PURE__ */ jsx(
2911
- Button,
2912
- {
2913
- fontSize: 2,
2914
- text: "Cancel upload",
2915
- mode: "ghost",
2916
- tone: "critical",
2917
- onClick: onCancel
2918
- }
2919
- ) : null
2920
- ] }) }), Player = ({ asset, buttons, readOnly, onChange }) => {
2906
+ }) => {
2907
+ const isCancelDisabled = progress >= 90;
2908
+ return /* @__PURE__ */ jsx(CardWrapper, { tone: "primary", padding: 4, border: !0, height: "fill", children: /* @__PURE__ */ jsxs(FlexWrapper, { align: "center", justify: "space-between", height: "fill", direction: "row", gap: 2, children: [
2909
+ /* @__PURE__ */ jsxs(LeftSection, { children: [
2910
+ /* @__PURE__ */ jsx(Flex, { justify: "center", gap: [3, 3, 2, 2], direction: ["column", "column", "row"], children: /* @__PURE__ */ jsx(Text, { size: 1, children: /* @__PURE__ */ jsxs(Inline, { space: 2, children: [
2911
+ text,
2912
+ /* @__PURE__ */ jsx(CodeWrapper, { size: 1, children: filename || "..." })
2913
+ ] }) }) }),
2914
+ /* @__PURE__ */ jsx(Card, { marginTop: 3, radius: 5, shadow: 1, children: /* @__PURE__ */ jsx(LinearProgress, { value: progress }) })
2915
+ ] }),
2916
+ onCancel ? /* @__PURE__ */ jsx(
2917
+ Button,
2918
+ {
2919
+ fontSize: 2,
2920
+ text: "Cancel upload",
2921
+ mode: "ghost",
2922
+ tone: "critical",
2923
+ onClick: onCancel,
2924
+ disabled: isCancelDisabled
2925
+ }
2926
+ ) : null
2927
+ ] }) });
2928
+ }, Player = ({ asset, buttons, readOnly, onChange }) => {
2921
2929
  const isLoading = useMemo(() => asset?.status === "preparing" ? "Preparing the video" : asset?.status === "waiting_for_upload" ? "Waiting for upload to start" : asset?.status === "waiting" ? "Processing upload" : !(asset?.status === "ready" || typeof asset?.status > "u"), [asset]), isPreparingStaticRenditions = useMemo(() => asset?.data?.static_renditions?.status === "preparing", [asset?.data?.static_renditions?.status]), playRef = useRef(null), muteRef = useRef(null), handleCancelUpload = useCancelUpload(asset, onChange);
2922
2930
  return useEffect(() => {
2923
2931
  const style = document.createElement("style");
@@ -3331,9 +3339,10 @@ function PlaybackPolicy({
3331
3339
  noPolicySelected && /* @__PURE__ */ jsx(PlaybackPolicyWarning, {})
3332
3340
  ] });
3333
3341
  }
3334
- const ENCODING_OPTIONS = [
3335
- { value: "smart", label: "Smart" },
3336
- { value: "baseline", label: "Baseline" }
3342
+ const VIDEO_QUALITY_LEVELS = [
3343
+ { value: "basic", label: "Basic" },
3344
+ { value: "plus", label: "Plus" },
3345
+ { value: "premium", label: "Premium" }
3337
3346
  ], RESOLUTION_TIERS = [
3338
3347
  { value: "1080p", label: "1080p" },
3339
3348
  { value: "1440p", label: "1440p (2k)" },
@@ -3347,7 +3356,7 @@ function UploadConfiguration({
3347
3356
  onClose
3348
3357
  }) {
3349
3358
  const id = useId(), autoTextTracks = useRef(
3350
- pluginConfig.encoding_tier === "smart" && pluginConfig.defaultAutogeneratedSubtitleLang ? [
3359
+ pluginConfig.video_quality === "plus" && pluginConfig.defaultAutogeneratedSubtitleLang ? [
3351
3360
  {
3352
3361
  _id: uuid(),
3353
3362
  type: "autogenerated",
@@ -3358,16 +3367,16 @@ function UploadConfiguration({
3358
3367
  ).current, [config, dispatch] = useReducer(
3359
3368
  (prev, action) => {
3360
3369
  switch (action.action) {
3361
- case "encoding_tier":
3362
- return action.value === "baseline" ? Object.assign({}, prev, {
3363
- encoding_tier: action.value,
3370
+ case "video_quality":
3371
+ return action.value === "basic" ? Object.assign({}, prev, {
3372
+ video_quality: action.value,
3364
3373
  mp4_support: "none",
3365
3374
  max_resolution_tier: "1080p",
3366
3375
  text_tracks: prev.text_tracks?.filter(({ type }) => type !== "autogenerated"),
3367
3376
  public_policy: !0,
3368
3377
  signed_policy: !1
3369
3378
  }) : Object.assign({}, prev, {
3370
- encoding_tier: action.value,
3379
+ video_quality: action.value,
3371
3380
  mp4_support: pluginConfig.mp4_support,
3372
3381
  max_resolution_tier: pluginConfig.max_resolution_tier,
3373
3382
  text_tracks: [...autoTextTracks, ...prev.text_tracks || []]
@@ -3409,11 +3418,11 @@ function UploadConfiguration({
3409
3418
  }
3410
3419
  },
3411
3420
  {
3412
- encoding_tier: pluginConfig.encoding_tier,
3421
+ video_quality: pluginConfig.video_quality,
3413
3422
  max_resolution_tier: pluginConfig.max_resolution_tier,
3414
3423
  mp4_support: pluginConfig.mp4_support,
3415
3424
  signed_policy: secrets.enableSignedUrls && pluginConfig.defaultSigned,
3416
- public_policy: !0,
3425
+ public_policy: pluginConfig.defaultPublic,
3417
3426
  normalize_audio: pluginConfig.normalize_audio,
3418
3427
  text_tracks: autoTextTracks
3419
3428
  }
@@ -3421,7 +3430,7 @@ function UploadConfiguration({
3421
3430
  if (useEffect(() => {
3422
3431
  skipConfig && startUpload(formatUploadConfig(config));
3423
3432
  }, []), skipConfig) return null;
3424
- const maxSupportedResolution = RESOLUTION_TIERS.findIndex(
3433
+ const basicConfig = config.video_quality !== "plus" && config.video_quality !== "premium", maxSupportedResolution = RESOLUTION_TIERS.findIndex(
3425
3434
  (rt) => rt.value === pluginConfig.max_resolution_tier
3426
3435
  );
3427
3436
  return /* @__PURE__ */ jsx(
@@ -3457,9 +3466,9 @@ function UploadConfiguration({
3457
3466
  /* @__PURE__ */ jsx(
3458
3467
  FormField$2,
3459
3468
  {
3460
- title: "Encoding Tier",
3469
+ title: "Video Quality Level",
3461
3470
  description: /* @__PURE__ */ jsxs(Fragment, { children: [
3462
- "The encoding tier informs the cost, quality, and available platform features for the asset.",
3471
+ "The video quality level informs the cost, quality, and available platform features for the asset.",
3463
3472
  " ",
3464
3473
  /* @__PURE__ */ jsx(
3465
3474
  "a",
@@ -3471,16 +3480,16 @@ function UploadConfiguration({
3471
3480
  }
3472
3481
  )
3473
3482
  ] }),
3474
- children: /* @__PURE__ */ jsx(Flex, { gap: 3, children: ENCODING_OPTIONS.map(({ value, label }) => {
3483
+ children: /* @__PURE__ */ jsx(Flex, { gap: 3, children: VIDEO_QUALITY_LEVELS.map(({ value, label }) => {
3475
3484
  const inputId = `${id}--encodingtier-${value}`;
3476
3485
  return /* @__PURE__ */ jsxs(Flex, { align: "center", gap: 2, children: [
3477
3486
  /* @__PURE__ */ jsx(
3478
3487
  Radio,
3479
3488
  {
3480
- checked: config.encoding_tier === value,
3489
+ checked: config.video_quality === value,
3481
3490
  name: "asset-encodingtier",
3482
3491
  onChange: (e) => dispatch({
3483
- action: "encoding_tier",
3492
+ action: "video_quality",
3484
3493
  value: e.currentTarget.value
3485
3494
  }),
3486
3495
  value,
@@ -3492,7 +3501,7 @@ function UploadConfiguration({
3492
3501
  }) })
3493
3502
  }
3494
3503
  ),
3495
- config.encoding_tier === "smart" && maxSupportedResolution > 0 && /* @__PURE__ */ jsx(
3504
+ !basicConfig && maxSupportedResolution > 0 && /* @__PURE__ */ jsx(
3496
3505
  FormField$2,
3497
3506
  {
3498
3507
  title: "Resolution Tier",
@@ -3532,9 +3541,9 @@ function UploadConfiguration({
3532
3541
  }) })
3533
3542
  }
3534
3543
  ),
3535
- config.encoding_tier === "smart" && /* @__PURE__ */ jsx(FormField$2, { title: "Additional Configuration", children: /* @__PURE__ */ jsxs(Stack, { space: 2, children: [
3544
+ !basicConfig && /* @__PURE__ */ jsx(FormField$2, { title: "Additional Configuration", children: /* @__PURE__ */ jsxs(Stack, { space: 2, children: [
3536
3545
  /* @__PURE__ */ jsx(PlaybackPolicy, { id, config, secrets, dispatch }),
3537
- config.encoding_tier === "smart" && /* @__PURE__ */ jsxs(Flex, { align: "center", gap: 2, padding: [0, 2], children: [
3546
+ !basicConfig && /* @__PURE__ */ jsxs(Flex, { align: "center", gap: 2, padding: [0, 2], children: [
3538
3547
  /* @__PURE__ */ jsx(
3539
3548
  Checkbox,
3540
3549
  {
@@ -3553,7 +3562,7 @@ function UploadConfiguration({
3553
3562
  ] })
3554
3563
  ] }) })
3555
3564
  ] }),
3556
- !disableTextTrackConfig && config.encoding_tier === "smart" && /* @__PURE__ */ jsx(
3565
+ !disableTextTrackConfig && !basicConfig && /* @__PURE__ */ jsx(
3557
3566
  TextTracksEditor,
3558
3567
  {
3559
3568
  tracks: config.text_tracks,
@@ -3564,7 +3573,7 @@ function UploadConfiguration({
3564
3573
  /* @__PURE__ */ jsx(Box, { marginTop: 4, children: /* @__PURE__ */ jsx(
3565
3574
  Button,
3566
3575
  {
3567
- disabled: config.encoding_tier === "smart" && !config.public_policy && !config.signed_policy,
3576
+ disabled: !basicConfig && !config.public_policy && !config.signed_policy,
3568
3577
  icon: UploadIcon,
3569
3578
  text: "Upload",
3570
3579
  tone: "positive",
@@ -3605,7 +3614,7 @@ function formatUploadConfig(config) {
3605
3614
  mp4_support: config.mp4_support,
3606
3615
  playback_policy: setPlaybackPolicy(config),
3607
3616
  max_resolution_tier: config.max_resolution_tier,
3608
- encoding_tier: config.encoding_tier,
3617
+ video_quality: config.video_quality,
3609
3618
  normalize_audio: config.normalize_audio
3610
3619
  };
3611
3620
  }
@@ -3783,7 +3792,7 @@ function Uploader(props) {
3783
3792
  handleClick: (event) => events$.next(event)
3784
3793
  };
3785
3794
  })()
3786
- ).current, uploadRef = useRef(null), [state, dispatch] = useReducer(
3795
+ ).current, uploadRef = useRef(null), uploadingDocumentId = useRef(null), [state, dispatch] = useReducer(
3787
3796
  (prev, action) => {
3788
3797
  switch (action.action) {
3789
3798
  case "stageUpload":
@@ -3809,9 +3818,9 @@ function Uploader(props) {
3809
3818
  });
3810
3819
  case "reset":
3811
3820
  case "complete":
3812
- return uploadRef.current?.unsubscribe(), uploadRef.current = null, INITIAL_STATE;
3821
+ return uploadRef.current?.unsubscribe(), uploadRef.current = null, uploadingDocumentId.current = null, INITIAL_STATE;
3813
3822
  case "error":
3814
- return uploadRef.current?.unsubscribe(), uploadRef.current = null, Object.assign({}, INITIAL_STATE, { error: action.error });
3823
+ return uploadRef.current?.unsubscribe(), uploadRef.current = null, uploadingDocumentId.current = null, Object.assign({}, INITIAL_STATE, { error: action.error });
3815
3824
  default:
3816
3825
  return prev;
3817
3826
  }
@@ -3822,9 +3831,21 @@ function Uploader(props) {
3822
3831
  error: null
3823
3832
  }
3824
3833
  );
3825
- useEffect(() => () => {
3826
- uploadRef.current && !uploadRef.current.closed && uploadRef.current.unsubscribe();
3827
- }, []);
3834
+ useEffect(() => {
3835
+ const cleanup = () => {
3836
+ if (uploadRef.current && !uploadRef.current.closed && uploadRef.current.unsubscribe(), uploadingDocumentId.current && props.asset?._id !== uploadingDocumentId.current) {
3837
+ const docId = uploadingDocumentId.current;
3838
+ uploadingDocumentId.current = null, props.client.delete(docId).catch((err) => {
3839
+ console.warn("Failed to cleanup orphaned upload document:", err);
3840
+ });
3841
+ }
3842
+ }, handleBeforeUnload = () => {
3843
+ cleanup();
3844
+ };
3845
+ return window.addEventListener("beforeunload", handleBeforeUnload), window.addEventListener("pagehide", handleBeforeUnload), () => {
3846
+ window.removeEventListener("beforeunload", handleBeforeUnload), window.removeEventListener("pagehide", handleBeforeUnload), cleanup();
3847
+ };
3848
+ }, [props.client, props.asset?._id]);
3828
3849
  const startUpload = (settings) => {
3829
3850
  const { stagedUpload } = state;
3830
3851
  if (!stagedUpload || uploadRef.current) return;
@@ -3847,7 +3868,7 @@ function Uploader(props) {
3847
3868
  takeUntil(
3848
3869
  cancelUploadButton.observable.pipe(
3849
3870
  tap(() => {
3850
- state.uploadStatus?.uuid && props.client.delete(state.uploadStatus.uuid);
3871
+ uploadingDocumentId.current && (props.client.delete(uploadingDocumentId.current), uploadingDocumentId.current = null);
3851
3872
  })
3852
3873
  )
3853
3874
  )
@@ -3858,6 +3879,8 @@ function Uploader(props) {
3858
3879
  next: (event) => {
3859
3880
  switch (event.type) {
3860
3881
  case "uuid":
3882
+ uploadingDocumentId.current = event.uuid, dispatch({ action: "progressInfo", ...event });
3883
+ break;
3861
3884
  case "file":
3862
3885
  case "url":
3863
3886
  dispatch({ action: "progressInfo", ...event });
@@ -3866,7 +3889,7 @@ function Uploader(props) {
3866
3889
  dispatch({ action: "progress", percent: event.percent });
3867
3890
  break;
3868
3891
  case "success":
3869
- dispatch({ action: "progress", percent: 100 }), props.onChange(
3892
+ dispatch({ action: "progress", percent: 100 }), uploadingDocumentId.current = null, props.onChange(
3870
3893
  PatchEvent.from([
3871
3894
  setIfMissing({ asset: {} }),
3872
3895
  set({ _type: "reference", _weak: !0, _ref: event.asset._id }, ["asset"])
@@ -4146,6 +4169,10 @@ const muxVideoSchema = {
4146
4169
  type: "string",
4147
4170
  name: "encoding_tier"
4148
4171
  },
4172
+ {
4173
+ type: "string",
4174
+ name: "video_quality"
4175
+ },
4149
4176
  {
4150
4177
  type: "string",
4151
4178
  name: "master_access"
@@ -4224,13 +4251,18 @@ const muxVideoSchema = {
4224
4251
  muxVideoAsset
4225
4252
  ], defaultConfig = {
4226
4253
  mp4_support: "none",
4227
- encoding_tier: "smart",
4254
+ video_quality: "plus",
4228
4255
  max_resolution_tier: "1080p",
4229
4256
  normalize_audio: !1,
4257
+ defaultPublic: !0,
4230
4258
  defaultSigned: !1,
4231
4259
  tool: DEFAULT_TOOL_CONFIG,
4232
4260
  allowedRolesForConfiguration: []
4233
4261
  }, muxInput = definePlugin((userConfig) => {
4262
+ if (typeof userConfig == "object" && "encoding_tier" in userConfig) {
4263
+ const deprecated_encoding_tier = userConfig.encoding_tier;
4264
+ userConfig.video_quality || (deprecated_encoding_tier === "baseline" && (userConfig.video_quality = "basic"), deprecated_encoding_tier === "smart" && (userConfig.video_quality = "plus"));
4265
+ }
4234
4266
  const config = { ...defaultConfig, ...userConfig || {} };
4235
4267
  return {
4236
4268
  name: "mux-input",