sanity-plugin-mux-input 2.12.0 → 2.13.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/LICENSE +1 -1
- package/README.md +133 -0
- package/dist/index.d.mts +41 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +188 -72
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +188 -72
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/_exports/index.ts +1 -0
- package/src/components/FileInputButton.tsx +2 -2
- package/src/components/Player.tsx +4 -3
- package/src/components/PlayerActionsMenu.tsx +4 -3
- package/src/components/UploadConfiguration.tsx +181 -4
- package/src/components/UploadPlaceholder.tsx +14 -6
- package/src/components/Uploader.tsx +54 -6
- package/src/components/VideoInBrowser.tsx +2 -7
- package/src/components/VideoPlayer.tsx +33 -6
- package/src/components/icons/Audio.tsx +13 -0
- package/src/util/types.ts +45 -0
- package/src/components/FileInputArea.tsx +0 -93
package/dist/index.js
CHANGED
|
@@ -1483,10 +1483,21 @@ function EditThumbnailDialog({ asset, currentTime = 0 }) {
|
|
|
1483
1483
|
}
|
|
1484
1484
|
);
|
|
1485
1485
|
}
|
|
1486
|
+
function AudioIcon(props) {
|
|
1487
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "1em", height: "1em", viewBox: "0 0 24 24", ...props, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1488
|
+
"path",
|
|
1489
|
+
{
|
|
1490
|
+
fill: "currentColor",
|
|
1491
|
+
style: { opacity: "0.65" },
|
|
1492
|
+
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"
|
|
1493
|
+
}
|
|
1494
|
+
) });
|
|
1495
|
+
}
|
|
1486
1496
|
function VideoPlayer({
|
|
1487
1497
|
asset,
|
|
1488
1498
|
thumbnailWidth = 250,
|
|
1489
1499
|
children,
|
|
1500
|
+
hlsConfig,
|
|
1490
1501
|
...props
|
|
1491
1502
|
}) {
|
|
1492
1503
|
const client = useClient(), { dialogState } = useDialogStateContext(), isAudio = assetIsAudio(asset), muxPlayer = React.useRef(null), {
|
|
@@ -1512,52 +1523,79 @@ function VideoPlayer({
|
|
|
1512
1523
|
// Make it wider when forcing aspect ratio to balance with videos' rendering height (audio players overflow a bit)
|
|
1513
1524
|
props.forceAspectRatio * 1.2
|
|
1514
1525
|
) : AUDIO_ASPECT_RATIO), /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1515
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1526
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1527
|
+
ui.Card,
|
|
1528
|
+
{
|
|
1529
|
+
tone: "transparent",
|
|
1530
|
+
style: {
|
|
1531
|
+
aspectRatio,
|
|
1532
|
+
position: "relative",
|
|
1533
|
+
...isAudio && { display: "flex", alignItems: "flex-end" }
|
|
1534
|
+
},
|
|
1535
|
+
children: [
|
|
1536
|
+
videoSrc && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1537
|
+
isAudio && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1538
|
+
AudioIcon,
|
|
1539
|
+
{
|
|
1540
|
+
style: {
|
|
1541
|
+
padding: "0.5em",
|
|
1542
|
+
width: "2.2em",
|
|
1543
|
+
height: "2.2em",
|
|
1544
|
+
position: "absolute",
|
|
1545
|
+
top: 0,
|
|
1546
|
+
left: 0,
|
|
1547
|
+
zIndex: 1
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
),
|
|
1551
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1552
|
+
MuxPlayer__default.default,
|
|
1553
|
+
{
|
|
1554
|
+
poster: isAudio ? void 0 : thumbnailSrc,
|
|
1555
|
+
ref: muxPlayer,
|
|
1556
|
+
...props,
|
|
1557
|
+
playsInline: !0,
|
|
1558
|
+
playbackId: asset.playbackId,
|
|
1559
|
+
tokens: signedToken ? { playback: signedToken, thumbnail: signedToken, storyboard: signedToken } : void 0,
|
|
1560
|
+
preload: "metadata",
|
|
1561
|
+
crossOrigin: "anonymous",
|
|
1562
|
+
metadata: {
|
|
1563
|
+
player_name: "Sanity Admin Dashboard",
|
|
1564
|
+
player_version: "2.13.0",
|
|
1565
|
+
page_type: "Preview Player"
|
|
1566
|
+
},
|
|
1567
|
+
audio: isAudio,
|
|
1568
|
+
_hlsConfig: hlsConfig,
|
|
1569
|
+
style: {
|
|
1570
|
+
...!isAudio && { height: "100%" },
|
|
1571
|
+
width: "100%",
|
|
1572
|
+
display: "block",
|
|
1573
|
+
objectFit: "contain",
|
|
1574
|
+
...isAudio && { alignSelf: "end" }
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
),
|
|
1578
|
+
children
|
|
1579
|
+
] }),
|
|
1580
|
+
error ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1581
|
+
"div",
|
|
1582
|
+
{
|
|
1583
|
+
style: {
|
|
1584
|
+
position: "absolute",
|
|
1585
|
+
top: "50%",
|
|
1586
|
+
left: "50%",
|
|
1587
|
+
transform: "translate(-50%, -50%)"
|
|
1588
|
+
},
|
|
1589
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { muted: !0, children: [
|
|
1590
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ErrorOutlineIcon, { style: { marginRight: "0.15em" } }),
|
|
1591
|
+
typeof error == "object" && "message" in error && typeof error.message == "string" ? error.message : "Error loading video"
|
|
1592
|
+
] })
|
|
1539
1593
|
}
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
"div",
|
|
1546
|
-
{
|
|
1547
|
-
style: {
|
|
1548
|
-
position: "absolute",
|
|
1549
|
-
top: "50%",
|
|
1550
|
-
left: "50%",
|
|
1551
|
-
transform: "translate(-50%, -50%)"
|
|
1552
|
-
},
|
|
1553
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { muted: !0, children: [
|
|
1554
|
-
/* @__PURE__ */ jsxRuntime.jsx(icons.ErrorOutlineIcon, { style: { marginRight: "0.15em" } }),
|
|
1555
|
-
typeof error == "object" && "message" in error && typeof error.message == "string" ? error.message : "Error loading video"
|
|
1556
|
-
] })
|
|
1557
|
-
}
|
|
1558
|
-
) : null,
|
|
1559
|
-
children
|
|
1560
|
-
] }),
|
|
1594
|
+
) : null,
|
|
1595
|
+
children
|
|
1596
|
+
]
|
|
1597
|
+
}
|
|
1598
|
+
),
|
|
1561
1599
|
dialogState === "edit-thumbnail" && /* @__PURE__ */ jsxRuntime.jsx(EditThumbnailDialog, { asset, currentTime: muxPlayer?.current?.currentTime })
|
|
1562
1600
|
] });
|
|
1563
1601
|
}
|
|
@@ -2300,14 +2338,7 @@ function VideoInBrowser({
|
|
|
2300
2338
|
alignItems: "center",
|
|
2301
2339
|
justifyContent: "center"
|
|
2302
2340
|
},
|
|
2303
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2304
|
-
"path",
|
|
2305
|
-
{
|
|
2306
|
-
fill: "currentColor",
|
|
2307
|
-
style: { opacity: "0.65" },
|
|
2308
|
-
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"
|
|
2309
|
-
}
|
|
2310
|
-
) })
|
|
2341
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(AudioIcon, { width: "3em", height: "3em" })
|
|
2311
2342
|
}
|
|
2312
2343
|
) : /* @__PURE__ */ jsxRuntime.jsx(VideoThumbnail, { asset })
|
|
2313
2344
|
] }),
|
|
@@ -2932,7 +2963,7 @@ const TopControls = styledComponents.styled.div`
|
|
|
2932
2963
|
}
|
|
2933
2964
|
) : null
|
|
2934
2965
|
] }) });
|
|
2935
|
-
}, Player = ({ asset, buttons, readOnly, onChange }) => {
|
|
2966
|
+
}, Player = ({ asset, buttons, readOnly, onChange, config }) => {
|
|
2936
2967
|
const isLoading = React.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 = React.useMemo(() => {
|
|
2937
2968
|
if (asset?.data?.static_renditions?.status && asset?.data?.static_renditions?.status !== "disabled")
|
|
2938
2969
|
return !1;
|
|
@@ -2953,7 +2984,7 @@ const TopControls = styledComponents.styled.div`
|
|
|
2953
2984
|
text: isLoading !== !0 && isLoading || "Waiting for Mux to complete the upload",
|
|
2954
2985
|
onCancel: readOnly ? void 0 : () => handleCancelUpload()
|
|
2955
2986
|
}
|
|
2956
|
-
) : /* @__PURE__ */ jsxRuntime.jsxs(VideoPlayer, { asset, children: [
|
|
2987
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(VideoPlayer, { asset, hlsConfig: config?.hlsConfig, children: [
|
|
2957
2988
|
buttons && /* @__PURE__ */ jsxRuntime.jsx(TopControls, { slot: "top-chrome", children: buttons }),
|
|
2958
2989
|
isPreparingStaticRenditions && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2959
2990
|
ui.Card,
|
|
@@ -3065,7 +3096,7 @@ const FileButton = styledComponents.styled(ui.MenuItem)(({ theme }) => {
|
|
|
3065
3096
|
color: white;
|
|
3066
3097
|
`, isVideoAsset = (asset) => asset._type === "mux.videoAsset";
|
|
3067
3098
|
function PlayerActionsMenu(props) {
|
|
3068
|
-
const { asset, readOnly, dialogState, setDialogState, onChange, onSelect } = props, [open, setOpen] = React.useState(!1), [menuElement, setMenuRef] = React.useState(null), isSigned = React.useMemo(() => getPlaybackPolicy(asset) === "signed", [asset]), { hasConfigAccess } = useAccessControl(props.config), onReset = React.useCallback(() => onChange(sanity.PatchEvent.from(sanity.unset([]))), [onChange]);
|
|
3099
|
+
const { asset, readOnly, dialogState, setDialogState, onChange, onSelect, accept } = props, [open, setOpen] = React.useState(!1), [menuElement, setMenuRef] = React.useState(null), isSigned = React.useMemo(() => getPlaybackPolicy(asset) === "signed", [asset]), { hasConfigAccess } = useAccessControl(props.config), onReset = React.useCallback(() => onChange(sanity.PatchEvent.from(sanity.unset([]))), [onChange]);
|
|
3069
3100
|
return React.useEffect(() => {
|
|
3070
3101
|
open && dialogState && setOpen(!1);
|
|
3071
3102
|
}, [dialogState, open]), ui.useClickOutsideEvent(
|
|
@@ -3091,7 +3122,7 @@ function PlayerActionsMenu(props) {
|
|
|
3091
3122
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3092
3123
|
FileInputMenuItem,
|
|
3093
3124
|
{
|
|
3094
|
-
accept
|
|
3125
|
+
accept,
|
|
3095
3126
|
icon: icons.UploadIcon,
|
|
3096
3127
|
onSelect,
|
|
3097
3128
|
text: "Upload",
|
|
@@ -3455,7 +3486,47 @@ function UploadConfiguration({
|
|
|
3455
3486
|
(r) => r !== "highest" && r !== "audio-only"
|
|
3456
3487
|
).length > 0, [config.static_renditions]), [renditionMode, setRenditionMode] = React.useState(
|
|
3457
3488
|
isAdvancedMode ? "advanced" : "standard"
|
|
3458
|
-
),
|
|
3489
|
+
), [videoDuration, setVideoDuration] = React.useState(null), [urlFileSize, setUrlFileSize] = React.useState(null), [isLoadingDuration, setIsLoadingDuration] = React.useState(!1), [isLoadingFileSize, setIsLoadingFileSize] = React.useState(!1), [validationError, setValidationError] = React.useState(null), [canSkipFileSizeValidation, setCanSkipFileSizeValidation] = React.useState(!1), MAX_FILE_SIZE = pluginConfig.maxAssetFileSize, MAX_DURATION_SECONDS = pluginConfig.maxAssetDuration;
|
|
3490
|
+
React.useEffect(() => {
|
|
3491
|
+
setVideoDuration(null), setUrlFileSize(null), setIsLoadingDuration(!1), setIsLoadingFileSize(!1), setValidationError(null), setCanSkipFileSizeValidation(!1);
|
|
3492
|
+
let videoElement = null, currentVideoSrc = null;
|
|
3493
|
+
const cleanupVideo = (shouldRevokeUrl) => {
|
|
3494
|
+
videoElement && (videoElement.onloadedmetadata = null, videoElement.onerror = null, videoElement.src = "", videoElement.load(), videoElement = null), shouldRevokeUrl && currentVideoSrc?.startsWith("blob:") && URL.revokeObjectURL(currentVideoSrc), currentVideoSrc = null;
|
|
3495
|
+
}, validateDuration = (videoSrc, shouldRevokeUrl = !1) => {
|
|
3496
|
+
!MAX_DURATION_SECONDS || MAX_DURATION_SECONDS <= 0 || (setIsLoadingDuration(!0), videoElement = document.createElement("video"), videoElement.preload = "metadata", currentVideoSrc = videoSrc, videoElement.onloadedmetadata = () => {
|
|
3497
|
+
const duration = videoElement.duration;
|
|
3498
|
+
setVideoDuration(duration), setIsLoadingDuration(!1), duration > MAX_DURATION_SECONDS && setValidationError(
|
|
3499
|
+
`Video duration (${formatSeconds(duration)}) exceeds maximum allowed duration of ${formatSeconds(MAX_DURATION_SECONDS)}`
|
|
3500
|
+
), cleanupVideo(shouldRevokeUrl);
|
|
3501
|
+
}, videoElement.onerror = () => {
|
|
3502
|
+
setIsLoadingDuration(!1), console.warn("Could not read video metadata for validation"), cleanupVideo(shouldRevokeUrl);
|
|
3503
|
+
}, videoElement.src = videoSrc);
|
|
3504
|
+
}, validateFileSize = (size) => MAX_FILE_SIZE === void 0 || size <= MAX_FILE_SIZE ? !0 : (setValidationError(
|
|
3505
|
+
`File size (${formatBytes(size)}) exceeds maximum allowed size of ${formatBytes(MAX_FILE_SIZE)}`
|
|
3506
|
+
), !1);
|
|
3507
|
+
if (stagedUpload.type === "file") {
|
|
3508
|
+
const file = stagedUpload.files[0];
|
|
3509
|
+
validateFileSize(file.size) && validateDuration(URL.createObjectURL(file), !0);
|
|
3510
|
+
}
|
|
3511
|
+
if (stagedUpload.type === "url") {
|
|
3512
|
+
const url = stagedUpload.url;
|
|
3513
|
+
(async () => {
|
|
3514
|
+
setIsLoadingFileSize(!0);
|
|
3515
|
+
try {
|
|
3516
|
+
const contentLength = (await fetch(url, { method: "HEAD" })).headers.get("content-length"), fileSize = contentLength ? parseInt(contentLength, 10) : null;
|
|
3517
|
+
setIsLoadingFileSize(!1), fileSize && setUrlFileSize(fileSize);
|
|
3518
|
+
const shouldValidateDuration = MAX_FILE_SIZE === void 0 || fileSize === null || validateFileSize(fileSize);
|
|
3519
|
+
fileSize === null && MAX_FILE_SIZE !== void 0 && setCanSkipFileSizeValidation(!0), shouldValidateDuration && validateDuration(url);
|
|
3520
|
+
} catch {
|
|
3521
|
+
setIsLoadingFileSize(!1), console.warn("Could not validate file size from URL"), setCanSkipFileSizeValidation(!0), validateDuration(url);
|
|
3522
|
+
}
|
|
3523
|
+
})();
|
|
3524
|
+
}
|
|
3525
|
+
return () => {
|
|
3526
|
+
cleanupVideo(!0);
|
|
3527
|
+
};
|
|
3528
|
+
}, [stagedUpload, MAX_FILE_SIZE, MAX_DURATION_SECONDS]);
|
|
3529
|
+
const toggleRendition = (rendition) => {
|
|
3459
3530
|
const current = config.static_renditions, hasRendition = current.includes(rendition);
|
|
3460
3531
|
dispatch(hasRendition ? {
|
|
3461
3532
|
action: "static_renditions",
|
|
@@ -3490,6 +3561,13 @@ function UploadConfiguration({
|
|
|
3490
3561
|
header: "Configure Mux Upload",
|
|
3491
3562
|
onClose,
|
|
3492
3563
|
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { padding: 4, space: 2, children: [
|
|
3564
|
+
validationError && /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { padding: 3, tone: "critical", radius: 2, marginBottom: 2, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { gap: 2, align: "flex-start", children: [
|
|
3565
|
+
/* @__PURE__ */ jsxRuntime.jsx(icons.ErrorOutlineIcon, { width: 20, height: 20 }),
|
|
3566
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 2, children: [
|
|
3567
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, weight: "semibold", children: "Validation Error" }),
|
|
3568
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, children: validationError })
|
|
3569
|
+
] })
|
|
3570
|
+
] }) }),
|
|
3493
3571
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { size: 3, children: "FILE TO UPLOAD" }),
|
|
3494
3572
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3495
3573
|
ui.Card,
|
|
@@ -3503,7 +3581,14 @@ function UploadConfiguration({
|
|
|
3503
3581
|
/* @__PURE__ */ jsxRuntime.jsx(icons.DocumentVideoIcon, { fontSize: "2em" }),
|
|
3504
3582
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 2, children: [
|
|
3505
3583
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { textOverflow: "ellipsis", as: "h2", size: 3, children: stagedUpload.type === "file" ? stagedUpload.files[0].name : stagedUpload.url }),
|
|
3506
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { as: "p", size: 1, muted: !0, children: stagedUpload.type === "file" ? `Direct File Upload (${formatBytes(stagedUpload.files[0].size)})` : "File From URL (Unknown size)" })
|
|
3584
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { as: "p", size: 1, muted: !0, children: stagedUpload.type === "file" ? `Direct File Upload (${formatBytes(stagedUpload.files[0].size)})` : urlFileSize ? `File From URL (${formatBytes(urlFileSize)})` : isLoadingFileSize ? "File From URL (Loading size...)" : "File From URL (Unknown size)" }),
|
|
3585
|
+
stagedUpload.type === "file" && /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 1, children: [
|
|
3586
|
+
isLoadingDuration && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { as: "p", size: 1, muted: !0, children: "Reading video metadata..." }),
|
|
3587
|
+
videoDuration !== null && !validationError && /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { as: "p", size: 1, muted: !0, children: [
|
|
3588
|
+
"Duration: ",
|
|
3589
|
+
formatSeconds(videoDuration)
|
|
3590
|
+
] })
|
|
3591
|
+
] })
|
|
3507
3592
|
] })
|
|
3508
3593
|
] })
|
|
3509
3594
|
}
|
|
@@ -3695,11 +3780,13 @@ function UploadConfiguration({
|
|
|
3695
3780
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginTop: 4, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3696
3781
|
ui.Button,
|
|
3697
3782
|
{
|
|
3698
|
-
disabled: !basicConfig && !config.public_policy && !config.signed_policy,
|
|
3783
|
+
disabled: !basicConfig && !config.public_policy && !config.signed_policy || validationError !== null || isLoadingDuration || isLoadingFileSize && !canSkipFileSizeValidation,
|
|
3699
3784
|
icon: icons.UploadIcon,
|
|
3700
3785
|
text: "Upload",
|
|
3701
3786
|
tone: "positive",
|
|
3702
|
-
onClick: () =>
|
|
3787
|
+
onClick: () => {
|
|
3788
|
+
validationError || startUpload(formatUploadConfig(config));
|
|
3789
|
+
}
|
|
3703
3790
|
}
|
|
3704
3791
|
) })
|
|
3705
3792
|
] })
|
|
@@ -3822,7 +3909,7 @@ const ctrlKey = 17, cmdKey = 91, UploadCardWithFocusRing = withFocusRing(ui.Card
|
|
|
3822
3909
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3823
3910
|
HiddenInput,
|
|
3824
3911
|
{
|
|
3825
|
-
accept
|
|
3912
|
+
accept,
|
|
3826
3913
|
ref: inputRef,
|
|
3827
3914
|
tabIndex: 0,
|
|
3828
3915
|
type: "file",
|
|
@@ -3843,8 +3930,11 @@ const ctrlKey = 17, cmdKey = 91, UploadCardWithFocusRing = withFocusRing(ui.Card
|
|
|
3843
3930
|
)
|
|
3844
3931
|
] });
|
|
3845
3932
|
};
|
|
3933
|
+
function formatAcceptString(accept) {
|
|
3934
|
+
return accept.split(",").map((type) => type.trim().replace("/*", "")).join(" or ");
|
|
3935
|
+
}
|
|
3846
3936
|
function UploadPlaceholder(props) {
|
|
3847
|
-
const { setDialogState, readOnly, onSelect, hovering, needsSetup } = props, handleBrowse = React.useCallback(() => setDialogState("select-video"), [setDialogState]), handleConfigureApi = React.useCallback(() => setDialogState("secrets"), [setDialogState]), { hasConfigAccess } = useAccessControl(props.config);
|
|
3937
|
+
const { setDialogState, readOnly, onSelect, hovering, needsSetup, accept } = props, handleBrowse = React.useCallback(() => setDialogState("select-video"), [setDialogState]), handleConfigureApi = React.useCallback(() => setDialogState("secrets"), [setDialogState]), { hasConfigAccess } = useAccessControl(props.config);
|
|
3848
3938
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3849
3939
|
ui.Card,
|
|
3850
3940
|
{
|
|
@@ -3867,12 +3957,17 @@ function UploadPlaceholder(props) {
|
|
|
3867
3957
|
children: [
|
|
3868
3958
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", justify: "flex-start", gap: 2, flex: 1, children: [
|
|
3869
3959
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { justify: "center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { muted: !0, children: /* @__PURE__ */ jsxRuntime.jsx(icons.DocumentVideoIcon, {}) }) }),
|
|
3870
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { justify: "center", children: /* @__PURE__ */ jsxRuntime.
|
|
3960
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { justify: "center", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: 1, muted: !0, children: [
|
|
3961
|
+
"Drag ",
|
|
3962
|
+
formatAcceptString(accept),
|
|
3963
|
+
" file or paste URL here"
|
|
3964
|
+
] }) })
|
|
3871
3965
|
] }),
|
|
3872
3966
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Inline, { space: 2, children: [
|
|
3873
3967
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3874
3968
|
FileInputButton,
|
|
3875
3969
|
{
|
|
3970
|
+
accept,
|
|
3876
3971
|
mode: "bleed",
|
|
3877
3972
|
tone: "default",
|
|
3878
3973
|
icon: icons.UploadIcon,
|
|
@@ -4023,21 +4118,33 @@ function Uploader(props) {
|
|
|
4023
4118
|
complete: () => dispatch({ action: "complete" }),
|
|
4024
4119
|
error: (error) => dispatch({ action: "error", error })
|
|
4025
4120
|
});
|
|
4026
|
-
},
|
|
4027
|
-
|
|
4121
|
+
}, invalidFileToast = React.useCallback(() => {
|
|
4122
|
+
toast.push({
|
|
4123
|
+
status: "error",
|
|
4124
|
+
title: `Invalid file type. Accepted types: ${props.config.acceptedMimeTypes?.join(", ")}`
|
|
4125
|
+
});
|
|
4126
|
+
}, [props.config.acceptedMimeTypes, toast]), isInvalidFile = (files) => Array.from(files).some((file) => !props.config.acceptedMimeTypes?.some((acceptedType) => {
|
|
4127
|
+
const pattern = `^${acceptedType.replace("*", ".*")}$`;
|
|
4128
|
+
return new RegExp(pattern).test(file.type);
|
|
4129
|
+
})), handleUpload = (files) => {
|
|
4130
|
+
isInvalidFile(files) || dispatch({
|
|
4028
4131
|
action: "stageUpload",
|
|
4029
4132
|
input: { type: "file", files }
|
|
4030
4133
|
});
|
|
4031
4134
|
}, handlePaste = (event) => {
|
|
4032
4135
|
event.preventDefault(), event.stopPropagation();
|
|
4033
|
-
const url = (event.clipboardData || window.clipboardData)
|
|
4136
|
+
const url = (event.clipboardData || window.clipboardData)?.getData("text")?.trim();
|
|
4034
4137
|
if (!isValidUrl(url)) {
|
|
4035
4138
|
toast.push({ status: "error", title: "Invalid URL for Mux video input." });
|
|
4036
4139
|
return;
|
|
4037
4140
|
}
|
|
4038
4141
|
dispatch({ action: "stageUpload", input: { type: "url", url } });
|
|
4039
4142
|
}, handleDrop = (event) => {
|
|
4040
|
-
|
|
4143
|
+
if (event.preventDefault(), event.stopPropagation(), dragState === "invalid") {
|
|
4144
|
+
invalidFileToast(), setDragState(null);
|
|
4145
|
+
return;
|
|
4146
|
+
}
|
|
4147
|
+
setDragState(null), extractDroppedFiles(event.nativeEvent.dataTransfer).then((files) => {
|
|
4041
4148
|
dispatch({
|
|
4042
4149
|
action: "stageUpload",
|
|
4043
4150
|
input: { type: "file", files }
|
|
@@ -4047,8 +4154,11 @@ function Uploader(props) {
|
|
|
4047
4154
|
event.preventDefault(), event.stopPropagation();
|
|
4048
4155
|
}, handleDragEnter = (event) => {
|
|
4049
4156
|
event.stopPropagation(), dragEnteredEls.current.push(event.target);
|
|
4050
|
-
const type = event.dataTransfer.items?.[0]?.type
|
|
4051
|
-
|
|
4157
|
+
const type = event.dataTransfer.items?.[0]?.type, isValidType = props.config.acceptedMimeTypes?.some((acceptedType) => {
|
|
4158
|
+
const pattern = `^${acceptedType.replace("*", ".*")}$`;
|
|
4159
|
+
return new RegExp(pattern).test(type);
|
|
4160
|
+
});
|
|
4161
|
+
setDragState(isValidType ? "valid" : "invalid");
|
|
4052
4162
|
}, handleDragLeave = (event) => {
|
|
4053
4163
|
event.stopPropagation();
|
|
4054
4164
|
const idx = dragEnteredEls.current.indexOf(event.target);
|
|
@@ -4086,7 +4196,9 @@ function Uploader(props) {
|
|
|
4086
4196
|
}
|
|
4087
4197
|
);
|
|
4088
4198
|
let tone;
|
|
4089
|
-
|
|
4199
|
+
dragState && (tone = dragState === "valid" ? "positive" : "critical");
|
|
4200
|
+
const acceptMimeString = props.config?.acceptedMimeTypes?.length ? props.config.acceptedMimeTypes.join(",") : "video/*, audio/*";
|
|
4201
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4090
4202
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4091
4203
|
UploadCard,
|
|
4092
4204
|
{
|
|
@@ -4108,9 +4220,11 @@ function Uploader(props) {
|
|
|
4108
4220
|
readOnly: props.readOnly,
|
|
4109
4221
|
asset: props.asset,
|
|
4110
4222
|
onChange: props.onChange,
|
|
4223
|
+
config: props.config,
|
|
4111
4224
|
buttons: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4112
4225
|
PlayerActionsMenu$1,
|
|
4113
4226
|
{
|
|
4227
|
+
accept: acceptMimeString,
|
|
4114
4228
|
asset: props.asset,
|
|
4115
4229
|
dialogState: props.dialogState,
|
|
4116
4230
|
setDialogState: props.setDialogState,
|
|
@@ -4126,6 +4240,7 @@ function Uploader(props) {
|
|
|
4126
4240
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
4127
4241
|
UploadPlaceholder,
|
|
4128
4242
|
{
|
|
4243
|
+
accept: acceptMimeString,
|
|
4129
4244
|
hovering: dragState !== null,
|
|
4130
4245
|
onSelect: handleUpload,
|
|
4131
4246
|
readOnly: !!props.readOnly,
|
|
@@ -4386,7 +4501,8 @@ const muxVideoSchema = {
|
|
|
4386
4501
|
defaultPublic: !0,
|
|
4387
4502
|
defaultSigned: !1,
|
|
4388
4503
|
tool: DEFAULT_TOOL_CONFIG,
|
|
4389
|
-
allowedRolesForConfiguration: []
|
|
4504
|
+
allowedRolesForConfiguration: [],
|
|
4505
|
+
acceptedMimeTypes: ["video/*", "audio/*"]
|
|
4390
4506
|
};
|
|
4391
4507
|
function convertLegacyConfig(config) {
|
|
4392
4508
|
return config.static_renditions && config.static_renditions.length > 0 ? { static_renditions: config.static_renditions } : config.mp4_support === "standard" ? { static_renditions: ["highest"] } : { static_renditions: [] };
|