sanity-plugin-mux-input 2.7.0 → 2.8.1

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
@@ -1,4 +1,4 @@
1
- import { useClient as useClient$1, createHookFromObservableFactory, useDocumentStore, collate, useDocumentValues, truncateString, useFormattedDuration, SanityDefaultPreview, useTimeAgo, TextWithTone, isRecord, getPreviewStateObservable, getPreviewValueWithFallback, DocumentPreviewPresence, useDocumentPreviewStore, useSchema, useDocumentPresence, PreviewCard, isReference, useProjectId, useDataset, PatchEvent, unset, setIfMissing, set, LinearProgress, FormField as FormField$2, definePlugin } from "sanity";
1
+ import { useClient as useClient$1, createHookFromObservableFactory, useDocumentStore, collate, useDocumentValues, truncateString, useFormattedDuration, SanityDefaultPreview, useTimeAgo, TextWithTone, isRecord, getPreviewStateObservable, getPreviewValueWithFallback, DocumentPreviewPresence, useDocumentPreviewStore, useSchema, useDocumentPresence, PreviewCard, isReference, useProjectId, useDataset, useCurrentUser, PatchEvent, unset, setIfMissing, set, LinearProgress, FormField as FormField$2, definePlugin } from "sanity";
2
2
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
3
3
  import { ErrorOutlineIcon, RetryIcon, CheckmarkCircleIcon, RetrieveIcon, SortIcon, WarningOutlineIcon, EditIcon, PublishIcon, DocumentIcon, TrashIcon, RevertIcon, SearchIcon, ClockIcon, CropIcon, CalendarIcon, TagIcon, CheckmarkIcon, LockIcon, PlayIcon, PlugIcon, EllipsisHorizontalIcon, UploadIcon, ImageIcon, ResetIcon, TranslateIcon, WarningFilledIcon, DocumentVideoIcon } from "@sanity/icons";
4
4
  import { Card, Box, Spinner, Stack, Text, Checkbox, Button, Dialog, Flex, Heading, Code, MenuButton, Menu, MenuItem, TextInput, Tooltip, Inline, useToast, TabList, Tab, TabPanel, Label as Label$1, Grid, useTheme_v2, useClickOutsideEvent, Popover, MenuDivider, Autocomplete, Radio, rem } from "@sanity/ui";
@@ -14,7 +14,6 @@ import { defer, timer, of, Observable, concat, throwError, from, Subject } from
14
14
  import { expand, concatMap, tap, switchMap, mergeMap, catchError, mergeMapTo, takeUntil } from "rxjs/operators";
15
15
  import { suspend, clear, preload } from "suspend-react";
16
16
  import MuxPlayer from "@mux/mux-player-react";
17
- import { usePaneRouter } from "sanity/desk";
18
17
  import { IntentLink } from "sanity/router";
19
18
  import isNumber from "lodash/isNumber.js";
20
19
  import isString from "lodash/isString.js";
@@ -916,7 +915,7 @@ function VideoPlayer({
916
915
  crossOrigin: "anonymous",
917
916
  metadata: {
918
917
  player_name: "Sanity Admin Dashboard",
919
- player_version: "2.7.0",
918
+ player_version: "2.8.1",
920
919
  page_type: "Preview Player"
921
920
  },
922
921
  audio: isAudio,
@@ -1067,18 +1066,7 @@ function PaneItemPreview(props) {
1067
1066
  function getIconWithFallback(icon, schemaType, defaultIcon) {
1068
1067
  return icon === !1 ? !1 : icon || schemaType && schemaType.icon || defaultIcon || !1;
1069
1068
  }
1070
- function DocumentPreviewInInput(props) {
1071
- const { ChildLink } = usePaneRouter();
1072
- return (linkProps) => /* @__PURE__ */ jsx(
1073
- ChildLink,
1074
- {
1075
- childId: props.documentPair.id,
1076
- childParameters: { type: props.documentPair.type },
1077
- children: linkProps.children
1078
- }
1079
- );
1080
- }
1081
- function DocumentPreviewInRool(props) {
1069
+ function DocumentPreviewLink(props) {
1082
1070
  return (linkProps) => /* @__PURE__ */ jsx(IntentLink, { intent: "edit", params: { id: props.documentPair.id }, children: linkProps.children });
1083
1071
  }
1084
1072
  function DocumentPreview(props) {
@@ -1097,7 +1085,7 @@ function DocumentPreview(props) {
1097
1085
  PreviewCard,
1098
1086
  {
1099
1087
  __unstable_focusRing: !0,
1100
- as: props.placement === "input" ? DocumentPreviewInInput(props) : DocumentPreviewInRool(props),
1088
+ as: DocumentPreviewLink(props),
1101
1089
  "data-as": "a",
1102
1090
  "data-ui": "PaneItem",
1103
1091
  padding: 2,
@@ -1134,14 +1122,7 @@ const Container = styled(Box)`
1134
1122
  radius: 2,
1135
1123
  shadow: 1,
1136
1124
  style: { overflow: "hidden" },
1137
- children: /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(
1138
- DocumentPreview,
1139
- {
1140
- documentPair,
1141
- schemaType,
1142
- placement: props.placement
1143
- }
1144
- ) })
1125
+ children: /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(DocumentPreview, { documentPair, schemaType }) })
1145
1126
  },
1146
1127
  documentPair.id
1147
1128
  );
@@ -1152,7 +1133,6 @@ function DeleteDialog({
1152
1133
  references,
1153
1134
  referencesLoading,
1154
1135
  cancelDelete,
1155
- placement,
1156
1136
  succeededDeleting
1157
1137
  }) {
1158
1138
  const client = useClient(), [state, setState] = useState("checkingReferences"), [deleteOnMux, setDeleteOnMux] = useState(!0), toast = useToast();
@@ -1205,14 +1185,7 @@ function DeleteDialog({
1205
1185
  " ",
1206
1186
  "pointing to this video. Remove their references to this file or delete them before proceeding."
1207
1187
  ] }),
1208
- /* @__PURE__ */ jsx(
1209
- VideoReferences,
1210
- {
1211
- references,
1212
- isLoaded: !referencesLoading,
1213
- placement
1214
- }
1215
- )
1188
+ /* @__PURE__ */ jsx(VideoReferences, { references, isLoaded: !referencesLoading })
1216
1189
  ] }),
1217
1190
  state === "confirm" && /* @__PURE__ */ jsxs(Fragment, { children: [
1218
1191
  /* @__PURE__ */ jsx(Heading, { size: 2, children: "Are you sure you want to delete this video?" }),
@@ -1403,7 +1376,6 @@ const AssetInput = (props) => /* @__PURE__ */ jsx(FormField$1, { title: props.la
1403
1376
  {
1404
1377
  asset: props.asset,
1405
1378
  cancelDelete: () => setState("idle"),
1406
- placement: props.placement,
1407
1379
  referencesLoading,
1408
1380
  references,
1409
1381
  succeededDeleting: () => {
@@ -1585,14 +1557,7 @@ ${displayInfo.id}`, icon: TagIcon, size: 2 }),
1585
1557
  "aria-labelledby": "references-tab",
1586
1558
  id: "references-panel",
1587
1559
  hidden: tab !== "references",
1588
- children: /* @__PURE__ */ jsx(
1589
- VideoReferences,
1590
- {
1591
- references,
1592
- isLoaded: !referencesLoading,
1593
- placement: props.placement
1594
- }
1595
- )
1560
+ children: /* @__PURE__ */ jsx(VideoReferences, { references, isLoaded: !referencesLoading })
1596
1561
  }
1597
1562
  )
1598
1563
  ] })
@@ -1820,7 +1785,7 @@ function VideosBrowser({ onSelect }) {
1820
1785
  const { assets, isLoading, searchQuery, setSearchQuery, setSort, sort } = useAssets(), [editedAsset, setEditedAsset] = useState(null), freshEditedAsset = useMemo(
1821
1786
  () => assets.find((a2) => a2._id === editedAsset?._id) || editedAsset,
1822
1787
  [editedAsset, assets]
1823
- ), placement = onSelect ? "input" : "tool";
1788
+ );
1824
1789
  return /* @__PURE__ */ jsxs(Fragment, { children: [
1825
1790
  /* @__PURE__ */ jsxs(Stack, { padding: 4, space: 4, style: { minHeight: "50vh" }, children: [
1826
1791
  /* @__PURE__ */ jsxs(Flex, { justify: "space-between", align: "center", children: [
@@ -1836,7 +1801,7 @@ function VideosBrowser({ onSelect }) {
1836
1801
  ),
1837
1802
  /* @__PURE__ */ jsx(SelectSortOptions, { setSort, sort })
1838
1803
  ] }),
1839
- placement === "tool" && /* @__PURE__ */ jsx(ImportVideosFromMux, {})
1804
+ (onSelect ? "input" : "tool") == "tool" && /* @__PURE__ */ jsx(ImportVideosFromMux, {})
1840
1805
  ] }),
1841
1806
  /* @__PURE__ */ jsxs(Stack, { space: 3, children: [
1842
1807
  assets?.length > 0 && /* @__PURE__ */ jsxs(Label$1, { muted: !0, children: [
@@ -1868,14 +1833,7 @@ function VideosBrowser({ onSelect }) {
1868
1833
  isLoading && /* @__PURE__ */ jsx(SpinnerBox, {}),
1869
1834
  !isLoading && assets.length === 0 && /* @__PURE__ */ jsx(Card, { marginY: 4, paddingX: 4, paddingY: 6, border: !0, radius: 2, tone: "transparent", children: /* @__PURE__ */ jsx(Text, { align: "center", muted: !0, size: 3, children: searchQuery ? `No videos found for "${searchQuery}"` : "No videos in this dataset" }) })
1870
1835
  ] }),
1871
- freshEditedAsset && /* @__PURE__ */ jsx(
1872
- VideoDetails,
1873
- {
1874
- closeDialog: () => setEditedAsset(null),
1875
- asset: freshEditedAsset,
1876
- placement
1877
- }
1878
- )
1836
+ freshEditedAsset && /* @__PURE__ */ jsx(VideoDetails, { closeDialog: () => setEditedAsset(null), asset: freshEditedAsset })
1879
1837
  ] });
1880
1838
  }
1881
1839
  const StudioTool = () => /* @__PURE__ */ jsx(VideosBrowser, {}), DEFAULT_TOOL_CONFIG = {
@@ -2349,9 +2307,12 @@ const InputFallback = () => /* @__PURE__ */ jsx("div", { style: { padding: 1 },
2349
2307
  /* @__PURE__ */ jsx(Box, { marginTop: 3, children: /* @__PURE__ */ jsx(Text, { align: "center", muted: !0, size: 1, children: "Loading\u2026" }) })
2350
2308
  ] })
2351
2309
  }
2352
- ) });
2310
+ ) }), useAccessControl = (config) => {
2311
+ const user = useCurrentUser();
2312
+ return { hasConfigAccess: !config?.allowedRolesForConfiguration || user?.roles?.some((role) => config.allowedRolesForConfiguration.includes(role.name)) };
2313
+ };
2353
2314
  function Onboard(props) {
2354
- const { setDialogState } = props, handleOpen = useCallback(() => setDialogState("secrets"), [setDialogState]);
2315
+ const { setDialogState } = props, handleOpen = useCallback(() => setDialogState("secrets"), [setDialogState]), { hasConfigAccess } = useAccessControl(props.config);
2355
2316
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx("div", { style: { padding: 2 }, children: /* @__PURE__ */ jsx(
2356
2317
  Card,
2357
2318
  {
@@ -2368,7 +2329,7 @@ function Onboard(props) {
2368
2329
  children: /* @__PURE__ */ jsx(Flex, { justify: "flex-start", align: "center", children: /* @__PURE__ */ jsxs(Grid, { columns: 1, gap: [2, 3, 4, 4], children: [
2369
2330
  /* @__PURE__ */ jsx(Inline, { paddingY: 1, children: /* @__PURE__ */ jsx("div", { style: { height: "32px" }, children: /* @__PURE__ */ jsx(MuxLogo, {}) }) }),
2370
2331
  /* @__PURE__ */ jsx(Inline, { paddingY: 1, children: /* @__PURE__ */ jsx(Heading, { size: [0, 1, 2, 2], children: "Upload and preview videos directly from your studio." }) }),
2371
- /* @__PURE__ */ jsx(Inline, { paddingY: 1, children: /* @__PURE__ */ jsx(Button, { mode: "ghost", icon: PlugIcon, text: "Configure API", onClick: handleOpen }) })
2332
+ /* @__PURE__ */ jsx(Inline, { paddingY: 1, children: hasConfigAccess ? /* @__PURE__ */ jsx(Button, { mode: "ghost", icon: PlugIcon, text: "Configure API", onClick: handleOpen }) : /* @__PURE__ */ jsx(Card, { padding: [3, 3, 3], radius: 2, shadow: 1, tone: "critical", children: /* @__PURE__ */ jsx(Text, { children: "You do not have access to configure the Mux API. Please contact your administrator." }) }) })
2372
2333
  ] }) })
2373
2334
  }
2374
2335
  ) }) });
@@ -2851,7 +2812,7 @@ const FileButton = styled(MenuItem)(({ theme }) => {
2851
2812
  color: white;
2852
2813
  `, isVideoAsset = (asset) => asset._type === "mux.videoAsset";
2853
2814
  function PlayerActionsMenu(props) {
2854
- const { asset, readOnly, dialogState, setDialogState, onChange, onSelect } = props, [open, setOpen] = useState(!1), [menuElement, setMenuRef] = useState(null), isSigned = useMemo(() => getPlaybackPolicy(asset) === "signed", [asset]), onReset = useCallback(() => onChange(PatchEvent.from(unset([]))), [onChange]);
2815
+ const { asset, readOnly, dialogState, setDialogState, onChange, onSelect } = props, [open, setOpen] = useState(!1), [menuElement, setMenuRef] = useState(null), isSigned = useMemo(() => getPlaybackPolicy(asset) === "signed", [asset]), { hasConfigAccess } = useAccessControl(props.config), onReset = useCallback(() => onChange(PatchEvent.from(unset([]))), [onChange]);
2855
2816
  return useEffect(() => {
2856
2817
  open && dialogState && setOpen(!1);
2857
2818
  }, [dialogState, open]), useClickOutsideEvent(
@@ -2902,15 +2863,17 @@ function PlayerActionsMenu(props) {
2902
2863
  }
2903
2864
  ),
2904
2865
  /* @__PURE__ */ jsx(MenuDivider, {}),
2905
- /* @__PURE__ */ jsx(
2906
- MenuItem,
2907
- {
2908
- icon: PlugIcon,
2909
- text: "Configure API",
2910
- onClick: () => setDialogState("secrets")
2911
- }
2912
- ),
2913
- /* @__PURE__ */ jsx(MenuDivider, {}),
2866
+ hasConfigAccess && /* @__PURE__ */ jsxs(Fragment, { children: [
2867
+ /* @__PURE__ */ jsx(
2868
+ MenuItem,
2869
+ {
2870
+ icon: PlugIcon,
2871
+ text: "Configure API",
2872
+ onClick: () => setDialogState("secrets")
2873
+ }
2874
+ ),
2875
+ /* @__PURE__ */ jsx(MenuDivider, {})
2876
+ ] }),
2914
2877
  /* @__PURE__ */ jsx(
2915
2878
  MenuItem,
2916
2879
  {
@@ -3517,7 +3480,7 @@ const ctrlKey = 17, cmdKey = 91, UploadCardWithFocusRing = withFocusRing(Card),
3517
3480
  ] });
3518
3481
  };
3519
3482
  function UploadPlaceholder(props) {
3520
- const { setDialogState, readOnly, onSelect, hovering, needsSetup } = props, handleBrowse = useCallback(() => setDialogState("select-video"), [setDialogState]), handleConfigureApi = useCallback(() => setDialogState("secrets"), [setDialogState]);
3483
+ const { setDialogState, readOnly, onSelect, hovering, needsSetup } = props, handleBrowse = useCallback(() => setDialogState("select-video"), [setDialogState]), handleConfigureApi = useCallback(() => setDialogState("secrets"), [setDialogState]), { hasConfigAccess } = useAccessControl(props.config);
3521
3484
  return /* @__PURE__ */ jsx(
3522
3485
  Card,
3523
3486
  {
@@ -3554,7 +3517,7 @@ function UploadPlaceholder(props) {
3554
3517
  }
3555
3518
  ),
3556
3519
  /* @__PURE__ */ jsx(Button, { mode: "bleed", icon: SearchIcon, text: "Select", onClick: handleBrowse }),
3557
- /* @__PURE__ */ jsx(
3520
+ hasConfigAccess && /* @__PURE__ */ jsx(
3558
3521
  Button,
3559
3522
  {
3560
3523
  padding: 3,
@@ -3775,7 +3738,8 @@ function Uploader(props) {
3775
3738
  setDialogState: props.setDialogState,
3776
3739
  onChange: props.onChange,
3777
3740
  onSelect: handleUpload,
3778
- readOnly: props.readOnly
3741
+ readOnly: props.readOnly,
3742
+ config: props.config
3779
3743
  }
3780
3744
  )
3781
3745
  }
@@ -3788,7 +3752,8 @@ function Uploader(props) {
3788
3752
  onSelect: handleUpload,
3789
3753
  readOnly: !!props.readOnly,
3790
3754
  setDialogState: props.setDialogState,
3791
- needsSetup: props.needsSetup
3755
+ needsSetup: props.needsSetup,
3756
+ config: props.config
3792
3757
  }
3793
3758
  )
3794
3759
  }
@@ -3804,12 +3769,12 @@ function Uploader(props) {
3804
3769
  ] });
3805
3770
  }
3806
3771
  const Input = (props) => {
3807
- const client = useClient(), secretDocumentValues = useSecretsDocumentValues(), assetDocumentValues = useAssetDocumentValues(props.value?.asset), poll = useMuxPolling(props.readOnly ? void 0 : assetDocumentValues?.value || void 0), [dialogState, setDialogState] = useDialogState(), error = secretDocumentValues.error || assetDocumentValues.error || poll.error;
3772
+ const client = useClient(), secretDocumentValues = useSecretsDocumentValues(), assetDocumentValues = useAssetDocumentValues(props.value?.asset), poll = useMuxPolling(props.readOnly ? void 0 : assetDocumentValues?.value || void 0), [dialogState, setDialogState] = useDialogState(), { hasConfigAccess } = useAccessControl(props.config), error = secretDocumentValues.error || assetDocumentValues.error || poll.error;
3808
3773
  if (error)
3809
3774
  throw error;
3810
3775
  const isLoading = secretDocumentValues.isLoading || assetDocumentValues.isLoading;
3811
3776
  return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsx(ErrorBoundaryCard$1, { schemaType: props.schemaType, children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(InputFallback, {}), children: isLoading ? /* @__PURE__ */ jsx(InputFallback, {}) : /* @__PURE__ */ jsxs(Fragment, { children: [
3812
- secretDocumentValues.value.needsSetup && !assetDocumentValues.value ? /* @__PURE__ */ jsx(Onboard, { setDialogState }) : /* @__PURE__ */ jsx(
3777
+ secretDocumentValues.value.needsSetup && !assetDocumentValues.value ? /* @__PURE__ */ jsx(Onboard, { setDialogState, config: props.config }) : /* @__PURE__ */ jsx(
3813
3778
  Uploader,
3814
3779
  {
3815
3780
  ...props,
@@ -3823,7 +3788,7 @@ const Input = (props) => {
3823
3788
  needsSetup: secretDocumentValues.value.needsSetup
3824
3789
  }
3825
3790
  ),
3826
- dialogState === "secrets" && /* @__PURE__ */ jsx(
3791
+ dialogState === "secrets" && hasConfigAccess && /* @__PURE__ */ jsx(
3827
3792
  ConfigureApi$1,
3828
3793
  {
3829
3794
  setDialogState,
@@ -3989,7 +3954,7 @@ const muxVideoSchema = {
3989
3954
  ]
3990
3955
  }, muxVideoAsset = {
3991
3956
  name: "mux.videoAsset",
3992
- type: "object",
3957
+ type: "document",
3993
3958
  title: "Video asset",
3994
3959
  fields: [
3995
3960
  {
@@ -4030,7 +3995,8 @@ const muxVideoSchema = {
4030
3995
  max_resolution_tier: "1080p",
4031
3996
  normalize_audio: !1,
4032
3997
  defaultSigned: !1,
4033
- tool: DEFAULT_TOOL_CONFIG
3998
+ tool: DEFAULT_TOOL_CONFIG,
3999
+ allowedRolesForConfiguration: []
4034
4000
  }, muxInput = definePlugin((userConfig) => {
4035
4001
  const config = { ...defaultConfig, ...userConfig || {} };
4036
4002
  return {