sanity-plugin-mux-input
5.1.15.1.2
dist/index.js.map~
dist/index.js.mapModified+1−1
Index: package/dist/index.js.map
===================================================================
--- package/dist/index.js.map
+++ package/dist/index.js.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"index.js","names":["{\n muxApiHost,\n children,\n}: {\n muxApiHost: string | undefined\n children: React.ReactNode\n}","<MuxApiHostContext.Provider value={muxApiHost}>{children}</MuxApiHostContext.Provider>","MuxApiHostContext.Provider","_c","<svg\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 24 24\"\n height=\"1em\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M21 3H3c-1.11 0-2 .89-2 2v12c0 1.1.89 2 2 2h5v2h8v-2h5c1.1 0 1.99-.9 1.99-2L23 5c0-1.11-.9-2-2-2zm0 14H3V5h18v12zm-5-6l-7 4V7z\" />\n </svg>","_c","{\n config,\n children,\n}: DrmPlaybackWarningContextProviderProps","warningDisabled || window.localStorage.getItem(LOCAL_STORAGE_HAS_SHOWN_WARNING_KEY) === 'true'","(b: boolean) => {\n window.localStorage.setItem(LOCAL_STORAGE_HAS_SHOWN_WARNING_KEY, b.toString())\n setHasWarnedAboutDrmPlayback(b)\n }","useCallback((b: boolean) => {\n window.localStorage.setItem(LOCAL_STORAGE_HAS_SHOWN_WARNING_KEY, b.toString())\n setHasWarnedAboutDrmPlayback(b)\n }, [])","{\n hasShownWarning: hasWarnedAboutDrmPlayback,\n setHasWarnedAboutDrmPlayback: setHasShownWarning,\n }","useMemo(\n () => ({\n hasShownWarning: hasWarnedAboutDrmPlayback,\n setHasWarnedAboutDrmPlayback: setHasShownWarning,\n }),\n [hasWarnedAboutDrmPlayback, setHasShownWarning],\n )","<DrmPlaybackWarningContext.Provider value={value}>\n {children}\n </DrmPlaybackWarningContext.Provider>","DrmPlaybackWarningContext.Provider","{onClose}: {onClose: () => void}","() => {\n setHasWarnedAboutDrmPlayback(true)\n onClose()\n }","<Stack padding={3}>\n <Button mode=\"ghost\" tone=\"primary\" onClick={_onClose} text=\"Ok\" />\n </Stack>","[3, 3, 3]","<Card padding={[3, 3, 3]} radius={2}>\n <Stack gap={3}>\n <Text size={1} weight=\"semibold\">\n DRM-protected playback will generate a license with a small associated cost. The\n plugin will attempt to play signed or public playback IDs instead whenever possible.\n </Text>\n </Stack>\n </Card>","<Stack gap={3} padding={3}>\n <Card padding={[3, 3, 3]} radius={2}>\n <Stack gap={3}>\n <Text size={1} weight=\"semibold\">\n DRM-protected playback will generate a license with a small associated cost. The\n plugin will attempt to play signed or public playback IDs instead whenever possible.\n </Text>\n </Stack>\n </Card>\n <Card padding={[3, 3, 3]} radius={2} tone=\"suggest\">\n <Stack gap={3}>\n <Text size={1} weight=\"semibold\">\n This is a one time warning. If it persists, you can disable it from your plugin\n configuration.\n </Text>\n </Stack>\n </Card>\n </Stack>","<Dialog\n open\n id=\"drm-playback-warn\"\n onClose={_onClose}\n header=\"DRM Playback Warning\"\n footer={\n <Stack padding={3}>\n <Button mode=\"ghost\" tone=\"primary\" onClick={_onClose} text=\"Ok\" />\n </Stack>\n }\n >\n <Stack gap={3} padding={3}>\n <Card padding={[3, 3, 3]} radius={2}>\n <Stack gap={3}>\n <Text size={1} weight=\"semibold\">\n DRM-protected playback will generate a license with a small associated cost. The\n plugin will attempt to play signed or public playback IDs instead whenever possible.\n </Text>\n </Stack>\n </Card>\n <Card padding={[3, 3, 3]} radius={2} tone=\"suggest\">\n <Stack gap={3}>\n <Text size={1} weight=\"semibold\">\n This is a one time warning. If it persists, you can disable it from your plugin\n configuration.\n </Text>\n </Stack>\n </Card>\n </Stack>\n </Dialog>","_c","hasWarned","{apiVersion: SANITY_API_VERSION}","muxApiHost ? withMuxApiHost(client, muxApiHost) : client","useMemo(\n () => (muxApiHost ? withMuxApiHost(client, muxApiHost) : client),\n [client, muxApiHost],\n )","useClient","_c","useSanityClient","{documentStore, sort, searchQuery}","assetDocuments = []","useMemo(() => ({documentStore, sort, searchQuery}), [documentStore, sort, searchQuery])","collate<VideoAssetDocument>(assetDocuments).map(\n (collated) =>\n ({\n ...(collated.draft || collated.published),\n _id: collated.id,\n }) as VideoAssetDocument,\n )","(collated) =>\n ({\n ...(collated.draft || collated.published),\n _id: collated.id,\n }) as VideoAssetDocument","useMemo(\n () =>\n // Avoid displaying both drafts & published assets by collating them together and giving preference to drafts\n collate<VideoAssetDocument>(assetDocuments).map(\n (collated) =>\n ({\n ...(collated.draft || collated.published),\n _id: collated.id,\n }) as VideoAssetDocument,\n ),\n [assetDocuments],\n )","{\n assets,\n isLoading,\n sort,\n searchQuery,\n setSort,\n setSearchQuery,\n }","_c","_temp","{\n token: value?.token || null,\n secretKey: value?.secretKey || null,\n enableSignedUrls: value?.enableSignedUrls || false,\n signingKeyId: value?.signingKeyId || null,\n signingKeyPrivate: value?.signingKeyPrivate || null,\n drmConfigId: value?.drmConfigId || null,\n }","value?.token || null","value?.secretKey || null","value?.enableSignedUrls || false","value?.signingKeyId || null","value?.signingKeyPrivate || null","value?.drmConfigId || null","{\n isInitialSetup: !exists,\n needsSetup: !secrets?.token || !secrets?.secretKey,\n secrets,\n }","!exists","!secrets?.token || !secrets?.secretKey","useMemo(() => {\n const exists = Boolean(value)\n const secrets: Secrets = {\n token: value?.token || null,\n secretKey: value?.secretKey || null,\n enableSignedUrls: value?.enableSignedUrls || false,\n signingKeyId: value?.signingKeyId || null,\n signingKeyPrivate: value?.signingKeyPrivate || null,\n drmConfigId: value?.drmConfigId || null,\n }\n return {\n isInitialSetup: !exists,\n needsSetup: !secrets?.token || !secrets?.secretKey,\n secrets,\n }\n }, [value])","{error, isLoading, value: cache}","path","_c","{height = 26}: Props","height = 26","{\n fillRule: 'nonzero',\n }","{height: `${height}px`}","`${height}px`","<path\n d=\"M994.287,93.486c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m0,-93.486c-34.509,-0 -62.484,27.976 -62.484,62.486l0,187.511c0,68.943 -56.09,125.033 -125.032,125.033c-68.942,-0 -125.03,-56.09 -125.03,-125.033l0,-187.511c0,-34.51 -27.976,-62.486 -62.485,-62.486c-34.509,-0 -62.484,27.976 -62.484,62.486l0,187.511c0,137.853 112.149,250.003 249.999,250.003c137.851,-0 250.001,-112.15 250.001,-250.003l0,-187.511c0,-34.51 -27.976,-62.486 -62.485,-62.486\"\n style={pathStyle}\n />","<path\n d=\"M1537.51,468.511c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m-275.883,-218.509l-143.33,143.329c-24.402,24.402 -24.402,63.966 0,88.368c24.402,24.402 63.967,24.402 88.369,-0l143.33,-143.329l143.328,143.329c24.402,24.4 63.967,24.402 88.369,-0c24.403,-24.402 24.403,-63.966 0.001,-88.368l-143.33,-143.329l0.001,-0.004l143.329,-143.329c24.402,-24.402 24.402,-63.965 0,-88.367c-24.402,-24.402 -63.967,-24.402 -88.369,-0l-143.329,143.328l-143.329,-143.328c-24.402,-24.401 -63.967,-24.402 -88.369,-0c-24.402,24.402 -24.402,63.965 0,88.367l143.329,143.329l0,0.004Z\"\n style={pathStyle}\n />","<path\n d=\"M437.511,468.521c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m23.915,-463.762c-23.348,-9.672 -50.226,-4.327 -68.096,13.544l-143.331,143.329l-143.33,-143.329c-17.871,-17.871 -44.747,-23.216 -68.096,-13.544c-23.349,9.671 -38.574,32.455 -38.574,57.729l0,375.026c0,34.51 27.977,62.486 62.487,62.486c34.51,-0 62.486,-27.976 62.486,-62.486l0,-224.173l80.843,80.844c24.404,24.402 63.965,24.402 88.369,-0l80.843,-80.844l0,224.173c0,34.51 27.976,62.486 62.486,62.486c34.51,-0 62.486,-27.976 62.486,-62.486l0,-375.026c0,-25.274 -15.224,-48.058 -38.573,-57.729\"\n style={pathStyle}\n />","<g id=\"Layer-1\" fill={fillColor}>\n <path\n d=\"M994.287,93.486c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m0,-93.486c-34.509,-0 -62.484,27.976 -62.484,62.486l0,187.511c0,68.943 -56.09,125.033 -125.032,125.033c-68.942,-0 -125.03,-56.09 -125.03,-125.033l0,-187.511c0,-34.51 -27.976,-62.486 -62.485,-62.486c-34.509,-0 -62.484,27.976 -62.484,62.486l0,187.511c0,137.853 112.149,250.003 249.999,250.003c137.851,-0 250.001,-112.15 250.001,-250.003l0,-187.511c0,-34.51 -27.976,-62.486 -62.485,-62.486\"\n style={pathStyle}\n />\n <path\n d=\"M1537.51,468.511c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m-275.883,-218.509l-143.33,143.329c-24.402,24.402 -24.402,63.966 0,88.368c24.402,24.402 63.967,24.402 88.369,-0l143.33,-143.329l143.328,143.329c24.402,24.4 63.967,24.402 88.369,-0c24.403,-24.402 24.403,-63.966 0.001,-88.368l-143.33,-143.329l0.001,-0.004l143.329,-143.329c24.402,-24.402 24.402,-63.965 0,-88.367c-24.402,-24.402 -63.967,-24.402 -88.369,-0l-143.329,143.328l-143.329,-143.328c-24.402,-24.401 -63.967,-24.402 -88.369,-0c-24.402,24.402 -24.402,63.965 0,88.367l143.329,143.329l0,0.004Z\"\n style={pathStyle}\n />\n <path\n d=\"M437.511,468.521c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m23.915,-463.762c-23.348,-9.672 -50.226,-4.327 -68.096,13.544l-143.331,143.329l-143.33,-143.329c-17.871,-17.871 -44.747,-23.216 -68.096,-13.544c-23.349,9.671 -38.574,32.455 -38.574,57.729l0,375.026c0,34.51 27.977,62.486 62.487,62.486c34.51,-0 62.486,-27.976 62.486,-62.486l0,-224.173l80.843,80.844c24.404,24.402 63.965,24.402 88.369,-0l80.843,-80.844l0,224.173c0,34.51 27.976,62.486 62.486,62.486c34.51,-0 62.486,-27.976 62.486,-62.486l0,-375.026c0,-25.274 -15.224,-48.058 -38.573,-57.729\"\n style={pathStyle}\n />\n </g>","<svg\n aria-labelledby={titleId}\n style={{height: `${height}px`}}\n viewBox=\"0 0 1600 500\"\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlSpace=\"preserve\"\n >\n <g id=\"Layer-1\" fill={fillColor}>\n <path\n d=\"M994.287,93.486c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m0,-93.486c-34.509,-0 -62.484,27.976 -62.484,62.486l0,187.511c0,68.943 -56.09,125.033 -125.032,125.033c-68.942,-0 -125.03,-56.09 -125.03,-125.033l0,-187.511c0,-34.51 -27.976,-62.486 -62.485,-62.486c-34.509,-0 -62.484,27.976 -62.484,62.486l0,187.511c0,137.853 112.149,250.003 249.999,250.003c137.851,-0 250.001,-112.15 250.001,-250.003l0,-187.511c0,-34.51 -27.976,-62.486 -62.485,-62.486\"\n style={pathStyle}\n />\n <path\n d=\"M1537.51,468.511c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m-275.883,-218.509l-143.33,143.329c-24.402,24.402 -24.402,63.966 0,88.368c24.402,24.402 63.967,24.402 88.369,-0l143.33,-143.329l143.328,143.329c24.402,24.4 63.967,24.402 88.369,-0c24.403,-24.402 24.403,-63.966 0.001,-88.368l-143.33,-143.329l0.001,-0.004l143.329,-143.329c24.402,-24.402 24.402,-63.965 0,-88.367c-24.402,-24.402 -63.967,-24.402 -88.369,-0l-143.329,143.328l-143.329,-143.328c-24.402,-24.401 -63.967,-24.402 -88.369,-0c-24.402,24.402 -24.402,63.965 0,88.367l143.329,143.329l0,0.004Z\"\n style={pathStyle}\n />\n <path\n d=\"M437.511,468.521c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m23.915,-463.762c-23.348,-9.672 -50.226,-4.327 -68.096,13.544l-143.331,143.329l-143.33,-143.329c-17.871,-17.871 -44.747,-23.216 -68.096,-13.544c-23.349,9.671 -38.574,32.455 -38.574,57.729l0,375.026c0,34.51 27.977,62.486 62.487,62.486c34.51,-0 62.486,-27.976 62.486,-62.486l0,-224.173l80.843,80.844c24.404,24.402 63.965,24.402 88.369,-0l80.843,-80.844l0,224.173c0,34.51 27.976,62.486 62.486,62.486c34.51,-0 62.486,-27.976 62.486,-62.486l0,-375.026c0,-25.274 -15.224,-48.058 -38.573,-57.729\"\n style={pathStyle}\n />\n </g>\n </svg>","_c","<>\n <Logo>\n <MuxLogo height={13} />\n </Logo>\n API Credentials\n </>","_c","_Fragment","title || <em>Untitled</em>","<Text as=\"label\" htmlFor={inputId} weight=\"semibold\" size={1}>\n {title || <em>Untitled</em>}\n </Text>","description && (\n <Text muted size={1}>\n {description}\n </Text>\n )","<Flex align=\"flex-end\">\n <Box flex={1} paddingY={2}>\n <Stack gap={2}>\n <Text as=\"label\" htmlFor={inputId} weight=\"semibold\" size={1}>\n {title || <em>Untitled</em>}\n </Text>\n\n {description && (\n <Text muted size={1}>\n {description}\n </Text>\n )}\n </Stack>\n </Box>\n </Flex>","<div>{children}</div>","<Stack gap={1}>\n <Flex align=\"flex-end\">\n <Box flex={1} paddingY={2}>\n <Stack gap={2}>\n <Text as=\"label\" htmlFor={inputId} weight=\"semibold\" size={1}>\n {title || <em>Untitled</em>}\n </Text>\n\n {description && (\n <Text muted size={1}>\n {description}\n </Text>\n )}\n </Stack>\n </Box>\n </Flex>\n <div>{children}</div>\n </Stack>","FormField","_c","{secrets, setDialogState}: ConfigureApiDialogProps","() => setDialogState(false)","useCallback(() => setDialogState(false), [setDialogState])","fieldNames.map((field) => `${id}-${field}`)","(event: SubmitEvent<HTMLFormElement>) => {\n event.preventDefault()\n\n if (!saving.current && event.currentTarget.reportValidity()) {\n saving.current = true\n dispatch({type: 'submit'})\n const {token, secretKey, enableSignedUrls, drmConfigId} = state\n handleSaveSecrets({token, secretKey, enableSignedUrls, drmConfigId})\n .then((savedSecrets) => {\n const {projectId, dataset} = client.config()\n clear([cacheNs, secretsId, projectId, dataset])\n preload(() => Promise.resolve(savedSecrets), [cacheNs, secretsId, projectId, dataset])\n setDialogState(false)\n })\n .catch((err) => dispatch({type: 'error', payload: err.message}))\n .finally(() => {\n saving.current = false\n })\n }\n }","useCallback(\n (event: SubmitEvent<HTMLFormElement>) => {\n event.preventDefault()\n\n if (!saving.current && event.currentTarget.reportValidity()) {\n saving.current = true\n dispatch({type: 'submit'})\n const {token, secretKey, enableSignedUrls, drmConfigId} = state\n handleSaveSecrets({token, secretKey, enableSignedUrls, drmConfigId})\n .then((savedSecrets) => {\n const {projectId, dataset} = client.config()\n clear([cacheNs, secretsId, projectId, dataset])\n preload(() => Promise.resolve(savedSecrets), [cacheNs, secretsId, projectId, dataset])\n setDialogState(false)\n })\n .catch((err) => dispatch({type: 'error', payload: err.message}))\n .finally(() => {\n saving.current = false\n })\n }\n },\n [client, dispatch, handleSaveSecrets, setDialogState, state],\n )","(event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'token', value: event.currentTarget.value},\n })\n }","event","useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'token', value: event.currentTarget.value},\n })\n },\n [dispatch],\n )","(event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'secretKey', value: event.currentTarget.value},\n })\n }","useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'secretKey', value: event.currentTarget.value},\n })\n },\n [dispatch],\n )","(event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'enableSignedUrls', value: event.currentTarget.checked},\n })\n }","useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'enableSignedUrls', value: event.currentTarget.checked},\n })\n },\n [dispatch],\n )","(event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'drmConfigId', value: event.currentTarget.value},\n })\n }","useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'drmConfigId', value: event.currentTarget.value},\n })\n },\n [dispatch],\n )","() => {\n if (firstField.current) {\n firstField.current.focus()\n }\n }","[firstField]","<Header />","!hasSecretsInitially && (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"primary\">\n <Stack gap={3}>\n <Text size={1}>\n To set up a new access token, go to your{' '}\n <a\n href=\"https://dashboard.mux.com/settings/access-tokens\"\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n >\n account on mux.com\n </a>\n .\n </Text>\n <Text size={1}>\n The access token needs permissions: <strong>Mux Video </strong>\n (Full Access) and <strong>Mux Data</strong> (Read)\n <br />\n To use Signed URLs, the token must also have System permissions.\n <br />\n The credentials will be stored safely in a hidden document only available to\n editors.\n </Text>\n </Stack>\n </Card>\n )","<TextInput\n id={tokenId}\n ref={firstField}\n onChange={handleChangeToken}\n type=\"text\"\n value={state.token ?? ''}\n required={!!state.secretKey || state.enableSignedUrls}\n />","state.token ?? ''","!!state.secretKey || state.enableSignedUrls","<FormField title=\"Access Token\" inputId={tokenId}>\n <TextInput\n id={tokenId}\n ref={firstField}\n onChange={handleChangeToken}\n type=\"text\"\n value={state.token ?? ''}\n required={!!state.secretKey || state.enableSignedUrls}\n />\n </FormField>","<TextInput\n id={secretKeyId}\n onChange={handleChangeSecretKey}\n type=\"text\"\n value={state.secretKey ?? ''}\n required={!!state.token || state.enableSignedUrls}\n />","state.secretKey ?? ''","!!state.token || state.enableSignedUrls","<FormField title=\"Secret Key\" inputId={secretKeyId}>\n <TextInput\n id={secretKeyId}\n onChange={handleChangeSecretKey}\n type=\"text\"\n value={state.secretKey ?? ''}\n required={!!state.token || state.enableSignedUrls}\n />\n </FormField>","{display: 'block'}","<Checkbox\n id={enableSignedUrlsId}\n onChange={handleChangeEnableSignedUrls}\n checked={state.enableSignedUrls}\n style={{display: 'block'}}\n />","enableSignedUrls","<Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor={enableSignedUrlsId}>Enable Signed Urls</label>\n </Text>\n </Box>","<Flex align=\"center\">\n <Checkbox\n id={enableSignedUrlsId}\n onChange={handleChangeEnableSignedUrls}\n checked={state.enableSignedUrls}\n style={{display: 'block'}}\n />\n <Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor={enableSignedUrlsId}>Enable Signed Urls</label>\n </Text>\n </Box>\n </Flex>","secrets.signingKeyId && state.enableSignedUrls ? (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"caution\">\n <Stack gap={3}>\n <Text size={1}>The signing key ID that Sanity will use is:</Text>\n <Code size={1}>{secrets.signingKeyId}</Code>\n <Text size={1}>\n This key is only used for previewing content in the Sanity UI.\n <br />\n You should generate a different key to use in your application server.\n </Text>\n </Stack>\n </Card>\n ) : null","signingKeyId","<Stack gap={4}>\n <Flex align=\"center\">\n <Checkbox\n id={enableSignedUrlsId}\n onChange={handleChangeEnableSignedUrls}\n checked={state.enableSignedUrls}\n style={{display: 'block'}}\n />\n <Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor={enableSignedUrlsId}>Enable Signed Urls</label>\n </Text>\n </Box>\n </Flex>\n {secrets.signingKeyId && state.enableSignedUrls ? (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"caution\">\n <Stack gap={3}>\n <Text size={1}>The signing key ID that Sanity will use is:</Text>\n <Code size={1}>{secrets.signingKeyId}</Code>\n <Text size={1}>\n This key is only used for previewing content in the Sanity UI.\n <br />\n You should generate a different key to use in your application server.\n </Text>\n </Stack>\n </Card>\n ) : null}\n </Stack>","<TextInput\n id={drmConfigIdId}\n onChange={handleChangeDrmConfigId}\n type=\"text\"\n value={state.drmConfigId ?? ''}\n required={false}\n />","state.drmConfigId ?? ''","<FormField title=\"DRM Configuration ID\" inputId={drmConfigIdId}>\n <TextInput\n id={drmConfigIdId}\n onChange={handleChangeDrmConfigId}\n type=\"text\"\n value={state.drmConfigId ?? ''}\n required={false}\n />\n </FormField>","[3, 3, 3]","<Text size={1}>\n DRM (Digital Rights Management) provides an extra layer of content security for\n video content streamed from Mux. For additional information check out our{' '}\n <a\n href=\"https://www.mux.com/docs/guides/protect-videos-with-drm#play-drm-protected-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n DRM Guide\n </a>\n .\n </Text>","<Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"neutral\">\n <Stack gap={3}>\n <Text size={1}>\n DRM (Digital Rights Management) provides an extra layer of content security for\n video content streamed from Mux. For additional information check out our{' '}\n <a\n href=\"https://www.mux.com/docs/guides/protect-videos-with-drm#play-drm-protected-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n DRM Guide\n </a>\n .\n </Text>\n <Text size={1}>\n <a\n href=\"https://www.mux.com/support/human\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Contact us\n </a>{' '}\n to get started using DRM.\n </Text>\n </Stack>\n </Card>","<Button\n text=\"Save\"\n disabled={!dirty}\n loading={state.submitting}\n tone=\"primary\"\n mode=\"default\"\n type=\"submit\"\n />","submitting","!dirty","<Button\n disabled={state.submitting}\n text=\"Cancel\"\n mode=\"bleed\"\n onClick={handleClose}\n />","<Inline gap={2}>\n <Button\n text=\"Save\"\n disabled={!dirty}\n loading={state.submitting}\n tone=\"primary\"\n mode=\"default\"\n type=\"submit\"\n />\n <Button\n disabled={state.submitting}\n text=\"Cancel\"\n mode=\"bleed\"\n onClick={handleClose}\n />\n </Inline>","state.error && (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"critical\">\n <Text>{state.error}</Text>\n </Card>\n )","error","<Stack gap={4}>\n {!hasSecretsInitially && (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"primary\">\n <Stack gap={3}>\n <Text size={1}>\n To set up a new access token, go to your{' '}\n <a\n href=\"https://dashboard.mux.com/settings/access-tokens\"\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n >\n account on mux.com\n </a>\n .\n </Text>\n <Text size={1}>\n The access token needs permissions: <strong>Mux Video </strong>\n (Full Access) and <strong>Mux Data</strong> (Read)\n <br />\n To use Signed URLs, the token must also have System permissions.\n <br />\n The credentials will be stored safely in a hidden document only available to\n editors.\n </Text>\n </Stack>\n </Card>\n )}\n <FormField title=\"Access Token\" inputId={tokenId}>\n <TextInput\n id={tokenId}\n ref={firstField}\n onChange={handleChangeToken}\n type=\"text\"\n value={state.token ?? ''}\n required={!!state.secretKey || state.enableSignedUrls}\n />\n </FormField>\n <FormField title=\"Secret Key\" inputId={secretKeyId}>\n <TextInput\n id={secretKeyId}\n onChange={handleChangeSecretKey}\n type=\"text\"\n value={state.secretKey ?? ''}\n required={!!state.token || state.enableSignedUrls}\n />\n </FormField>\n\n <Stack gap={4}>\n <Flex align=\"center\">\n <Checkbox\n id={enableSignedUrlsId}\n onChange={handleChangeEnableSignedUrls}\n checked={state.enableSignedUrls}\n style={{display: 'block'}}\n />\n <Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor={enableSignedUrlsId}>Enable Signed Urls</label>\n </Text>\n </Box>\n </Flex>\n {secrets.signingKeyId && state.enableSignedUrls ? (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"caution\">\n <Stack gap={3}>\n <Text size={1}>The signing key ID that Sanity will use is:</Text>\n <Code size={1}>{secrets.signingKeyId}</Code>\n <Text size={1}>\n This key is only used for previewing content in the Sanity UI.\n <br />\n You should generate a different key to use in your application server.\n </Text>\n </Stack>\n </Card>\n ) : null}\n </Stack>\n\n <FormField title=\"DRM Configuration ID\" inputId={drmConfigIdId}>\n <TextInput\n id={drmConfigIdId}\n onChange={handleChangeDrmConfigId}\n type=\"text\"\n value={state.drmConfigId ?? ''}\n required={false}\n />\n </FormField>\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"neutral\">\n <Stack gap={3}>\n <Text size={1}>\n DRM (Digital Rights Management) provides an extra layer of content security for\n video content streamed from Mux. For additional information check out our{' '}\n <a\n href=\"https://www.mux.com/docs/guides/protect-videos-with-drm#play-drm-protected-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n DRM Guide\n </a>\n .\n </Text>\n <Text size={1}>\n <a\n href=\"https://www.mux.com/support/human\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Contact us\n </a>{' '}\n to get started using DRM.\n </Text>\n </Stack>\n </Card>\n\n <Inline gap={2}>\n <Button\n text=\"Save\"\n disabled={!dirty}\n loading={state.submitting}\n tone=\"primary\"\n mode=\"default\"\n type=\"submit\"\n />\n <Button\n disabled={state.submitting}\n text=\"Cancel\"\n mode=\"bleed\"\n onClick={handleClose}\n />\n </Inline>\n {state.error && (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"critical\">\n <Text>{state.error}</Text>\n </Card>\n )}\n </Stack>","<Box padding={3}>\n <form onSubmit={handleSubmit} noValidate>\n <Stack gap={4}>\n {!hasSecretsInitially && (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"primary\">\n <Stack gap={3}>\n <Text size={1}>\n To set up a new access token, go to your{' '}\n <a\n href=\"https://dashboard.mux.com/settings/access-tokens\"\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n >\n account on mux.com\n </a>\n .\n </Text>\n <Text size={1}>\n The access token needs permissions: <strong>Mux Video </strong>\n (Full Access) and <strong>Mux Data</strong> (Read)\n <br />\n To use Signed URLs, the token must also have System permissions.\n <br />\n The credentials will be stored safely in a hidden document only available to\n editors.\n </Text>\n </Stack>\n </Card>\n )}\n <FormField title=\"Access Token\" inputId={tokenId}>\n <TextInput\n id={tokenId}\n ref={firstField}\n onChange={handleChangeToken}\n type=\"text\"\n value={state.token ?? ''}\n required={!!state.secretKey || state.enableSignedUrls}\n />\n </FormField>\n <FormField title=\"Secret Key\" inputId={secretKeyId}>\n <TextInput\n id={secretKeyId}\n onChange={handleChangeSecretKey}\n type=\"text\"\n value={state.secretKey ?? ''}\n required={!!state.token || state.enableSignedUrls}\n />\n </FormField>\n\n <Stack gap={4}>\n <Flex align=\"center\">\n <Checkbox\n id={enableSignedUrlsId}\n onChange={handleChangeEnableSignedUrls}\n checked={state.enableSignedUrls}\n style={{display: 'block'}}\n />\n <Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor={enableSignedUrlsId}>Enable Signed Urls</label>\n </Text>\n </Box>\n </Flex>\n {secrets.signingKeyId && state.enableSignedUrls ? (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"caution\">\n <Stack gap={3}>\n <Text size={1}>The signing key ID that Sanity will use is:</Text>\n <Code size={1}>{secrets.signingKeyId}</Code>\n <Text size={1}>\n This key is only used for previewing content in the Sanity UI.\n <br />\n You should generate a different key to use in your application server.\n </Text>\n </Stack>\n </Card>\n ) : null}\n </Stack>\n\n <FormField title=\"DRM Configuration ID\" inputId={drmConfigIdId}>\n <TextInput\n id={drmConfigIdId}\n onChange={handleChangeDrmConfigId}\n type=\"text\"\n value={state.drmConfigId ?? ''}\n required={false}\n />\n </FormField>\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"neutral\">\n <Stack gap={3}>\n <Text size={1}>\n DRM (Digital Rights Management) provides an extra layer of content security for\n video content streamed from Mux. For additional information check out our{' '}\n <a\n href=\"https://www.mux.com/docs/guides/protect-videos-with-drm#play-drm-protected-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n DRM Guide\n </a>\n .\n </Text>\n <Text size={1}>\n <a\n href=\"https://www.mux.com/support/human\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Contact us\n </a>{' '}\n to get started using DRM.\n </Text>\n </Stack>\n </Card>\n\n <Inline gap={2}>\n <Button\n text=\"Save\"\n disabled={!dirty}\n loading={state.submitting}\n tone=\"primary\"\n mode=\"default\"\n type=\"submit\"\n />\n <Button\n disabled={state.submitting}\n text=\"Cancel\"\n mode=\"bleed\"\n onClick={handleClose}\n />\n </Inline>\n {state.error && (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"critical\">\n <Text>{state.error}</Text>\n </Card>\n )}\n </Stack>\n </form>\n </Box>","<Dialog\n animate\n id={id}\n onClose={handleClose}\n onClickOutside={handleClose}\n header={<Header />}\n zOffset={DIALOGS_Z_INDEX}\n position=\"fixed\"\n width={1}\n >\n <Box padding={3}>\n <form onSubmit={handleSubmit} noValidate>\n <Stack gap={4}>\n {!hasSecretsInitially && (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"primary\">\n <Stack gap={3}>\n <Text size={1}>\n To set up a new access token, go to your{' '}\n <a\n href=\"https://dashboard.mux.com/settings/access-tokens\"\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n >\n account on mux.com\n </a>\n .\n </Text>\n <Text size={1}>\n The access token needs permissions: <strong>Mux Video </strong>\n (Full Access) and <strong>Mux Data</strong> (Read)\n <br />\n To use Signed URLs, the token must also have System permissions.\n <br />\n The credentials will be stored safely in a hidden document only available to\n editors.\n </Text>\n </Stack>\n </Card>\n )}\n <FormField title=\"Access Token\" inputId={tokenId}>\n <TextInput\n id={tokenId}\n ref={firstField}\n onChange={handleChangeToken}\n type=\"text\"\n value={state.token ?? ''}\n required={!!state.secretKey || state.enableSignedUrls}\n />\n </FormField>\n <FormField title=\"Secret Key\" inputId={secretKeyId}>\n <TextInput\n id={secretKeyId}\n onChange={handleChangeSecretKey}\n type=\"text\"\n value={state.secretKey ?? ''}\n required={!!state.token || state.enableSignedUrls}\n />\n </FormField>\n\n <Stack gap={4}>\n <Flex align=\"center\">\n <Checkbox\n id={enableSignedUrlsId}\n onChange={handleChangeEnableSignedUrls}\n checked={state.enableSignedUrls}\n style={{display: 'block'}}\n />\n <Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor={enableSignedUrlsId}>Enable Signed Urls</label>\n </Text>\n </Box>\n </Flex>\n {secrets.signingKeyId && state.enableSignedUrls ? (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"caution\">\n <Stack gap={3}>\n <Text size={1}>The signing key ID that Sanity will use is:</Text>\n <Code size={1}>{secrets.signingKeyId}</Code>\n <Text size={1}>\n This key is only used for previewing content in the Sanity UI.\n <br />\n You should generate a different key to use in your application server.\n </Text>\n </Stack>\n </Card>\n ) : null}\n </Stack>\n\n <FormField title=\"DRM Configuration ID\" inputId={drmConfigIdId}>\n <TextInput\n id={drmConfigIdId}\n onChange={handleChangeDrmConfigId}\n type=\"text\"\n value={state.drmConfigId ?? ''}\n required={false}\n />\n </FormField>\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"neutral\">\n <Stack gap={3}>\n <Text size={1}>\n DRM (Digital Rights Management) provides an extra layer of content security for\n video content streamed from Mux. For additional information check out our{' '}\n <a\n href=\"https://www.mux.com/docs/guides/protect-videos-with-drm#play-drm-protected-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n DRM Guide\n </a>\n .\n </Text>\n <Text size={1}>\n <a\n href=\"https://www.mux.com/support/human\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Contact us\n </a>{' '}\n to get started using DRM.\n </Text>\n </Stack>\n </Card>\n\n <Inline gap={2}>\n <Button\n text=\"Save\"\n disabled={!dirty}\n loading={state.submitting}\n tone=\"primary\"\n mode=\"default\"\n type=\"submit\"\n />\n <Button\n disabled={state.submitting}\n text=\"Cancel\"\n mode=\"bleed\"\n onClick={handleClose}\n />\n </Inline>\n {state.error && (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"critical\">\n <Text>{state.error}</Text>\n </Card>\n )}\n </Stack>\n </form>\n </Box>\n </Dialog>","() => setDialogOpen('secrets')","useCallback(() => setDialogOpen('secrets'), [setDialogOpen])","<ConfigureApiDialog\n secrets={secretDocumentValues.value.secrets}\n setDialogState={setDialogOpen}\n />","secrets","<Button mode=\"bleed\" text=\"Configure plugin\" onClick={openDialog} />","_c","useClient","secretsId","FormField","{client, enabled}: {client: SanityClient; enabled: boolean}","{loading: true, cursor: null}","() => {\n if (!enabled) return\n\n const subscription = defer(() =>\n fetchMuxAssetsPage(\n client,\n // When we've already successfully loaded before (fully or partially), we start from the next cursor to avoid re-fetching\n 'data' in state && state.data && state.data.length > 0 && !state.error\n ? state.cursor\n : null,\n ),\n )\n .pipe(\n // Here we use \"expand\" to recursively fetch next pages\n expand((pageResult) => {\n // if fetched page has next_cursor, we continue emitting, requesting the next page\n // after 2s to avoid rate limiting\n if (hasMorePages(pageResult)) {\n return timer(2000).pipe(\n concatMap(() =>\n defer(() =>\n fetchMuxAssetsPage(\n client,\n 'next_cursor' in pageResult ? pageResult.next_cursor : null,\n ),\n ),\n ),\n )\n }\n\n // Else, we stop emitting\n return of()\n }),\n\n // On each iteration, persist intermediate states to give feedback to users\n tap((pageResult) =>\n setState((prevState) => accumulateIntermediateState(prevState, pageResult)),\n ),\n )\n .subscribe({\n // Once done, let the user know we've stopped loading\n complete: () => {\n setState((prev) => ({\n ...prev,\n loading: false,\n }))\n },\n })\n\n // Unsubscribe on component unmount to prevent memory leaks or fetching unnecessarily\n return () => subscription.unsubscribe()\n // oxlint-disable-next-line react/rule-suppression\n // oxlint-disable-next-line react/exhaustive-deps -- secrets/pluginConfig are stable for the asset fetch lifecycle once enabled\n }","pageResult","(prev) => ({\n ...prev,\n loading: false,\n })","[enabled]","_c","_temp","{\n client,\n enabled: hasSecrets && dialogOpen,\n }","hasSecrets && dialogOpen","assetsInSanity && muxAssets.data\n ? muxAssets.data.filter((a) => !assetExistsInSanity(a, assetsInSanity))\n : undefined","data","useMemo(() => {\n return assetsInSanity && muxAssets.data\n ? muxAssets.data.filter((a) => !assetExistsInSanity(a, assetsInSanity))\n : undefined\n }, [assetsInSanity, muxAssets.data])","[]","() => {\n if (importState !== 'importing') setImportState('closed')\n }","() => {\n if (importState === 'closed') setImportState('idle')\n }","async function importAssets() {\n setImportState('importing')\n const documents = selectedAssets.flatMap((asset) => muxAssetToSanityDocument(asset) || [])\n\n const tx = client.transaction()\n documents.forEach((doc) => tx.create(doc))\n\n try {\n await tx.commit({returnDocuments: false})\n setSelectedAssets([])\n setImportState('done')\n } catch (error) {\n setImportState('error')\n setImportError(error)\n }\n }","(asset) => muxAssetToSanityDocument(asset) || []","error","{\n assetsInSanityLoading,\n closeDialog,\n dialogOpen,\n importState,\n importError,\n hasSecrets,\n importAssets,\n missingAssets,\n muxAssets,\n openDialog,\n selectedAssets,\n setSelectedAssets,\n }","_c","useClient","_temp","options: IntersectionOptions = {}","() => {\n if (!ref.current) return\n\n const observer = new IntersectionObserver(([entry], obs) => {\n // ==== from react-intersection-observer ====\n // While it would be nice if you could just look at isIntersecting to determine if the component is inside the viewport, browsers can't agree on how to use it.\n // -Firefox ignores `threshold` when considering `isIntersecting`, so it will never be false again if `threshold` is > 0\n const nowInView =\n entry!.isIntersecting &&\n obs.thresholds.some((threshold) => entry!.intersectionRatio >= threshold)\n\n // Update our state when observer callback fires\n setInView(nowInView)\n options?.onChange?.(nowInView)\n }, options)\n\n const toObserve = ref.current\n observer.observe(toObserve)\n\n return () => {\n if (toObserve) observer.unobserve(toObserve)\n }\n }","[options, ref]","options?.onChange","ref.current","[entry]","_c","Image","useClient","_Fragment","{\n asset,\n selectAsset,\n selected,\n}: {\n asset: MuxAsset\n selectAsset: (selected: boolean) => void\n selected: boolean\n}","{position: 'relative'}","(e) => {\n selectAsset(e.currentTarget.checked)\n }","<MissingAssetCheckbox\n checked={selected}\n onChange={(e) => {\n selectAsset(e.currentTarget.checked)\n }}\n aria-label={selected ? `Import video ${asset.id}` : `Skip import of video ${asset.id}`}\n />","selected ? `Import video ${asset.id}` : `Skip import of video ${asset.id}`","asset.playback_ids.find((p) => p.id)?.id","playback_ids","(p) => p.id","<VideoThumbnail\n asset={{\n assetId: asset.id,\n data: asset,\n filename: asset.id,\n playbackId: asset.playback_ids.find((p) => p.id)?.id,\n }}\n width={150}\n />","asset.id","truncateString(asset.id, 15)","id","<Code size={2}>{truncateString(asset.id, 15)}</Code>","<Text muted size={2}>\n ({duration.formatted})\n </Text>","formatted","<Flex align=\"center\" gap={1}>\n <Code size={2}>{truncateString(asset.id, 15)}</Code>{' '}\n <Text muted size={2}>\n ({duration.formatted})\n </Text>\n </Flex>","new Date(Number(asset.created_at) * 1000).toLocaleDateString('en', {\n year: 'numeric',\n day: '2-digit',\n month: '2-digit',\n })","Number(asset.created_at) * 1000","<Text size={1}>\n Uploaded at{' '}\n {new Date(Number(asset.created_at) * 1000).toLocaleDateString('en', {\n year: 'numeric',\n day: '2-digit',\n month: '2-digit',\n })}\n </Text>","<Stack gap={2}>\n <Flex align=\"center\" gap={1}>\n <Code size={2}>{truncateString(asset.id, 15)}</Code>{' '}\n <Text muted size={2}>\n ({duration.formatted})\n </Text>\n </Flex>\n <Text size={1}>\n Uploaded at{' '}\n {new Date(Number(asset.created_at) * 1000).toLocaleDateString('en', {\n year: 'numeric',\n day: '2-digit',\n month: '2-digit',\n })}\n </Text>\n </Stack>","<Flex align=\"center\" gap={2}>\n <MissingAssetCheckbox\n checked={selected}\n onChange={(e) => {\n selectAsset(e.currentTarget.checked)\n }}\n aria-label={selected ? `Import video ${asset.id}` : `Skip import of video ${asset.id}`}\n />\n <VideoThumbnail\n asset={{\n assetId: asset.id,\n data: asset,\n filename: asset.id,\n playbackId: asset.playback_ids.find((p) => p.id)?.id,\n }}\n width={150}\n />\n <Stack gap={2}>\n <Flex align=\"center\" gap={1}>\n <Code size={2}>{truncateString(asset.id, 15)}</Code>{' '}\n <Text muted size={2}>\n ({duration.formatted})\n </Text>\n </Flex>\n <Text size={1}>\n Uploaded at{' '}\n {new Date(Number(asset.created_at) * 1000).toLocaleDateString('en', {\n year: 'numeric',\n day: '2-digit',\n month: '2-digit',\n })}\n </Text>\n </Stack>\n </Flex>","<Card\n key={asset.id}\n tone={selected ? 'positive' : undefined}\n border\n paddingX={2}\n paddingY={3}\n style={{position: 'relative'}}\n radius={1}\n >\n <Flex align=\"center\" gap={2}>\n <MissingAssetCheckbox\n checked={selected}\n onChange={(e) => {\n selectAsset(e.currentTarget.checked)\n }}\n aria-label={selected ? `Import video ${asset.id}` : `Skip import of video ${asset.id}`}\n />\n <VideoThumbnail\n asset={{\n assetId: asset.id,\n data: asset,\n filename: asset.id,\n playbackId: asset.playback_ids.find((p) => p.id)?.id,\n }}\n width={150}\n />\n <Stack gap={2}>\n <Flex align=\"center\" gap={1}>\n <Code size={2}>{truncateString(asset.id, 15)}</Code>{' '}\n <Text muted size={2}>\n ({duration.formatted})\n </Text>\n </Flex>\n <Text size={1}>\n Uploaded at{' '}\n {new Date(Number(asset.created_at) * 1000).toLocaleDateString('en', {\n year: 'numeric',\n day: '2-digit',\n month: '2-digit',\n })}\n </Text>\n </Stack>\n </Flex>\n </Card>","selected ? 'positive' : undefined","importState !== 'done' &&\n !noAssetsToImport && (\n <Card padding={3}>\n <Flex justify=\"space-between\" align=\"center\">\n <Button\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Cancel\"\n tone=\"critical\"\n onClick={props.closeDialog}\n disabled={isImporting}\n />\n {props.missingAssets && (\n <Button\n icon={RetrieveIcon}\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text={\n props.selectedAssets?.length > 0\n ? `Import ${props.selectedAssets.length} video(s)`\n : 'No video(s) selected'\n }\n tone=\"positive\"\n onClick={props.importAssets}\n iconRight={isImporting && Spinner}\n disabled={!canTriggerImport}\n />\n )}\n </Flex>\n </Card>\n )","closeDialog","importAssets","missingAssets","selectedAssets","props.muxAssets.hasSkippedAssetsWithoutPlayback && (\n <Card tone=\"caution\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <InfoOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Some videos were skipped\n </Text>\n <Text size={1}>\n Videos without playback IDs cannot be imported and have been excluded from the\n list.\n </Text>\n </Stack>\n </Flex>\n </Card>\n )","hasSkippedAssetsWithoutPlayback","(props.muxAssets.loading || props.assetsInSanityLoading) && (\n <Card tone=\"primary\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Loading assets from Mux\n </Text>\n <Text size={1}>\n This may take a while.\n {props.missingAssets &&\n props.missingAssets.length > 0 &&\n ` There are at least ${props.missingAssets.length} video${props.missingAssets.length > 1 ? 's' : ''} currently not in Sanity...`}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )","assetsInSanityLoading","loading","props.muxAssets.error && (\n <Card tone=\"critical\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error getting all data from Mux\n </Text>\n <Text size={1}>\n {props.missingAssets\n ? `But we've found ${props.missingAssets.length} video${props.missingAssets.length > 1 ? 's' : ''} not in Sanity, which you can start importing now.`\n : 'Please try again or contact a developer for help.'}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )","error","importState === 'importing' && (\n <Card tone=\"primary\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Importing {props.selectedAssets.length} video\n {props.selectedAssets.length > 1 && 's'} from Mux\n </Text>\n </Stack>\n </Flex>\n </Card>\n )","importState === 'error' && (\n <Card tone=\"critical\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error importing videos\n </Text>\n <Text size={1}>\n {props.importError\n ? `Error: ${props.importError}`\n : 'Please try again or contact a developer for help.'}\n </Text>\n <Box marginTop={1}>\n <Button\n icon={RetryIcon}\n text=\"Retry\"\n tone=\"primary\"\n onClick={props.importAssets}\n />\n </Box>\n </Stack>\n </Flex>\n </Card>\n )","importError","(noAssetsToImport || importState === 'done') && (\n <Stack paddingY={5} marginBottom={4} gap={3} style={{textAlign: 'center'}}>\n <Box>\n <CheckmarkCircleIcon fontSize={48} />\n </Box>\n <Heading size={2}>\n {importState === 'done'\n ? `Videos imported successfully`\n : 'There are no Mux videos to import'}\n </Heading>\n <Text size={2}>\n {importState === 'done'\n ? 'You can now use them in your Sanity content.'\n : \"They're all in Sanity and ready to be used in your content.\"}\n </Text>\n </Stack>\n )","props.missingAssets &&\n props.missingAssets.length > 0 &&\n (importState === 'idle' || importState === 'error') && (\n <Stack gap={4}>\n <Heading size={1}>\n There are {props.missingAssets.length}\n {props.muxAssets.loading && '+'} Mux video{props.missingAssets.length > 1 && 's'}{' '}\n not in Sanity\n </Heading>\n {!props.muxAssets.loading && (\n <Flex align=\"center\" paddingX={2}>\n <Checkbox\n id=\"import-all\"\n style={{display: 'block'}}\n onClick={(e) => {\n const selectAll = e.currentTarget.checked\n if (selectAll) {\n // eslint-disable-next-line no-unused-expressions\n props.missingAssets && props.setSelectedAssets(props.missingAssets)\n } else {\n props.setSelectedAssets([])\n }\n }}\n checked={props.selectedAssets.length === props.missingAssets.length}\n />\n <Box flex={1} paddingLeft={3} as=\"label\" htmlFor=\"import-all\">\n <Text>Import all</Text>\n </Box>\n </Flex>\n )}\n {props.missingAssets.map((asset) => (\n <MissingAsset\n key={asset.id}\n asset={asset}\n selectAsset={(selected) => {\n if (selected) {\n props.setSelectedAssets([...props.selectedAssets, asset])\n } else {\n props.setSelectedAssets(props.selectedAssets.filter((a) => a.id !== asset.id))\n }\n }}\n selected={props.selectedAssets.some((a) => a.id === asset.id)}\n />\n ))}\n </Stack>\n )","props.missingAssets","a","<Box padding={3}>\n {/* WARNING: SKIPPED ASSETS WITHOUT PLAYBACK */}\n {props.muxAssets.hasSkippedAssetsWithoutPlayback && (\n <Card tone=\"caution\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <InfoOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Some videos were skipped\n </Text>\n <Text size={1}>\n Videos without playback IDs cannot be imported and have been excluded from the\n list.\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* LOADING ASSETS STATE */}\n {(props.muxAssets.loading || props.assetsInSanityLoading) && (\n <Card tone=\"primary\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Loading assets from Mux\n </Text>\n <Text size={1}>\n This may take a while.\n {props.missingAssets &&\n props.missingAssets.length > 0 &&\n ` There are at least ${props.missingAssets.length} video${props.missingAssets.length > 1 ? 's' : ''} currently not in Sanity...`}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR LOADING MUX */}\n {props.muxAssets.error && (\n <Card tone=\"critical\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error getting all data from Mux\n </Text>\n <Text size={1}>\n {props.missingAssets\n ? `But we've found ${props.missingAssets.length} video${props.missingAssets.length > 1 ? 's' : ''} not in Sanity, which you can start importing now.`\n : 'Please try again or contact a developer for help.'}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* IMPORTING STATE */}\n {importState === 'importing' && (\n <Card tone=\"primary\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Importing {props.selectedAssets.length} video\n {props.selectedAssets.length > 1 && 's'} from Mux\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR IMPORTING */}\n {importState === 'error' && (\n <Card tone=\"critical\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error importing videos\n </Text>\n <Text size={1}>\n {props.importError\n ? `Error: ${props.importError}`\n : 'Please try again or contact a developer for help.'}\n </Text>\n <Box marginTop={1}>\n <Button\n icon={RetryIcon}\n text=\"Retry\"\n tone=\"primary\"\n onClick={props.importAssets}\n />\n </Box>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* NO ASSETS TO IMPORT or SUCESS STATE */}\n {(noAssetsToImport || importState === 'done') && (\n <Stack paddingY={5} marginBottom={4} gap={3} style={{textAlign: 'center'}}>\n <Box>\n <CheckmarkCircleIcon fontSize={48} />\n </Box>\n <Heading size={2}>\n {importState === 'done'\n ? `Videos imported successfully`\n : 'There are no Mux videos to import'}\n </Heading>\n <Text size={2}>\n {importState === 'done'\n ? 'You can now use them in your Sanity content.'\n : \"They're all in Sanity and ready to be used in your content.\"}\n </Text>\n </Stack>\n )}\n\n {/* MISSING ASSETS SELECTOR */}\n {props.missingAssets &&\n props.missingAssets.length > 0 &&\n (importState === 'idle' || importState === 'error') && (\n <Stack gap={4}>\n <Heading size={1}>\n There are {props.missingAssets.length}\n {props.muxAssets.loading && '+'} Mux video{props.missingAssets.length > 1 && 's'}{' '}\n not in Sanity\n </Heading>\n {!props.muxAssets.loading && (\n <Flex align=\"center\" paddingX={2}>\n <Checkbox\n id=\"import-all\"\n style={{display: 'block'}}\n onClick={(e) => {\n const selectAll = e.currentTarget.checked\n if (selectAll) {\n // eslint-disable-next-line no-unused-expressions\n props.missingAssets && props.setSelectedAssets(props.missingAssets)\n } else {\n props.setSelectedAssets([])\n }\n }}\n checked={props.selectedAssets.length === props.missingAssets.length}\n />\n <Box flex={1} paddingLeft={3} as=\"label\" htmlFor=\"import-all\">\n <Text>Import all</Text>\n </Box>\n </Flex>\n )}\n {props.missingAssets.map((asset) => (\n <MissingAsset\n key={asset.id}\n asset={asset}\n selectAsset={(selected) => {\n if (selected) {\n props.setSelectedAssets([...props.selectedAssets, asset])\n } else {\n props.setSelectedAssets(props.selectedAssets.filter((a) => a.id !== asset.id))\n }\n }}\n selected={props.selectedAssets.some((a) => a.id === asset.id)}\n />\n ))}\n </Stack>\n )}\n </Box>","<Dialog\n animate\n header={'Import videos from Mux'}\n zOffset={DIALOGS_Z_INDEX}\n id=\"video-details-dialog\"\n onClose={props.closeDialog}\n onClickOutside={props.closeDialog}\n width={1}\n position=\"fixed\"\n footer={\n importState !== 'done' &&\n !noAssetsToImport && (\n <Card padding={3}>\n <Flex justify=\"space-between\" align=\"center\">\n <Button\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Cancel\"\n tone=\"critical\"\n onClick={props.closeDialog}\n disabled={isImporting}\n />\n {props.missingAssets && (\n <Button\n icon={RetrieveIcon}\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text={\n props.selectedAssets?.length > 0\n ? `Import ${props.selectedAssets.length} video(s)`\n : 'No video(s) selected'\n }\n tone=\"positive\"\n onClick={props.importAssets}\n iconRight={isImporting && Spinner}\n disabled={!canTriggerImport}\n />\n )}\n </Flex>\n </Card>\n )\n }\n >\n <Box padding={3}>\n {/* WARNING: SKIPPED ASSETS WITHOUT PLAYBACK */}\n {props.muxAssets.hasSkippedAssetsWithoutPlayback && (\n <Card tone=\"caution\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <InfoOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Some videos were skipped\n </Text>\n <Text size={1}>\n Videos without playback IDs cannot be imported and have been excluded from the\n list.\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* LOADING ASSETS STATE */}\n {(props.muxAssets.loading || props.assetsInSanityLoading) && (\n <Card tone=\"primary\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Loading assets from Mux\n </Text>\n <Text size={1}>\n This may take a while.\n {props.missingAssets &&\n props.missingAssets.length > 0 &&\n ` There are at least ${props.missingAssets.length} video${props.missingAssets.length > 1 ? 's' : ''} currently not in Sanity...`}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR LOADING MUX */}\n {props.muxAssets.error && (\n <Card tone=\"critical\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error getting all data from Mux\n </Text>\n <Text size={1}>\n {props.missingAssets\n ? `But we've found ${props.missingAssets.length} video${props.missingAssets.length > 1 ? 's' : ''} not in Sanity, which you can start importing now.`\n : 'Please try again or contact a developer for help.'}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* IMPORTING STATE */}\n {importState === 'importing' && (\n <Card tone=\"primary\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Importing {props.selectedAssets.length} video\n {props.selectedAssets.length > 1 && 's'} from Mux\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR IMPORTING */}\n {importState === 'error' && (\n <Card tone=\"critical\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error importing videos\n </Text>\n <Text size={1}>\n {props.importError\n ? `Error: ${props.importError}`\n : 'Please try again or contact a developer for help.'}\n </Text>\n <Box marginTop={1}>\n <Button\n icon={RetryIcon}\n text=\"Retry\"\n tone=\"primary\"\n onClick={props.importAssets}\n />\n </Box>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* NO ASSETS TO IMPORT or SUCESS STATE */}\n {(noAssetsToImport || importState === 'done') && (\n <Stack paddingY={5} marginBottom={4} gap={3} style={{textAlign: 'center'}}>\n <Box>\n <CheckmarkCircleIcon fontSize={48} />\n </Box>\n <Heading size={2}>\n {importState === 'done'\n ? `Videos imported successfully`\n : 'There are no Mux videos to import'}\n </Heading>\n <Text size={2}>\n {importState === 'done'\n ? 'You can now use them in your Sanity content.'\n : \"They're all in Sanity and ready to be used in your content.\"}\n </Text>\n </Stack>\n )}\n\n {/* MISSING ASSETS SELECTOR */}\n {props.missingAssets &&\n props.missingAssets.length > 0 &&\n (importState === 'idle' || importState === 'error') && (\n <Stack gap={4}>\n <Heading size={1}>\n There are {props.missingAssets.length}\n {props.muxAssets.loading && '+'} Mux video{props.missingAssets.length > 1 && 's'}{' '}\n not in Sanity\n </Heading>\n {!props.muxAssets.loading && (\n <Flex align=\"center\" paddingX={2}>\n <Checkbox\n id=\"import-all\"\n style={{display: 'block'}}\n onClick={(e) => {\n const selectAll = e.currentTarget.checked\n if (selectAll) {\n // eslint-disable-next-line no-unused-expressions\n props.missingAssets && props.setSelectedAssets(props.missingAssets)\n } else {\n props.setSelectedAssets([])\n }\n }}\n checked={props.selectedAssets.length === props.missingAssets.length}\n />\n <Box flex={1} paddingLeft={3} as=\"label\" htmlFor=\"import-all\">\n <Text>Import all</Text>\n </Box>\n </Flex>\n )}\n {props.missingAssets.map((asset) => (\n <MissingAsset\n key={asset.id}\n asset={asset}\n selectAsset={(selected) => {\n if (selected) {\n props.setSelectedAssets([...props.selectedAssets, asset])\n } else {\n props.setSelectedAssets(props.selectedAssets.filter((a) => a.id !== asset.id))\n }\n }}\n selected={props.selectedAssets.some((a) => a.id === asset.id)}\n />\n ))}\n </Stack>\n )}\n </Box>\n </Dialog>","<ImportVideosDialog {...importAssets} />","<Button mode=\"bleed\" text=\"Import from Mux\" onClick={importAssets.openDialog} />","openDialog","_c","_temp","() => {\n // Constraint in bounds.\n const clamped = Math.min(props.total - 1, Math.max(0, page))\n if (page !== clamped) {\n setPage(clamped)\n }\n }","[page, props.total, setPage]","total","{cursor: 'pointer'}","() => {\n setPage((p) => {\n return Math.min(props.total - 1, Math.max(0, p - 1))\n })\n }","<Button\n icon={ChevronLeftIcon}\n mode=\"bleed\"\n padding={3}\n style={{cursor: 'pointer'}}\n disabled={page <= 0}\n onClick={() => {\n setPage((p) => {\n return Math.min(props.total - 1, Math.max(0, p - 1))\n })\n }}\n />","page <= 0","<Label muted>\n Page {page + 1}/{props.total}\n </Label>","page + 1","() => {\n setPage((p) => {\n return Math.min(props.total - 1, Math.max(0, p + 1))\n })\n }","p","<Button\n icon={ChevronRightIcon}\n mode=\"bleed\"\n padding={3}\n style={{cursor: 'pointer'}}\n disabled={page >= props.total - 1}\n onClick={() => {\n setPage((p) => {\n return Math.min(props.total - 1, Math.max(0, p + 1))\n })\n }}\n />","page >= props.total - 1","<>\n <Button\n icon={ChevronLeftIcon}\n mode=\"bleed\"\n padding={3}\n style={{cursor: 'pointer'}}\n disabled={page <= 0}\n onClick={() => {\n setPage((p) => {\n return Math.min(props.total - 1, Math.max(0, p - 1))\n })\n }}\n />\n <Label muted>\n Page {page + 1}/{props.total}\n </Label>\n <Button\n icon={ChevronRightIcon}\n mode=\"bleed\"\n padding={3}\n style={{cursor: 'pointer'}}\n disabled={page >= props.total - 1}\n onClick={() => {\n setPage((p) => {\n return Math.min(props.total - 1, Math.max(0, p + 1))\n })\n }}\n />\n </>","_c","_Fragment","{\n client,\n enabled: hasSecrets && dialogOpen,\n }","hasSecrets && dialogOpen","sanityAssets && muxAssets.data\n ? sanityAssets.map((sanityDoc) => {\n const muxAsset = muxAssets.data?.find(\n (m) => m.id === sanityDoc.assetId || m.id === sanityDoc.data?.id,\n )\n return {\n sanityDoc,\n muxAsset,\n muxTitle: muxAsset?.meta?.title,\n currentTitle: sanityDoc.filename,\n }\n })\n : undefined","data","useMemo(() => {\n return sanityAssets && muxAssets.data\n ? sanityAssets.map((sanityDoc) => {\n const muxAsset = muxAssets.data?.find(\n (m) => m.id === sanityDoc.assetId || m.id === sanityDoc.data?.id,\n )\n return {\n sanityDoc,\n muxAsset,\n muxTitle: muxAsset?.meta?.title,\n currentTitle: sanityDoc.filename,\n }\n })\n : undefined\n }, [sanityAssets, muxAssets.data])","() => {\n if (resyncState !== 'syncing') setResyncState('closed')\n }","() => {\n if (resyncState === 'closed') setResyncState('idle')\n }","async function syncAllVideos() {\n if (!matchedAssets) return\n\n setResyncState('syncing')\n\n try {\n const tx = client.transaction()\n\n matchedAssets.forEach((matched) => {\n // Update all videos with the Mux title, even if it's undefined/empty\n const newTitle = matched.muxTitle || ''\n tx.patch(matched.sanityDoc._id, {set: {filename: newTitle}})\n })\n\n await tx.commit({returnDocuments: false})\n setResyncState('done')\n } catch (error) {\n setResyncState('error')\n setResyncError(error)\n }\n }","error","async function syncOnlyEmpty() {\n if (!matchedAssets) return\n\n setResyncState('syncing')\n\n try {\n const tx = client.transaction()\n\n matchedAssets.forEach((matched) => {\n // Only update if the current title is empty or has the placeholder format\n // AND there's a new title available from Mux\n if (\n matched.muxAsset &&\n matched.muxTitle &&\n isEmptyOrPlaceholderTitle(matched.currentTitle, matched.muxAsset.id)\n ) {\n tx.patch(matched.sanityDoc._id, {set: {filename: matched.muxTitle}})\n }\n })\n\n await tx.commit({returnDocuments: false})\n setResyncState('done')\n } catch (error) {\n setResyncState('error')\n setResyncError(error)\n }\n }","tx","matched","async function syncFullData() {\n if (!matchedAssets) return\n\n setResyncState('syncing')\n\n try {\n const tx = client.transaction()\n\n matchedAssets.forEach((matched) => {\n if (!matched.muxAsset) return\n\n const dataWithKeys = addKeysToMuxData(matched.muxAsset)\n\n // Update all fields: filename, status, and full data from Mux\n tx.patch(matched.sanityDoc._id, {\n set: {\n filename: matched.muxTitle || matched.currentTitle || '',\n status: matched.muxAsset.status,\n data: dataWithKeys,\n },\n })\n })\n\n await tx.commit({returnDocuments: false})\n setResyncState('done')\n } catch (error) {\n setResyncState('error')\n setResyncError(error)\n }\n }","{\n sanityAssetsLoading,\n closeDialog,\n dialogOpen,\n resyncState,\n resyncError,\n hasSecrets,\n syncAllVideos,\n syncOnlyEmpty,\n syncFullData,\n matchedAssets,\n muxAssets,\n openDialog,\n }","_c","useClient","{\n id,\n selected,\n onSelect,\n title,\n count,\n description,\n disabled,\n}: OptionCardProps","{\n cursor: disabled ? 'not-allowed' : 'pointer',\n opacity: disabled ? 0.5 : 1,\n }","disabled ? 'not-allowed' : 'pointer'","disabled ? 0.5 : 1","() => onSelect(id)","<Box paddingTop={1}>\n <Radio\n checked={selected}\n onChange={() => onSelect(id)}\n disabled={disabled}\n name=\"sync-option\"\n />\n </Box>","<Flex align=\"center\" gap={2}>\n <Text size={2} weight=\"semibold\">\n {title} ({count})\n </Text>\n </Flex>","<Text size={1} muted>\n {description}\n </Text>","<Stack gap={2} flex={1}>\n <Flex align=\"center\" gap={2}>\n <Text size={2} weight=\"semibold\">\n {title} ({count})\n </Text>\n </Flex>\n <Text size={1} muted>\n {description}\n </Text>\n </Stack>","<Flex gap={3} align=\"flex-start\">\n <Box paddingTop={1}>\n <Radio\n checked={selected}\n onChange={() => onSelect(id)}\n disabled={disabled}\n name=\"sync-option\"\n />\n </Box>\n <Stack gap={2} flex={1}>\n <Flex align=\"center\" gap={2}>\n <Text size={2} weight=\"semibold\">\n {title} ({count})\n </Text>\n </Flex>\n <Text size={1} muted>\n {description}\n </Text>\n </Stack>\n </Flex>","<Card\n as=\"label\"\n padding={3}\n radius={2}\n border\n tone={selected ? 'primary' : 'default'}\n style={{\n cursor: disabled ? 'not-allowed' : 'pointer',\n opacity: disabled ? 0.5 : 1,\n }}\n >\n <Flex gap={3} align=\"flex-start\">\n <Box paddingTop={1}>\n <Radio\n checked={selected}\n onChange={() => onSelect(id)}\n disabled={disabled}\n name=\"sync-option\"\n />\n </Box>\n <Stack gap={2} flex={1}>\n <Flex align=\"center\" gap={2}>\n <Text size={2} weight=\"semibold\">\n {title} ({count})\n </Text>\n </Flex>\n <Text size={1} muted>\n {description}\n </Text>\n </Stack>\n </Flex>\n </Card>","selected ? 'primary' : 'default'","props.matchedAssets?.filter((m) => m.muxAsset).length || 0","matchedAssets","(m) => m.muxAsset","props.matchedAssets?.filter(\n (m) => m.muxAsset && m.muxTitle && isEmptyOrPlaceholderTitle(m.currentTitle, m.muxAsset.id),\n ).length || 0","(m) => m.muxAsset && m.muxTitle && isEmptyOrPlaceholderTitle(m.currentTitle, m.muxAsset.id)","() => {\n switch (selectedOption) {\n case 'fillEmpty':\n void props.syncOnlyEmpty()\n break\n case 'syncTitles':\n void props.syncAllVideos()\n break\n case 'fullResync':\n void props.syncFullData()\n break\n default:\n break\n }\n }","!isDone && (\n <Card padding={3}>\n <Flex justify=\"flex-end\" gap={2}>\n <Button\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Cancel\"\n onClick={props.closeDialog}\n disabled={isResyncing}\n />\n <Button\n icon={SyncIcon}\n fontSize={2}\n padding={3}\n text=\"Run sync\"\n tone=\"primary\"\n onClick={handleSync}\n iconRight={isResyncing && Spinner}\n disabled={!canTriggerResync || isLoading}\n />\n </Flex>\n </Card>\n )","closeDialog","isLoading && (\n <Card tone=\"primary\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Loading assets from Mux\n </Text>\n <Text size={1} muted>\n This may take a while.\n </Text>\n </Stack>\n </Flex>\n </Card>\n )","props.muxAssets.error && (\n <Card tone=\"critical\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error getting data from Mux\n </Text>\n <Text size={1}>Please try again or contact a developer for help.</Text>\n </Stack>\n </Flex>\n </Card>\n )","error","resyncState === 'syncing' && (\n <Card tone=\"primary\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Syncing metadata\n </Text>\n <Text size={1} muted>\n Updating videos from Mux...\n </Text>\n </Stack>\n </Flex>\n </Card>\n )","resyncState === 'error' && (\n <Card tone=\"critical\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error syncing metadata\n </Text>\n <Text size={1}>\n {props.resyncError\n ? `Error: ${props.resyncError}`\n : 'Please try again or contact a developer for help.'}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )","resyncError","resyncState === 'done' && (\n <Stack paddingY={5} gap={3} style={{textAlign: 'center'}}>\n <Box>\n <CheckmarkCircleIcon fontSize={48} />\n </Box>\n <Heading size={2}>Sync completed</Heading>\n <Text size={2} muted>\n Videos have been updated from Mux.\n </Text>\n </Stack>\n )","!isDone && !isLoading && !props.muxAssets.error && (\n <Stack gap={4}>\n <Text size={1} muted>\n Found {videosToUpdate} video{videosToUpdate === 1 ? '' : 's'} linked to Mux.\n </Text>\n\n <Stack gap={3}>\n {hasEmptyTitles && (\n <OptionCard\n id=\"fillEmpty\"\n selected={selectedOption === 'fillEmpty'}\n onSelect={setSelectedOption}\n title=\"Fill missing titles only\"\n count={videosWithEmptyOrPlaceholder}\n description=\"Updates only videos without a title or with placeholder titles (e.g., 'Asset #123') using the title from Mux.\"\n disabled={isResyncing}\n />\n )}\n\n <OptionCard\n id=\"syncTitles\"\n selected={selectedOption === 'syncTitles'}\n onSelect={setSelectedOption}\n title=\"Sync all titles\"\n count={videosToUpdate}\n description=\"Replaces the title in Sanity with the title from Mux for all videos.\"\n disabled={isResyncing}\n />\n\n <OptionCard\n id=\"fullResync\"\n selected={selectedOption === 'fullResync'}\n onSelect={setSelectedOption}\n title=\"Full resync\"\n count={videosToUpdate}\n description=\"Updates all fields from Mux including status, duration, tracks, captions, and renditions.\"\n disabled={isResyncing}\n />\n </Stack>\n </Stack>\n )","<Box padding={4}>\n {/* LOADING ASSETS STATE */}\n {isLoading && (\n <Card tone=\"primary\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Loading assets from Mux\n </Text>\n <Text size={1} muted>\n This may take a while.\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR LOADING MUX */}\n {props.muxAssets.error && (\n <Card tone=\"critical\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error getting data from Mux\n </Text>\n <Text size={1}>Please try again or contact a developer for help.</Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* SYNCING STATE */}\n {resyncState === 'syncing' && (\n <Card tone=\"primary\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Syncing metadata\n </Text>\n <Text size={1} muted>\n Updating videos from Mux...\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR SYNCING */}\n {resyncState === 'error' && (\n <Card tone=\"critical\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error syncing metadata\n </Text>\n <Text size={1}>\n {props.resyncError\n ? `Error: ${props.resyncError}`\n : 'Please try again or contact a developer for help.'}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* SUCCESS STATE */}\n {resyncState === 'done' && (\n <Stack paddingY={5} gap={3} style={{textAlign: 'center'}}>\n <Box>\n <CheckmarkCircleIcon fontSize={48} />\n </Box>\n <Heading size={2}>Sync completed</Heading>\n <Text size={2} muted>\n Videos have been updated from Mux.\n </Text>\n </Stack>\n )}\n\n {/* OPTIONS */}\n {!isDone && !isLoading && !props.muxAssets.error && (\n <Stack gap={4}>\n <Text size={1} muted>\n Found {videosToUpdate} video{videosToUpdate === 1 ? '' : 's'} linked to Mux.\n </Text>\n\n <Stack gap={3}>\n {hasEmptyTitles && (\n <OptionCard\n id=\"fillEmpty\"\n selected={selectedOption === 'fillEmpty'}\n onSelect={setSelectedOption}\n title=\"Fill missing titles only\"\n count={videosWithEmptyOrPlaceholder}\n description=\"Updates only videos without a title or with placeholder titles (e.g., 'Asset #123') using the title from Mux.\"\n disabled={isResyncing}\n />\n )}\n\n <OptionCard\n id=\"syncTitles\"\n selected={selectedOption === 'syncTitles'}\n onSelect={setSelectedOption}\n title=\"Sync all titles\"\n count={videosToUpdate}\n description=\"Replaces the title in Sanity with the title from Mux for all videos.\"\n disabled={isResyncing}\n />\n\n <OptionCard\n id=\"fullResync\"\n selected={selectedOption === 'fullResync'}\n onSelect={setSelectedOption}\n title=\"Full resync\"\n count={videosToUpdate}\n description=\"Updates all fields from Mux including status, duration, tracks, captions, and renditions.\"\n disabled={isResyncing}\n />\n </Stack>\n </Stack>\n )}\n </Box>","<Dialog\n animate\n header=\"Sync with Mux\"\n zOffset={DIALOGS_Z_INDEX}\n id=\"resync-metadata-dialog\"\n onClose={props.closeDialog}\n onClickOutside={props.closeDialog}\n width={1}\n position=\"fixed\"\n footer={\n !isDone && (\n <Card padding={3}>\n <Flex justify=\"flex-end\" gap={2}>\n <Button\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Cancel\"\n onClick={props.closeDialog}\n disabled={isResyncing}\n />\n <Button\n icon={SyncIcon}\n fontSize={2}\n padding={3}\n text=\"Run sync\"\n tone=\"primary\"\n onClick={handleSync}\n iconRight={isResyncing && Spinner}\n disabled={!canTriggerResync || isLoading}\n />\n </Flex>\n </Card>\n )\n }\n >\n <Box padding={4}>\n {/* LOADING ASSETS STATE */}\n {isLoading && (\n <Card tone=\"primary\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Loading assets from Mux\n </Text>\n <Text size={1} muted>\n This may take a while.\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR LOADING MUX */}\n {props.muxAssets.error && (\n <Card tone=\"critical\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error getting data from Mux\n </Text>\n <Text size={1}>Please try again or contact a developer for help.</Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* SYNCING STATE */}\n {resyncState === 'syncing' && (\n <Card tone=\"primary\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Syncing metadata\n </Text>\n <Text size={1} muted>\n Updating videos from Mux...\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR SYNCING */}\n {resyncState === 'error' && (\n <Card tone=\"critical\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error syncing metadata\n </Text>\n <Text size={1}>\n {props.resyncError\n ? `Error: ${props.resyncError}`\n : 'Please try again or contact a developer for help.'}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* SUCCESS STATE */}\n {resyncState === 'done' && (\n <Stack paddingY={5} gap={3} style={{textAlign: 'center'}}>\n <Box>\n <CheckmarkCircleIcon fontSize={48} />\n </Box>\n <Heading size={2}>Sync completed</Heading>\n <Text size={2} muted>\n Videos have been updated from Mux.\n </Text>\n </Stack>\n )}\n\n {/* OPTIONS */}\n {!isDone && !isLoading && !props.muxAssets.error && (\n <Stack gap={4}>\n <Text size={1} muted>\n Found {videosToUpdate} video{videosToUpdate === 1 ? '' : 's'} linked to Mux.\n </Text>\n\n <Stack gap={3}>\n {hasEmptyTitles && (\n <OptionCard\n id=\"fillEmpty\"\n selected={selectedOption === 'fillEmpty'}\n onSelect={setSelectedOption}\n title=\"Fill missing titles only\"\n count={videosWithEmptyOrPlaceholder}\n description=\"Updates only videos without a title or with placeholder titles (e.g., 'Asset #123') using the title from Mux.\"\n disabled={isResyncing}\n />\n )}\n\n <OptionCard\n id=\"syncTitles\"\n selected={selectedOption === 'syncTitles'}\n onSelect={setSelectedOption}\n title=\"Sync all titles\"\n count={videosToUpdate}\n description=\"Replaces the title in Sanity with the title from Mux for all videos.\"\n disabled={isResyncing}\n />\n\n <OptionCard\n id=\"fullResync\"\n selected={selectedOption === 'fullResync'}\n onSelect={setSelectedOption}\n title=\"Full resync\"\n count={videosToUpdate}\n description=\"Updates all fields from Mux including status, duration, tracks, captions, and renditions.\"\n disabled={isResyncing}\n />\n </Stack>\n </Stack>\n )}\n </Box>\n </Dialog>","m","<ResyncMetadataDialog {...resyncMetadata} />","<Button mode=\"bleed\" text=\"Sync with Mux\" onClick={resyncMetadata.openDialog} />","openDialog","_c","_temp","_temp2","<Button text=\"Sort\" icon={SortIcon} mode=\"bleed\" padding={3} style={{cursor: 'pointer'}} />","Object.entries(ASSET_SORT_OPTIONS)","<Menu>\n {Object.entries(ASSET_SORT_OPTIONS).map(([type, {label}]) => (\n <MenuItem\n key={type}\n data-as=\"button\"\n onClick={() => props.setSort(type as SortOption)}\n padding={3}\n tone=\"default\"\n text={label}\n pressed={type === props.sort}\n />\n ))}\n </Menu>","{label}","[type, {label}]","<MenuButton\n button={\n <Button text=\"Sort\" icon={SortIcon} mode=\"bleed\" padding={3} style={{cursor: 'pointer'}} />\n }\n id={id}\n menu={\n <Menu>\n {Object.entries(ASSET_SORT_OPTIONS).map(([type, {label}]) => (\n <MenuItem\n key={type}\n data-as=\"button\"\n onClick={() => props.setSort(type as SortOption)}\n padding={3}\n tone=\"default\"\n text={label}\n pressed={type === props.sort}\n />\n ))}\n </Menu>\n }\n popover={CONTEXT_MENU_POPOVER_PROPS}\n />","_c","<Box\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: '150px',\n }}\n >\n <Spinner />\n </Box>","_c","<Icon />","<Text size={(props.size || 1) + 1} muted>\n <Icon />\n </Text>","(props.size || 1) + 1","<Text size={props.size || 1} muted={props.muted}>\n {props.text}\n </Text>","muted","text","props.size || 1","<Flex gap={2} align=\"center\" padding={1}>\n <Text size={(props.size || 1) + 1} muted>\n <Icon />\n </Text>\n <Text size={props.size || 1} muted={props.muted}>\n {props.text}\n </Text>\n </Flex>","_c","<path\n fill=\"currentColor\"\n d=\"M20 9V6h-3V4h5v5h-2ZM2 9V4h5v2H4v3H2Zm15 11v-2h3v-3h2v5h-5ZM2 20v-5h2v3h3v2H2Zm4-4V8h12v8H6Zm2-2h8v-4H8v4Zm0 0v-4v4Z\"\n />","<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\" {...props}>\n <path\n fill=\"currentColor\"\n d=\"M20 9V6h-3V4h5v5h-2ZM2 9V4h5v2H4v3H2Zm15 11v-2h3v-3h2v5h-5ZM2 20v-5h2v3h3v2H2Zm4-4V8h12v8H6Zm2-2h8v-4H8v4Zm0 0v-4v4Z\"\n />\n </svg>","_c","<path d=\"M232 306.667h48V176h-48v130.667z\" fill=\"currentColor\" />","<path\n d=\"M407.67 170.271l30.786-30.786-33.942-33.941-30.785 30.786C341.217 111.057 300.369 96 256 96 149.961 96 64 181.961 64 288s85.961 192 192 192 192-85.961 192-192c0-44.369-15.057-85.217-40.33-117.729zm-45.604 223.795C333.734 422.398 296.066 438 256 438s-77.735-15.602-106.066-43.934C121.602 365.735 106 328.066 106 288s15.602-77.735 43.934-106.066C178.265 153.602 215.934 138 256 138s77.734 15.602 106.066 43.934C390.398 210.265 406 247.934 406 288s-15.602 77.735-43.934 106.066z\"\n fill=\"currentColor\"\n />","<path d=\"M192 32h128v48H192z\" fill=\"currentColor\" />","<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 512 512\"\n {...props}\n >\n <path d=\"M232 306.667h48V176h-48v130.667z\" fill=\"currentColor\" />\n <path\n d=\"M407.67 170.271l30.786-30.786-33.942-33.941-30.785 30.786C341.217 111.057 300.369 96 256 96 149.961 96 64 181.961 64 288s85.961 192 192 192 192-85.961 192-192c0-44.369-15.057-85.217-40.33-117.729zm-45.604 223.795C333.734 422.398 296.066 438 256 438s-77.735-15.602-106.066-43.934C121.602 365.735 106 328.066 106 288s15.602-77.735 43.934-106.066C178.265 153.602 215.934 138 256 138s77.734 15.602 106.066 43.934C390.398 210.265 406 247.934 406 288s-15.602 77.735-43.934 106.066z\"\n fill=\"currentColor\"\n />\n <path d=\"M192 32h128v48H192z\" fill=\"currentColor\" />\n </svg>","_c","useClient","<Stack gap={3}>\n <Text size={1} muted>\n When you enable the mezzanine file, Mux creates a copy equivalent in quality to your\n original video — ideal for offline editing or archiving. Unlike the streamable MP4 (static)\n renditions, it is not meant for streaming.\n </Text>\n <Text size={1} muted>\n The file is prepared in the background and may take a few minutes depending on the\n asset's duration and resolution. Enabling is free and the download stays available for\n 24 hours.\n </Text>\n </Stack>","_c","{asset, withExplanation = true}: Props","withExplanation = true","<Label muted size={1}>\n Mezzanine\n </Label>","<Flex align=\"center\" justify=\"space-between\" gap={3}>\n <Label muted size={1}>\n Mezzanine\n </Label>\n <Text size={1}>\n <a href={MEZZANINE_LEARN_MORE_URL} target=\"_blank\" rel=\"noopener noreferrer\">\n Learn more\n </a>\n </Text>\n </Flex>","<Text size={1} muted={!isReady}>\n mezzanine.mp4\n </Text>","!isReady","resolution && (\n <Text size={1} muted>\n {resolution}\n </Text>\n )","<Stack gap={2}>\n <Text size={1} muted={!isReady}>\n mezzanine.mp4\n </Text>\n {resolution && (\n <Text size={1} muted>\n {resolution}\n </Text>\n )}\n </Stack>","withExplanation && showExplanation && <MezzanineExplanation />","showExplanation && (expired || status === 'errored') && (\n <Stack gap={2}>\n {expired && (\n <Text size={1} muted>\n The previous mezzanine file expired. Enable it again to download.\n </Text>\n )}\n {status === 'errored' && (\n <Text size={1} style={{color: 'var(--card-critical-color)'}}>\n Mux could not prepare the mezzanine file. Please try again.\n </Text>\n )}\n </Stack>\n )","isPreparing && (\n <Text size={1} muted>\n Preparing the mezzanine file… this can take a few minutes. You can close this and come\n back later.\n </Text>\n )","isReady && (\n <Text size={1} muted>\n Ready to download. The link stays available for about 24 hours.\n </Text>\n )","<Flex justify=\"flex-end\" gap={2}>\n {isPreparing ? (\n <Flex align=\"center\" gap={2}>\n <Spinner muted size={1} />\n <Text size={1} muted>\n Preparing…\n </Text>\n </Flex>\n ) : isReady ? (\n <Button\n icon={DownloadIcon}\n text=\"Download\"\n tone=\"positive\"\n fontSize={1}\n padding={3}\n loading={busy}\n disabled={busy}\n onClick={() => void download()}\n />\n ) : (\n <Button\n text={status === 'errored' ? 'Try again' : 'Enable'}\n tone=\"primary\"\n fontSize={1}\n padding={3}\n loading={busy}\n disabled={busy || !assetReady}\n onClick={() => void enable()}\n />\n )}\n </Flex>","<Card padding={3} radius={2} tone=\"transparent\" border>\n <Stack gap={4}>\n <Flex align=\"center\" justify=\"space-between\" gap={3}>\n <Label muted size={1}>\n Mezzanine\n </Label>\n <Text size={1}>\n <a href={MEZZANINE_LEARN_MORE_URL} target=\"_blank\" rel=\"noopener noreferrer\">\n Learn more\n </a>\n </Text>\n </Flex>\n\n <Stack gap={2}>\n <Text size={1} muted={!isReady}>\n mezzanine.mp4\n </Text>\n {resolution && (\n <Text size={1} muted>\n {resolution}\n </Text>\n )}\n </Stack>\n\n {withExplanation && showExplanation && <MezzanineExplanation />}\n\n {showExplanation && (expired || status === 'errored') && (\n <Stack gap={2}>\n {expired && (\n <Text size={1} muted>\n The previous mezzanine file expired. Enable it again to download.\n </Text>\n )}\n {status === 'errored' && (\n <Text size={1} style={{color: 'var(--card-critical-color)'}}>\n Mux could not prepare the mezzanine file. Please try again.\n </Text>\n )}\n </Stack>\n )}\n\n {isPreparing && (\n <Text size={1} muted>\n Preparing the mezzanine file… this can take a few minutes. You can close this and come\n back later.\n </Text>\n )}\n\n {isReady && (\n <Text size={1} muted>\n Ready to download. The link stays available for about 24 hours.\n </Text>\n )}\n\n <Flex justify=\"flex-end\" gap={2}>\n {isPreparing ? (\n <Flex align=\"center\" gap={2}>\n <Spinner muted size={1} />\n <Text size={1} muted>\n Preparing…\n </Text>\n </Flex>\n ) : isReady ? (\n <Button\n icon={DownloadIcon}\n text=\"Download\"\n tone=\"positive\"\n fontSize={1}\n padding={3}\n loading={busy}\n disabled={busy}\n onClick={() => void download()}\n />\n ) : (\n <Button\n text={status === 'errored' ? 'Try again' : 'Enable'}\n tone=\"primary\"\n fontSize={1}\n padding={3}\n loading={busy}\n disabled={busy || !assetReady}\n onClick={() => void enable()}\n />\n )}\n </Flex>\n </Stack>\n </Card>","_c","async (asset: VideoAssetDocument) => {\n if (!asset.assetId) {\n if (showToast) {\n toast.push({\n title: 'Cannot resync',\n description: 'Asset has no Mux ID',\n status: 'error',\n })\n }\n options?.onError?.(new Error('Asset has no Mux ID'))\n return undefined\n }\n\n if (!asset._id) {\n if (showToast) {\n toast.push({\n title: 'Cannot resync',\n description: 'Asset has no document ID',\n status: 'error',\n })\n }\n options?.onError?.(new Error('Asset has no document ID'))\n return undefined\n }\n\n setResyncState('syncing')\n setResyncError(null)\n\n try {\n const response = await getAsset(client, asset.assetId)\n const muxData = response.data\n const dataWithKeys = addKeysToMuxData(muxData)\n\n await client\n .patch(asset._id)\n .set({\n status: muxData.status,\n data: dataWithKeys,\n ...(muxData.meta?.title && {filename: muxData.meta.title}),\n })\n .commit({returnDocuments: false})\n\n setResyncState('success')\n if (showToast) {\n toast.push({\n title: 'Asset synced',\n description: 'Data has been updated from Mux',\n status: 'success',\n })\n }\n\n options?.onSuccess?.(muxData)\n return muxData\n } catch (error) {\n setResyncState('error')\n setResyncError(error)\n console.error('Failed to refresh asset data:', error)\n if (showToast) {\n toast.push({\n title: 'Sync failed',\n description: 'Could not sync asset from Mux',\n status: 'error',\n })\n }\n options?.onError?.(error)\n return undefined\n }\n }","options?.onError","error","useCallback(\n async (asset: VideoAssetDocument) => {\n if (!asset.assetId) {\n if (showToast) {\n toast.push({\n title: 'Cannot resync',\n description: 'Asset has no Mux ID',\n status: 'error',\n })\n }\n options?.onError?.(new Error('Asset has no Mux ID'))\n return undefined\n }\n\n if (!asset._id) {\n if (showToast) {\n toast.push({\n title: 'Cannot resync',\n description: 'Asset has no document ID',\n status: 'error',\n })\n }\n options?.onError?.(new Error('Asset has no document ID'))\n return undefined\n }\n\n setResyncState('syncing')\n setResyncError(null)\n\n try {\n const response = await getAsset(client, asset.assetId)\n const muxData = response.data\n const dataWithKeys = addKeysToMuxData(muxData)\n\n await client\n .patch(asset._id)\n .set({\n status: muxData.status,\n data: dataWithKeys,\n ...(muxData.meta?.title && {filename: muxData.meta.title}),\n })\n .commit({returnDocuments: false})\n\n setResyncState('success')\n if (showToast) {\n toast.push({\n title: 'Asset synced',\n description: 'Data has been updated from Mux',\n status: 'success',\n })\n }\n\n options?.onSuccess?.(muxData)\n return muxData\n } catch (error) {\n setResyncState('error')\n setResyncError(error)\n console.error('Failed to refresh asset data:', error)\n if (showToast) {\n toast.push({\n title: 'Sync failed',\n description: 'Could not sync asset from Mux',\n status: 'error',\n })\n }\n options?.onError?.(error)\n return undefined\n }\n },\n [client, toast, options, showToast],\n )","{\n resyncState,\n resyncError,\n resyncAsset,\n isResyncing: resyncState === 'syncing',\n }","resyncState === 'syncing'","_c","useClient","LANGUAGE_OPTIONS","useClient","useClient","{\n track,\n iconOnly,\n downloadingTrackId,\n deletingTrackId,\n trackToEdit,\n getTrackSourceLabel,\n handleDownload,\n setTrackToEdit,\n setTrackToDelete,\n}: TrackCardProps","(action: 'download' | 'edit' | 'delete') => {\n if (action === 'download') {\n return (\n downloadingTrackId !== null || deletingTrackId === track.id || trackToEdit?.id === track.id\n )\n }\n if (action === 'edit') {\n return (\n downloadingTrackId === track.id ||\n deletingTrackId === track.id ||\n trackToEdit?.id === track.id\n )\n }\n return (\n downloadingTrackId === track.id || deletingTrackId !== null || trackToEdit?.id === track.id\n )\n }","id","() => {\n if (track.status === 'preparing') {\n return (\n <Flex align=\"center\" gap={2}>\n <Spinner\n muted\n style={{\n width: '0.75em',\n height: '0.75em',\n verticalAlign: 'middle',\n display: 'inline-block',\n marginBottom: '-2px',\n }}\n />\n <Text size={1} muted>\n Processing...\n </Text>\n </Flex>\n )\n }\n\n return (\n <Flex gap={2}>\n {track.status !== 'errored' && (\n <Button\n icon={\n downloadingTrackId === track.id ? (\n <Spinner\n style={{\n verticalAlign: 'middle',\n display: 'inline-block',\n marginTop: '-2px',\n width: '0.5em',\n height: '0.5em',\n }}\n />\n ) : (\n <DownloadIcon />\n )\n }\n text={iconOnly ? undefined : 'Download'}\n mode=\"ghost\"\n tone=\"primary\"\n fontSize={1}\n padding={2}\n onClick={() => handleDownload(track)}\n disabled={isDisabled('download')}\n title=\"Download\"\n />\n )}\n <Button\n icon={<EditIcon />}\n text={iconOnly ? undefined : 'Edit'}\n mode=\"ghost\"\n tone=\"primary\"\n fontSize={1}\n padding={2}\n disabled={isDisabled('edit')}\n onClick={() => setTrackToEdit(track)}\n title=\"Edit\"\n />\n <Button\n icon={\n deletingTrackId === track.id ? (\n <Spinner\n style={{\n verticalAlign: 'middle',\n display: 'inline-block',\n marginTop: '-2px',\n width: '0.5em',\n height: '0.5em',\n }}\n />\n ) : (\n <TrashIcon />\n )\n }\n text={iconOnly ? undefined : 'Delete'}\n mode=\"ghost\"\n tone=\"critical\"\n fontSize={1}\n padding={2}\n disabled={isDisabled('delete')}\n onClick={() => setTrackToDelete(track)}\n title=\"Delete\"\n />\n </Flex>\n )\n }","track.status","<Text weight=\"semibold\">{track.name || 'Untitled'}</Text>","track.name || 'Untitled'","getTrackSourceLabel(track)","<Text size={1} muted>\n ({getTrackSourceLabel(track)})\n </Text>","track.status === 'errored' && (\n <ErrorOutlineIcon\n style={{color: 'var(--card-critical-color)'}}\n aria-label=\"Error\"\n fontSize={20}\n />\n )","status","<Flex align=\"center\" gap={2}>\n <Text weight=\"semibold\">{track.name || 'Untitled'}</Text>\n <Text size={1} muted>\n ({getTrackSourceLabel(track)})\n </Text>\n {track.status === 'errored' && (\n <ErrorOutlineIcon\n style={{color: 'var(--card-critical-color)'}}\n aria-label=\"Error\"\n fontSize={20}\n />\n )}\n </Flex>","track.language_code && (\n <Text size={1} muted>\n Language: {track.language_code}\n </Text>\n )","language_code","track.status === 'errored' && track.error && (\n <Text size={1} style={{color: 'var(--card-critical-color)'}}>\n {track.error.messages?.[0] || track.error.type || 'Failed to process track'}\n </Text>\n )","error","<Stack gap={2} flex={1}>\n <Flex align=\"center\" gap={2}>\n <Text weight=\"semibold\">{track.name || 'Untitled'}</Text>\n <Text size={1} muted>\n ({getTrackSourceLabel(track)})\n </Text>\n {track.status === 'errored' && (\n <ErrorOutlineIcon\n style={{color: 'var(--card-critical-color)'}}\n aria-label=\"Error\"\n fontSize={20}\n />\n )}\n </Flex>\n {track.language_code && (\n <Text size={1} muted>\n Language: {track.language_code}\n </Text>\n )}\n {track.status === 'errored' && track.error && (\n <Text size={1} style={{color: 'var(--card-critical-color)'}}>\n {track.error.messages?.[0] || track.error.type || 'Failed to process track'}\n </Text>\n )}\n </Stack>","renderActionButtons()","<Flex align=\"center\" justify=\"space-between\" gap={3}>\n <Stack gap={2} flex={1}>\n <Flex align=\"center\" gap={2}>\n <Text weight=\"semibold\">{track.name || 'Untitled'}</Text>\n <Text size={1} muted>\n ({getTrackSourceLabel(track)})\n </Text>\n {track.status === 'errored' && (\n <ErrorOutlineIcon\n style={{color: 'var(--card-critical-color)'}}\n aria-label=\"Error\"\n fontSize={20}\n />\n )}\n </Flex>\n {track.language_code && (\n <Text size={1} muted>\n Language: {track.language_code}\n </Text>\n )}\n {track.status === 'errored' && track.error && (\n <Text size={1} style={{color: 'var(--card-critical-color)'}}>\n {track.error.messages?.[0] || track.error.type || 'Failed to process track'}\n </Text>\n )}\n </Stack>\n {renderActionButtons()}\n </Flex>","<Card\n padding={3}\n radius={2}\n tone={track.status === 'errored' ? 'caution' : 'transparent'}\n border\n >\n <Flex align=\"center\" justify=\"space-between\" gap={3}>\n <Stack gap={2} flex={1}>\n <Flex align=\"center\" gap={2}>\n <Text weight=\"semibold\">{track.name || 'Untitled'}</Text>\n <Text size={1} muted>\n ({getTrackSourceLabel(track)})\n </Text>\n {track.status === 'errored' && (\n <ErrorOutlineIcon\n style={{color: 'var(--card-critical-color)'}}\n aria-label=\"Error\"\n fontSize={20}\n />\n )}\n </Flex>\n {track.language_code && (\n <Text size={1} muted>\n Language: {track.language_code}\n </Text>\n )}\n {track.status === 'errored' && track.error && (\n <Text size={1} style={{color: 'var(--card-critical-color)'}}>\n {track.error.messages?.[0] || track.error.type || 'Failed to process track'}\n </Text>\n )}\n </Stack>\n {renderActionButtons()}\n </Flex>\n </Card>","track.status === 'errored' ? 'caution' : 'transparent'","_c","useClient","{\n dialogState,\n setDialogState,\n children,\n}: DialogStateProviderProps","{dialogState, setDialogState}","useMemo(() => ({dialogState, setDialogState}), [dialogState, setDialogState])","<DialogStateContext.Provider value={value}>{children}</DialogStateContext.Provider>","DialogStateContext.Provider","_c","{asset}: Props","() => setDialogState(false)","<Stack padding={4}>\n <TextTracksManager asset={asset} />\n </Stack>","<Dialog id={dialogId} header=\"Edit Captions\" onClose={() => setDialogState(false)} width={1}>\n <Stack padding={4}>\n <TextTracksManager asset={asset} />\n </Stack>\n </Dialog>","_c","{asset, currentTime = 0}: Props","currentTime = 0","() =>\n formatSecondsToHHMMSS(currentTime)","{...asset, thumbTime: nextTime}","useMemo(() => ({...asset, thumbTime: nextTime}), [asset, nextTime])","() => {\n setSaving(true)\n client\n .patch(asset._id)\n .set({thumbTime: nextTime})\n .commit({returnDocuments: false})\n .then(() => setDialogState(false))\n .catch(setSaveThumbnailError)\n .finally(() => setSaving(false))\n }","_id","getDevicePixelRatio({maxDpr: 2})","(event: ChangeEvent<HTMLInputElement>) => {\n const value = event.currentTarget.value\n setTimeFormatted(value)\n\n if (isValidTimeFormat(value)) {\n setInputError('')\n const totalSeconds = getSecondsFromTimeFormat(value)\n setNextTime(totalSeconds)\n } else {\n setInputError('Invalid time format')\n }\n }","() => setDialogState(false)","<Stack padding={3}>\n <Button\n key=\"thumbnail\"\n disabled={inputError !== ''}\n mode=\"ghost\"\n tone=\"primary\"\n loading={saving}\n onClick={handleSave}\n text=\"Set new thumbnail\"\n />\n </Stack>","inputError !== ''","<Text size={1} weight=\"semibold\">\n Current:\n </Text>","<Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n Current:\n </Text>\n <VideoThumbnail asset={asset} width={width} staticImage />\n </Stack>","<Text size={1} weight=\"semibold\">\n New:\n </Text>","<Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n New:\n </Text>\n <VideoThumbnail asset={assetWithNewThumbnail} width={width} staticImage />\n </Stack>","<Stack gap={2}>\n <Flex align={'center'} justify={'center'}>\n <Text size={5} weight=\"semibold\">\n Or\n </Text>\n </Flex>\n </Stack>","<Text size={1} weight=\"semibold\">\n Selected time for thumbnail (hh:mm:ss):\n </Text>","<Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n Selected time for thumbnail (hh:mm:ss):\n </Text>\n <TextInput\n size={1}\n value={timeFormatted}\n placeholder=\"hh:mm:ss\"\n onChange={handleInputChange}\n customValidity={inputError}\n />\n </Stack>","<Stack gap={3} padding={3}>\n <Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n Current:\n </Text>\n <VideoThumbnail asset={asset} width={width} staticImage />\n </Stack>\n <Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n New:\n </Text>\n <VideoThumbnail asset={assetWithNewThumbnail} width={width} staticImage />\n </Stack>\n\n <Stack gap={2}>\n <Flex align={'center'} justify={'center'}>\n <Text size={5} weight=\"semibold\">\n Or\n </Text>\n </Flex>\n </Stack>\n\n <Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n Selected time for thumbnail (hh:mm:ss):\n </Text>\n <TextInput\n size={1}\n value={timeFormatted}\n placeholder=\"hh:mm:ss\"\n onChange={handleInputChange}\n customValidity={inputError}\n />\n </Stack>\n </Stack>","<Dialog\n id={dialogId}\n header=\"Edit thumbnail\"\n onClose={() => setDialogState(false)}\n footer={\n <Stack padding={3}>\n <Button\n key=\"thumbnail\"\n disabled={inputError !== ''}\n mode=\"ghost\"\n tone=\"primary\"\n loading={saving}\n onClick={handleSave}\n text=\"Set new thumbnail\"\n />\n </Stack>\n }\n >\n <Stack gap={3} padding={3}>\n <Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n Current:\n </Text>\n <VideoThumbnail asset={asset} width={width} staticImage />\n </Stack>\n <Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n New:\n </Text>\n <VideoThumbnail asset={assetWithNewThumbnail} width={width} staticImage />\n </Stack>\n\n <Stack gap={2}>\n <Flex align={'center'} justify={'center'}>\n <Text size={5} weight=\"semibold\">\n Or\n </Text>\n </Flex>\n </Stack>\n\n <Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n Selected time for thumbnail (hh:mm:ss):\n </Text>\n <TextInput\n size={1}\n value={timeFormatted}\n placeholder=\"hh:mm:ss\"\n onChange={handleInputChange}\n customValidity={inputError}\n />\n </Stack>\n </Stack>\n </Dialog>","_c","useClient","<path\n fill=\"currentColor\"\n style={{opacity: '0.65'}}\n 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\"\n />","<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\" {...props}>\n <path\n fill=\"currentColor\"\n style={{opacity: '0.65'}}\n 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\"\n />\n </svg>","_c","{asset, onClose}: Props","() => {\n onClose?.()\n setDialogState(false)\n }","getMezzanineStatus(asset)","showExplanation && <MezzanineExplanation />","<Mezzanine asset={asset} withExplanation={false} />","<Box padding={4}>\n <Stack gap={4}>\n {showExplanation && <MezzanineExplanation />}\n <Mezzanine asset={asset} withExplanation={false} />\n </Stack>\n </Box>","<Dialog\n id={dialogId}\n header=\"Mezzanine file\"\n onClose={closing}\n zOffset={DIALOGS_Z_INDEX}\n width={1}\n >\n <Box padding={4}>\n <Stack gap={4}>\n {showExplanation && <MezzanineExplanation />}\n <Mezzanine asset={asset} withExplanation={false} />\n </Stack>\n </Box>\n </Dialog>","_c","useClient","_Fragment","getUnknownTypeFallback(value._id, value._type)","_id","_type","<SanityDefaultPreview {...getUnknownTypeFallback(value._id, value._type)} layout={layout} />","_c","{time}: TimeAgoProps","{useTemporalPhrase: true}","<span title={timeAgo}>{timeAgo}</span>","_c","<Box padding={2}>\n <Text size={1}>\n {document ? (\n <>Edited {updatedAt && <TimeAgo time={updatedAt} />}</>\n ) : (\n <>No unpublished edits</>\n )}\n </Text>\n </Box>","<EditIcon />","<TextWithTone tone=\"caution\" dimmed={!document} muted={!document} size={1}>\n <EditIcon />\n </TextWithTone>","!document","<Tooltip\n animate\n portal\n content={\n <Box padding={2}>\n <Text size={1}>\n {document ? (\n <>Edited {updatedAt && <TimeAgo time={updatedAt} />}</>\n ) : (\n <>No unpublished edits</>\n )}\n </Text>\n </Box>\n }\n >\n <TextWithTone tone=\"caution\" dimmed={!document} muted={!document} size={1}>\n <EditIcon />\n </TextWithTone>\n </Tooltip>","_c","_Fragment","<Box padding={2}>\n <Text size={1}>\n {document ? (\n <>Published {updatedAt && <TimeAgo time={updatedAt} />}</>\n ) : (\n <>Not published</>\n )}\n </Text>\n </Box>","<PublishIcon />","<TextWithTone tone=\"positive\" dimmed={!document} muted={!document} size={1}>\n <PublishIcon />\n </TextWithTone>","!document","<Tooltip\n animate\n portal\n content={\n <Box padding={2}>\n <Text size={1}>\n {document ? (\n <>Published {updatedAt && <TimeAgo time={updatedAt} />}</>\n ) : (\n <>Not published</>\n )}\n </Text>\n </Box>\n }\n >\n <TextWithTone tone=\"positive\" dimmed={!document} muted={!document} size={1}>\n <PublishIcon />\n </TextWithTone>\n </Tooltip>","_c","_Fragment","getPreviewStateObservable(props.documentPreviewStore, schemaType, value._id)","documentPreviewStore","_id","useMemo(\n () => getPreviewStateObservable(props.documentPreviewStore, schemaType, value._id),\n [props.documentPreviewStore, schemaType, value._id],\n )","{\n isLoading: true,\n snapshot: null,\n original: null,\n }","isLoading ? null : (\n <Inline gap={4}>\n {presence && presence.length > 0 && <DocumentPreviewPresence presence={presence} />}\n <PublishedStatus document={original} />\n <DraftStatus document={snapshot} />\n </Inline>\n )","getPreviewValueWithFallback({snapshot, original, fallback: {title}})","<SanityDefaultPreview\n {...(getPreviewValueWithFallback({snapshot, original, fallback: {title}}) as any)}\n isPlaceholder={isLoading}\n icon={icon}\n layout={layout}\n status={status}\n />","getPreviewValueWithFallback({snapshot, original, fallback: {title}}) as any","_c","useMemo(() => {\n if (!doc) return null\n\n if (!schemaType || !hasSchemaType) {\n return <MissingSchemaType value={doc} />\n }\n\n return (\n <PaneItemPreview\n documentPreviewStore={documentPreviewStore}\n icon={getIconWithFallback(undefined, schemaType, DocumentIcon)}\n schemaType={schemaType}\n layout=\"default\"\n value={doc}\n presence={documentPresence}\n />\n )\n }, [hasSchemaType, schemaType, documentPresence, doc, documentPreviewStore])","<MissingSchemaType value={doc} />","getIconWithFallback(undefined, schemaType, DocumentIcon)","<PaneItemPreview\n documentPreviewStore={documentPreviewStore}\n icon={getIconWithFallback(undefined, schemaType, DocumentIcon)}\n schemaType={schemaType}\n layout=\"default\"\n value={doc}\n presence={documentPresence}\n />","{id: props.documentPair.id}","id","<PreviewCard\n __unstable_focusRing\n as={IntentLink}\n intent=\"edit\"\n params={{id: props.documentPair.id}}\n data-as=\"a\"\n data-ui=\"PaneItem\"\n padding={2}\n radius={2}\n tone=\"inherit\"\n >\n {children}\n </PreviewCard>","_c","<SpinnerBox />","<Card border radius={3} padding={3}>\n <Text size={2}>No documents are using this video</Text>\n </Card>","Container","documentPairs?.map((documentPair) => {\n const schemaType = schema.get(documentPair.type)\n\n return (\n <Card\n key={documentPair.id}\n marginBottom={2}\n padding={2}\n radius={2}\n shadow={1}\n style={{overflow: 'hidden'}}\n >\n <Box>\n <DocumentPreview documentPair={documentPair} schemaType={schemaType} />\n </Box>\n </Card>\n )\n })","references","props.references || []","<Container>\n {documentPairs?.map((documentPair) => {\n const schemaType = schema.get(documentPair.type)\n\n return (\n <Card\n key={documentPair.id}\n marginBottom={2}\n padding={2}\n radius={2}\n shadow={1}\n style={{overflow: 'hidden'}}\n >\n <Box>\n <DocumentPreview documentPair={documentPair} schemaType={schemaType} />\n </Box>\n </Card>\n )\n })}\n </Container>","_c","{\n asset,\n references,\n referencesLoading,\n cancelDelete,\n succeededDeleting,\n}: {\n asset: VideoAssetDocument\n references?: SanityDocument[]\n referencesLoading: boolean\n cancelDelete: () => void\n succeededDeleting: () => void\n}","() => {\n if (state !== 'checkingReferences' || referencesLoading) return\n\n // oxlint-disable-next-line react/set-state-in-effect\n setState(references?.length ? 'cantDelete' : 'confirm')\n }","length","[state, references, referencesLoading]","async function confirmDelete() {\n if (state !== 'confirm') return\n\n setState('processing_deletion')\n const worked = await deleteAsset({client, asset, deleteOnMux})\n if (worked === true) {\n toast.push({title: 'Successfully deleted video', status: 'success'})\n succeededDeleting()\n } else if (worked === 'failed-mux') {\n toast.push({\n title: 'Deleted video in Sanity',\n description: \"But it wasn't deleted in Mux\",\n status: 'warning',\n })\n succeededDeleting()\n } else {\n toast.push({title: 'Failed deleting video', status: 'error'})\n\n setState('error_deleting')\n }\n }","{\n minHeight: '150px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }","state === 'checkingReferences' && (\n <>\n <Heading size={2}>Checking if video can be deleted</Heading>\n <SpinnerBox />\n </>\n )","state === 'cantDelete' && (\n <>\n <Heading size={2}>Video can't be deleted</Heading>\n <Text size={2} style={{marginBottom: '2rem'}}>\n There are {references?.length} document{references && references.length > 0 && 's'}{' '}\n pointing to this video. Remove their references to this file or delete them before\n proceeding.\n </Text>\n <VideoReferences references={references} isLoaded={!referencesLoading} />\n </>\n )","references?.length","state === 'confirm' && (\n <>\n <Heading size={2}>Are you sure you want to delete this video?</Heading>\n <Text size={2}>This action is irreversible</Text>\n <Stack gap={4} marginY={4}>\n <Flex align=\"center\" as=\"label\">\n <Checkbox\n checked={deleteOnMux}\n onChange={() => setDeleteOnMux((prev) => !prev)}\n />\n <Text style={{margin: '0 10px'}}>Delete asset on Mux</Text>\n </Flex>\n <Flex align=\"center\" as=\"label\">\n <Checkbox disabled checked />\n <Text style={{margin: '0 10px'}}>Delete video from dataset</Text>\n </Flex>\n <Box>\n <Button\n icon={TrashIcon}\n fontSize={2}\n padding={3}\n text=\"Delete video\"\n tone=\"critical\"\n onClick={confirmDelete}\n disabled={['processing_deletion', 'checkingReferences', 'cantDelete'].some(\n (s) => s === state,\n )}\n />\n </Box>\n </Stack>\n </>\n )","(prev) => !prev","state === 'processing_deletion' && (\n <>\n <Heading size={2}>Deleting video...</Heading>\n <SpinnerBox />\n </>\n )","state === 'error_deleting' && (\n <>\n <Heading size={2}>Something went wrong!</Heading>\n <Text size={2}>Try deleting the video again by clicking the button below</Text>\n </>\n )","<Card\n padding={3}\n style={{\n minHeight: '150px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <Stack gap={3}>\n {state === 'checkingReferences' && (\n <>\n <Heading size={2}>Checking if video can be deleted</Heading>\n <SpinnerBox />\n </>\n )}\n {state === 'cantDelete' && (\n <>\n <Heading size={2}>Video can't be deleted</Heading>\n <Text size={2} style={{marginBottom: '2rem'}}>\n There are {references?.length} document{references && references.length > 0 && 's'}{' '}\n pointing to this video. Remove their references to this file or delete them before\n proceeding.\n </Text>\n <VideoReferences references={references} isLoaded={!referencesLoading} />\n </>\n )}\n {state === 'confirm' && (\n <>\n <Heading size={2}>Are you sure you want to delete this video?</Heading>\n <Text size={2}>This action is irreversible</Text>\n <Stack gap={4} marginY={4}>\n <Flex align=\"center\" as=\"label\">\n <Checkbox\n checked={deleteOnMux}\n onChange={() => setDeleteOnMux((prev) => !prev)}\n />\n <Text style={{margin: '0 10px'}}>Delete asset on Mux</Text>\n </Flex>\n <Flex align=\"center\" as=\"label\">\n <Checkbox disabled checked />\n <Text style={{margin: '0 10px'}}>Delete video from dataset</Text>\n </Flex>\n <Box>\n <Button\n icon={TrashIcon}\n fontSize={2}\n padding={3}\n text=\"Delete video\"\n tone=\"critical\"\n onClick={confirmDelete}\n disabled={['processing_deletion', 'checkingReferences', 'cantDelete'].some(\n (s) => s === state,\n )}\n />\n </Box>\n </Stack>\n </>\n )}\n {state === 'processing_deletion' && (\n <>\n <Heading size={2}>Deleting video...</Heading>\n <SpinnerBox />\n </>\n )}\n {state === 'error_deleting' && (\n <>\n <Heading size={2}>Something went wrong!</Heading>\n <Text size={2}>Try deleting the video again by clicking the button below</Text>\n </>\n )}\n </Stack>\n </Card>","<Dialog\n animate\n header={'Delete video'}\n zOffset={DIALOGS_Z_INDEX}\n id=\"deleting-video-details-dialog\"\n onClose={cancelDelete}\n onClickOutside={cancelDelete}\n width={1}\n position=\"fixed\"\n >\n <Card\n padding={3}\n style={{\n minHeight: '150px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <Stack gap={3}>\n {state === 'checkingReferences' && (\n <>\n <Heading size={2}>Checking if video can be deleted</Heading>\n <SpinnerBox />\n </>\n )}\n {state === 'cantDelete' && (\n <>\n <Heading size={2}>Video can't be deleted</Heading>\n <Text size={2} style={{marginBottom: '2rem'}}>\n There are {references?.length} document{references && references.length > 0 && 's'}{' '}\n pointing to this video. Remove their references to this file or delete them before\n proceeding.\n </Text>\n <VideoReferences references={references} isLoaded={!referencesLoading} />\n </>\n )}\n {state === 'confirm' && (\n <>\n <Heading size={2}>Are you sure you want to delete this video?</Heading>\n <Text size={2}>This action is irreversible</Text>\n <Stack gap={4} marginY={4}>\n <Flex align=\"center\" as=\"label\">\n <Checkbox\n checked={deleteOnMux}\n onChange={() => setDeleteOnMux((prev) => !prev)}\n />\n <Text style={{margin: '0 10px'}}>Delete asset on Mux</Text>\n </Flex>\n <Flex align=\"center\" as=\"label\">\n <Checkbox disabled checked />\n <Text style={{margin: '0 10px'}}>Delete video from dataset</Text>\n </Flex>\n <Box>\n <Button\n icon={TrashIcon}\n fontSize={2}\n padding={3}\n text=\"Delete video\"\n tone=\"critical\"\n onClick={confirmDelete}\n disabled={['processing_deletion', 'checkingReferences', 'cantDelete'].some(\n (s) => s === state,\n )}\n />\n </Box>\n </Stack>\n </>\n )}\n {state === 'processing_deletion' && (\n <>\n <Heading size={2}>Deleting video...</Heading>\n <SpinnerBox />\n </>\n )}\n {state === 'error_deleting' && (\n <>\n <Heading size={2}>Something went wrong!</Heading>\n <Text size={2}>Try deleting the video again by clicking the button below</Text>\n </>\n )}\n </Stack>\n </Card>\n </Dialog>","_c","useClient","_Fragment","_temp","{documentStore, id: props.asset._id}","_id","useMemo(() => ({documentStore, id: props.asset._id}), [documentStore, props.asset._id])","() => props.asset","asset","getVideoMetadata({...props.asset, filename})","{showToast: true}","async function handleResync() {\n if (state !== 'idle') return\n setState('resyncing')\n await resyncAsset(props.asset)\n setState('idle')\n }","function handleClose() {\n if (state !== 'idle') return\n\n if (modified) {\n setState('closing')\n return\n }\n\n props.closeDialog()\n }","function confirmClose(shouldClose: boolean) {\n if (state !== 'closing') return\n\n if (shouldClose) props.closeDialog()\n\n setState('idle')\n }","async function saveChanges() {\n if (state !== 'idle') return\n setState('saving')\n\n try {\n await client.patch(props.asset._id).set({filename}).commit()\n setOriginalAsset((prev) => ({...prev, filename}))\n toast.push({\n title: 'Video title updated',\n description: `New title: ${filename}`,\n status: 'success',\n })\n props.closeDialog()\n } catch (error) {\n toast.push({\n title: 'Failed updating file name',\n status: 'error',\n description: typeof error === 'string' ? error : 'Please try again',\n })\n setFilename(originalAsset.filename)\n }\n\n setState('idle')\n }","filename","props.asset._id","error","{\n references,\n referencesLoading,\n modified,\n filename,\n setFilename,\n displayInfo,\n state,\n setState,\n handleClose,\n confirmClose,\n saveChanges,\n handleResync,\n isResyncing,\n }","_c","useClient","<TextInput\n id={props.label}\n value={props.value}\n placeholder={props.placeholder}\n onInput={props.onInput}\n disabled={props.disabled}\n />","disabled","label","onInput","placeholder","value","<FormField title={props.label} description={props.description} inputId={props.label}>\n <TextInput\n id={props.label}\n value={props.value}\n placeholder={props.placeholder}\n onInput={props.onInput}\n disabled={props.disabled}\n />\n </FormField>","description","() => {\n if (!contentsRef.current || !('getBoundingClientRect' in contentsRef.current)) return\n\n setContainerHeight(contentsRef.current.getBoundingClientRect().height)\n }","[]","() => setState('deleting')","<Button\n icon={TrashIcon}\n fontSize={2}\n padding={3}\n mode=\"bleed\"\n text=\"Delete\"\n tone=\"critical\"\n onClick={() => setState('deleting')}\n disabled={isSaving || isResyncing}\n />","isSaving || isResyncing","<Button\n icon={SyncIcon}\n fontSize={2}\n padding={3}\n mode=\"bleed\"\n text=\"Resync\"\n tone=\"primary\"\n onClick={handleResync}\n disabled={isSaving || isResyncing}\n iconRight={isResyncing && Spinner}\n />","isResyncing && Spinner","<Flex gap={2}>\n <Button\n icon={TrashIcon}\n fontSize={2}\n padding={3}\n mode=\"bleed\"\n text=\"Delete\"\n tone=\"critical\"\n onClick={() => setState('deleting')}\n disabled={isSaving || isResyncing}\n />\n <Button\n icon={SyncIcon}\n fontSize={2}\n padding={3}\n mode=\"bleed\"\n text=\"Resync\"\n tone=\"primary\"\n onClick={handleResync}\n disabled={isSaving || isResyncing}\n iconRight={isResyncing && Spinner}\n />\n </Flex>","modified && (\n <Button\n icon={CheckmarkIcon}\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Save and close\"\n tone=\"positive\"\n onClick={saveChanges}\n iconRight={isSaving && Spinner}\n disabled={isSaving || isResyncing}\n />\n )","<Card padding={3}>\n <Flex justify=\"space-between\" align=\"center\">\n <Flex gap={2}>\n <Button\n icon={TrashIcon}\n fontSize={2}\n padding={3}\n mode=\"bleed\"\n text=\"Delete\"\n tone=\"critical\"\n onClick={() => setState('deleting')}\n disabled={isSaving || isResyncing}\n />\n <Button\n icon={SyncIcon}\n fontSize={2}\n padding={3}\n mode=\"bleed\"\n text=\"Resync\"\n tone=\"primary\"\n onClick={handleResync}\n disabled={isSaving || isResyncing}\n iconRight={isResyncing && Spinner}\n />\n </Flex>\n {modified && (\n <Button\n icon={CheckmarkIcon}\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Save and close\"\n tone=\"positive\"\n onClick={saveChanges}\n iconRight={isSaving && Spinner}\n disabled={isSaving || isResyncing}\n />\n )}\n </Flex>\n </Card>","state === 'deleting' && (\n <DeleteDialog\n asset={props.asset}\n cancelDelete={() => setState('idle')}\n referencesLoading={referencesLoading}\n references={references}\n succeededDeleting={() => {\n props.closeDialog()\n }}\n />\n )","state === 'closing' && (\n <Dialog\n animate\n header={'You have unsaved changes'}\n zOffset={DIALOGS_Z_INDEX}\n id=\"closing-video-details-dialog\"\n onClose={() => confirmClose(false)}\n onClickOutside={() => confirmClose(false)}\n width={1}\n position=\"fixed\"\n footer={\n <Card padding={3}>\n <Flex justify=\"space-between\" align=\"center\">\n <Button\n icon={ErrorOutlineIcon}\n fontSize={2}\n padding={3}\n text=\"Discard changes\"\n tone=\"critical\"\n onClick={() => confirmClose(true)}\n />\n {modified && (\n <Button\n icon={RevertIcon}\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Keep editing\"\n tone=\"primary\"\n onClick={() => confirmClose(false)}\n />\n )}\n </Flex>\n </Card>\n }\n >\n <Card padding={5}>\n <Stack style={{textAlign: 'center'}} gap={3}>\n <Heading size={2}>Unsaved changes will be lost</Heading>\n <Text size={2}>Are you sure you want to discard them?</Text>\n </Stack>\n </Card>\n </Dialog>\n )","{\n containerType: 'inline-size',\n }","['column', 'column', 'row']","typeof containerHeight === 'number'\n ? {\n minHeight: containerHeight,\n }\n : undefined","<VideoPlayer asset={props.asset} autoPlay={props.asset.autoPlay || false} />","asset","props.asset.autoPlay || false","tab === 'details' && (\n <>\n <TextTracksManager\n asset={props.asset}\n iconOnly\n collapseTracks\n tracks={\n displayInfo?.text_tracks ||\n props.asset.data?.tracks?.filter(\n (track): track is MuxTextTrack => track.type === 'text',\n ) ||\n []\n }\n />\n <Mezzanine asset={props.asset} />\n </>\n )","text_tracks","(track): track is MuxTextTrack => track.type === 'text'","<Stack gap={4} flex={1} sizing=\"border\">\n <VideoPlayer asset={props.asset} autoPlay={props.asset.autoPlay || false} />\n {tab === 'details' && (\n <>\n <TextTracksManager\n asset={props.asset}\n iconOnly\n collapseTracks\n tracks={\n displayInfo?.text_tracks ||\n props.asset.data?.tracks?.filter(\n (track): track is MuxTextTrack => track.type === 'text',\n ) ||\n []\n }\n />\n <Mezzanine asset={props.asset} />\n </>\n )}\n </Stack>","() => setTab('details')","<Tab\n aria-controls=\"details-panel\"\n icon={EditIcon}\n id=\"details-tab\"\n label=\"Details\"\n onClick={() => setTab('details')}\n selected={tab === 'details'}\n />","tab === 'details'","() => setTab('references')","<Tab\n aria-controls=\"references-panel\"\n icon={SearchIcon}\n id=\"references-tab\"\n label={`Used by ${references ? `(${references.length})` : ''}`}\n onClick={() => setTab('references')}\n selected={tab === 'references'}\n />","`Used by ${references ? `(${references.length})` : ''}`","tab === 'references'","<TabList gap={2}>\n <Tab\n aria-controls=\"details-panel\"\n icon={EditIcon}\n id=\"details-tab\"\n label=\"Details\"\n onClick={() => setTab('details')}\n selected={tab === 'details'}\n />\n <Tab\n aria-controls=\"references-panel\"\n icon={SearchIcon}\n id=\"references-tab\"\n label={`Used by ${references ? `(${references.length})` : ''}`}\n onClick={() => setTab('references')}\n selected={tab === 'references'}\n />\n </TabList>","{wordBreak: 'break-word'}","(e) => setFilename(e.currentTarget.value)","<AssetInput\n label=\"Video title or file name\"\n description=\"Not visible to users. Useful for finding videos later.\"\n value={filename || ''}\n onInput={(e) => setFilename(e.currentTarget.value)}\n disabled={state !== 'idle'}\n />","filename || ''","state !== 'idle'","displayInfo?.duration && (\n <IconInfo\n text={`Duration: ${displayInfo.duration}`}\n icon={ClockIcon}\n size={2}\n />\n )","duration","displayInfo?.max_stored_resolution && (\n <IconInfo\n text={`Max Resolution: ${displayInfo.max_stored_resolution}`}\n icon={ResolutionIcon}\n size={2}\n />\n )","max_stored_resolution","displayInfo?.max_stored_frame_rate && (\n <IconInfo\n text={`Frame rate: ${displayInfo.max_stored_frame_rate}`}\n icon={StopWatchIcon}\n size={2}\n />\n )","max_stored_frame_rate","displayInfo?.aspect_ratio && (\n <IconInfo\n text={`Aspect Ratio: ${displayInfo.aspect_ratio}`}\n icon={CropIcon}\n size={2}\n />\n )","aspect_ratio","displayInfo.createdAt.toLocaleDateString('en', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })","createdAt","<IconInfo\n text={`Uploaded on: ${displayInfo.createdAt.toLocaleDateString('en', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })}`}\n icon={CalendarIcon}\n size={2}\n />","`Uploaded on: ${displayInfo.createdAt.toLocaleDateString('en', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })}`","<IconInfo text={`Mux ID: \\n${displayInfo.id}`} icon={TagIcon} size={2} />","`Mux ID: \\n${displayInfo.id}`","<PlaybackIds playback_ids={displayInfo.playback_ids} />","playback_ids","<Stack gap={3}>\n {displayInfo?.duration && (\n <IconInfo\n text={`Duration: ${displayInfo.duration}`}\n icon={ClockIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_resolution && (\n <IconInfo\n text={`Max Resolution: ${displayInfo.max_stored_resolution}`}\n icon={ResolutionIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_frame_rate && (\n <IconInfo\n text={`Frame rate: ${displayInfo.max_stored_frame_rate}`}\n icon={StopWatchIcon}\n size={2}\n />\n )}\n {displayInfo?.aspect_ratio && (\n <IconInfo\n text={`Aspect Ratio: ${displayInfo.aspect_ratio}`}\n icon={CropIcon}\n size={2}\n />\n )}\n <IconInfo\n text={`Uploaded on: ${displayInfo.createdAt.toLocaleDateString('en', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })}`}\n icon={CalendarIcon}\n size={2}\n />\n <IconInfo text={`Mux ID: \\n${displayInfo.id}`} icon={TagIcon} size={2} />\n <PlaybackIds playback_ids={displayInfo.playback_ids} />\n </Stack>","<Stack gap={4}>\n <AssetInput\n label=\"Video title or file name\"\n description=\"Not visible to users. Useful for finding videos later.\"\n value={filename || ''}\n onInput={(e) => setFilename(e.currentTarget.value)}\n disabled={state !== 'idle'}\n />\n <Stack gap={3}>\n {displayInfo?.duration && (\n <IconInfo\n text={`Duration: ${displayInfo.duration}`}\n icon={ClockIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_resolution && (\n <IconInfo\n text={`Max Resolution: ${displayInfo.max_stored_resolution}`}\n icon={ResolutionIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_frame_rate && (\n <IconInfo\n text={`Frame rate: ${displayInfo.max_stored_frame_rate}`}\n icon={StopWatchIcon}\n size={2}\n />\n )}\n {displayInfo?.aspect_ratio && (\n <IconInfo\n text={`Aspect Ratio: ${displayInfo.aspect_ratio}`}\n icon={CropIcon}\n size={2}\n />\n )}\n <IconInfo\n text={`Uploaded on: ${displayInfo.createdAt.toLocaleDateString('en', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })}`}\n icon={CalendarIcon}\n size={2}\n />\n <IconInfo text={`Mux ID: \\n${displayInfo.id}`} icon={TagIcon} size={2} />\n <PlaybackIds playback_ids={displayInfo.playback_ids} />\n </Stack>\n </Stack>","<TabPanel\n aria-labelledby=\"details-tab\"\n id=\"details-panel\"\n hidden={tab !== 'details'}\n style={{wordBreak: 'break-word'}}\n >\n <Stack gap={4}>\n <AssetInput\n label=\"Video title or file name\"\n description=\"Not visible to users. Useful for finding videos later.\"\n value={filename || ''}\n onInput={(e) => setFilename(e.currentTarget.value)}\n disabled={state !== 'idle'}\n />\n <Stack gap={3}>\n {displayInfo?.duration && (\n <IconInfo\n text={`Duration: ${displayInfo.duration}`}\n icon={ClockIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_resolution && (\n <IconInfo\n text={`Max Resolution: ${displayInfo.max_stored_resolution}`}\n icon={ResolutionIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_frame_rate && (\n <IconInfo\n text={`Frame rate: ${displayInfo.max_stored_frame_rate}`}\n icon={StopWatchIcon}\n size={2}\n />\n )}\n {displayInfo?.aspect_ratio && (\n <IconInfo\n text={`Aspect Ratio: ${displayInfo.aspect_ratio}`}\n icon={CropIcon}\n size={2}\n />\n )}\n <IconInfo\n text={`Uploaded on: ${displayInfo.createdAt.toLocaleDateString('en', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })}`}\n icon={CalendarIcon}\n size={2}\n />\n <IconInfo text={`Mux ID: \\n${displayInfo.id}`} icon={TagIcon} size={2} />\n <PlaybackIds playback_ids={displayInfo.playback_ids} />\n </Stack>\n </Stack>\n </TabPanel>","tab !== 'details'","<VideoReferences references={references} isLoaded={!referencesLoading} />","!referencesLoading","<TabPanel\n aria-labelledby=\"references-tab\"\n id=\"references-panel\"\n hidden={tab !== 'references'}\n >\n <VideoReferences references={references} isLoaded={!referencesLoading} />\n </TabPanel>","tab !== 'references'","<Stack gap={4} flex={1} sizing=\"border\">\n <TabList gap={2}>\n <Tab\n aria-controls=\"details-panel\"\n icon={EditIcon}\n id=\"details-tab\"\n label=\"Details\"\n onClick={() => setTab('details')}\n selected={tab === 'details'}\n />\n <Tab\n aria-controls=\"references-panel\"\n icon={SearchIcon}\n id=\"references-tab\"\n label={`Used by ${references ? `(${references.length})` : ''}`}\n onClick={() => setTab('references')}\n selected={tab === 'references'}\n />\n </TabList>\n <TabPanel\n aria-labelledby=\"details-tab\"\n id=\"details-panel\"\n hidden={tab !== 'details'}\n style={{wordBreak: 'break-word'}}\n >\n <Stack gap={4}>\n <AssetInput\n label=\"Video title or file name\"\n description=\"Not visible to users. Useful for finding videos later.\"\n value={filename || ''}\n onInput={(e) => setFilename(e.currentTarget.value)}\n disabled={state !== 'idle'}\n />\n <Stack gap={3}>\n {displayInfo?.duration && (\n <IconInfo\n text={`Duration: ${displayInfo.duration}`}\n icon={ClockIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_resolution && (\n <IconInfo\n text={`Max Resolution: ${displayInfo.max_stored_resolution}`}\n icon={ResolutionIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_frame_rate && (\n <IconInfo\n text={`Frame rate: ${displayInfo.max_stored_frame_rate}`}\n icon={StopWatchIcon}\n size={2}\n />\n )}\n {displayInfo?.aspect_ratio && (\n <IconInfo\n text={`Aspect Ratio: ${displayInfo.aspect_ratio}`}\n icon={CropIcon}\n size={2}\n />\n )}\n <IconInfo\n text={`Uploaded on: ${displayInfo.createdAt.toLocaleDateString('en', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })}`}\n icon={CalendarIcon}\n size={2}\n />\n <IconInfo text={`Mux ID: \\n${displayInfo.id}`} icon={TagIcon} size={2} />\n <PlaybackIds playback_ids={displayInfo.playback_ids} />\n </Stack>\n </Stack>\n </TabPanel>\n <TabPanel\n aria-labelledby=\"references-tab\"\n id=\"references-panel\"\n hidden={tab !== 'references'}\n >\n <VideoReferences references={references} isLoaded={!referencesLoading} />\n </TabPanel>\n </Stack>","<Card\n padding={4}\n sizing=\"border\"\n style={{\n containerType: 'inline-size',\n }}\n >\n <Flex\n sizing=\"border\"\n gap={4}\n direction={['column', 'column', 'row']}\n align=\"flex-start\"\n ref={contentsRef}\n style={\n typeof containerHeight === 'number'\n ? {\n minHeight: containerHeight,\n }\n : undefined\n }\n >\n <Stack gap={4} flex={1} sizing=\"border\">\n <VideoPlayer asset={props.asset} autoPlay={props.asset.autoPlay || false} />\n {tab === 'details' && (\n <>\n <TextTracksManager\n asset={props.asset}\n iconOnly\n collapseTracks\n tracks={\n displayInfo?.text_tracks ||\n props.asset.data?.tracks?.filter(\n (track): track is MuxTextTrack => track.type === 'text',\n ) ||\n []\n }\n />\n <Mezzanine asset={props.asset} />\n </>\n )}\n </Stack>\n <Stack gap={4} flex={1} sizing=\"border\">\n <TabList gap={2}>\n <Tab\n aria-controls=\"details-panel\"\n icon={EditIcon}\n id=\"details-tab\"\n label=\"Details\"\n onClick={() => setTab('details')}\n selected={tab === 'details'}\n />\n <Tab\n aria-controls=\"references-panel\"\n icon={SearchIcon}\n id=\"references-tab\"\n label={`Used by ${references ? `(${references.length})` : ''}`}\n onClick={() => setTab('references')}\n selected={tab === 'references'}\n />\n </TabList>\n <TabPanel\n aria-labelledby=\"details-tab\"\n id=\"details-panel\"\n hidden={tab !== 'details'}\n style={{wordBreak: 'break-word'}}\n >\n <Stack gap={4}>\n <AssetInput\n label=\"Video title or file name\"\n description=\"Not visible to users. Useful for finding videos later.\"\n value={filename || ''}\n onInput={(e) => setFilename(e.currentTarget.value)}\n disabled={state !== 'idle'}\n />\n <Stack gap={3}>\n {displayInfo?.duration && (\n <IconInfo\n text={`Duration: ${displayInfo.duration}`}\n icon={ClockIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_resolution && (\n <IconInfo\n text={`Max Resolution: ${displayInfo.max_stored_resolution}`}\n icon={ResolutionIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_frame_rate && (\n <IconInfo\n text={`Frame rate: ${displayInfo.max_stored_frame_rate}`}\n icon={StopWatchIcon}\n size={2}\n />\n )}\n {displayInfo?.aspect_ratio && (\n <IconInfo\n text={`Aspect Ratio: ${displayInfo.aspect_ratio}`}\n icon={CropIcon}\n size={2}\n />\n )}\n <IconInfo\n text={`Uploaded on: ${displayInfo.createdAt.toLocaleDateString('en', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })}`}\n icon={CalendarIcon}\n size={2}\n />\n <IconInfo text={`Mux ID: \\n${displayInfo.id}`} icon={TagIcon} size={2} />\n <PlaybackIds playback_ids={displayInfo.playback_ids} />\n </Stack>\n </Stack>\n </TabPanel>\n <TabPanel\n aria-labelledby=\"references-tab\"\n id=\"references-panel\"\n hidden={tab !== 'references'}\n >\n <VideoReferences references={references} isLoaded={!referencesLoading} />\n </TabPanel>\n </Stack>\n </Flex>\n </Card>","<Dialog\n animate\n header={displayInfo.title}\n zOffset={DIALOGS_Z_INDEX}\n id=\"video-details-dialog\"\n onClose={handleClose}\n onClickOutside={handleClose}\n width={2}\n position=\"fixed\"\n footer={\n <Card padding={3}>\n <Flex justify=\"space-between\" align=\"center\">\n <Flex gap={2}>\n <Button\n icon={TrashIcon}\n fontSize={2}\n padding={3}\n mode=\"bleed\"\n text=\"Delete\"\n tone=\"critical\"\n onClick={() => setState('deleting')}\n disabled={isSaving || isResyncing}\n />\n <Button\n icon={SyncIcon}\n fontSize={2}\n padding={3}\n mode=\"bleed\"\n text=\"Resync\"\n tone=\"primary\"\n onClick={handleResync}\n disabled={isSaving || isResyncing}\n iconRight={isResyncing && Spinner}\n />\n </Flex>\n {modified && (\n <Button\n icon={CheckmarkIcon}\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Save and close\"\n tone=\"positive\"\n onClick={saveChanges}\n iconRight={isSaving && Spinner}\n disabled={isSaving || isResyncing}\n />\n )}\n </Flex>\n </Card>\n }\n >\n {/* DELETION DIALOG */}\n {state === 'deleting' && (\n <DeleteDialog\n asset={props.asset}\n cancelDelete={() => setState('idle')}\n referencesLoading={referencesLoading}\n references={references}\n succeededDeleting={() => {\n props.closeDialog()\n }}\n />\n )}\n\n {/* CONFIRM CLOSING DIALOG */}\n {state === 'closing' && (\n <Dialog\n animate\n header={'You have unsaved changes'}\n zOffset={DIALOGS_Z_INDEX}\n id=\"closing-video-details-dialog\"\n onClose={() => confirmClose(false)}\n onClickOutside={() => confirmClose(false)}\n width={1}\n position=\"fixed\"\n footer={\n <Card padding={3}>\n <Flex justify=\"space-between\" align=\"center\">\n <Button\n icon={ErrorOutlineIcon}\n fontSize={2}\n padding={3}\n text=\"Discard changes\"\n tone=\"critical\"\n onClick={() => confirmClose(true)}\n />\n {modified && (\n <Button\n icon={RevertIcon}\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Keep editing\"\n tone=\"primary\"\n onClick={() => confirmClose(false)}\n />\n )}\n </Flex>\n </Card>\n }\n >\n <Card padding={5}>\n <Stack style={{textAlign: 'center'}} gap={3}>\n <Heading size={2}>Unsaved changes will be lost</Heading>\n <Text size={2}>Are you sure you want to discard them?</Text>\n </Stack>\n </Card>\n </Dialog>\n )}\n <Card\n padding={4}\n sizing=\"border\"\n style={{\n containerType: 'inline-size',\n }}\n >\n <Flex\n sizing=\"border\"\n gap={4}\n direction={['column', 'column', 'row']}\n align=\"flex-start\"\n ref={contentsRef}\n style={\n typeof containerHeight === 'number'\n ? {\n minHeight: containerHeight,\n }\n : undefined\n }\n >\n <Stack gap={4} flex={1} sizing=\"border\">\n <VideoPlayer asset={props.asset} autoPlay={props.asset.autoPlay || false} />\n {tab === 'details' && (\n <>\n <TextTracksManager\n asset={props.asset}\n iconOnly\n collapseTracks\n tracks={\n displayInfo?.text_tracks ||\n props.asset.data?.tracks?.filter(\n (track): track is MuxTextTrack => track.type === 'text',\n ) ||\n []\n }\n />\n <Mezzanine asset={props.asset} />\n </>\n )}\n </Stack>\n <Stack gap={4} flex={1} sizing=\"border\">\n <TabList gap={2}>\n <Tab\n aria-controls=\"details-panel\"\n icon={EditIcon}\n id=\"details-tab\"\n label=\"Details\"\n onClick={() => setTab('details')}\n selected={tab === 'details'}\n />\n <Tab\n aria-controls=\"references-panel\"\n icon={SearchIcon}\n id=\"references-tab\"\n label={`Used by ${references ? `(${references.length})` : ''}`}\n onClick={() => setTab('references')}\n selected={tab === 'references'}\n />\n </TabList>\n <TabPanel\n aria-labelledby=\"details-tab\"\n id=\"details-panel\"\n hidden={tab !== 'details'}\n style={{wordBreak: 'break-word'}}\n >\n <Stack gap={4}>\n <AssetInput\n label=\"Video title or file name\"\n description=\"Not visible to users. Useful for finding videos later.\"\n value={filename || ''}\n onInput={(e) => setFilename(e.currentTarget.value)}\n disabled={state !== 'idle'}\n />\n <Stack gap={3}>\n {displayInfo?.duration && (\n <IconInfo\n text={`Duration: ${displayInfo.duration}`}\n icon={ClockIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_resolution && (\n <IconInfo\n text={`Max Resolution: ${displayInfo.max_stored_resolution}`}\n icon={ResolutionIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_frame_rate && (\n <IconInfo\n text={`Frame rate: ${displayInfo.max_stored_frame_rate}`}\n icon={StopWatchIcon}\n size={2}\n />\n )}\n {displayInfo?.aspect_ratio && (\n <IconInfo\n text={`Aspect Ratio: ${displayInfo.aspect_ratio}`}\n icon={CropIcon}\n size={2}\n />\n )}\n <IconInfo\n text={`Uploaded on: ${displayInfo.createdAt.toLocaleDateString('en', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })}`}\n icon={CalendarIcon}\n size={2}\n />\n <IconInfo text={`Mux ID: \\n${displayInfo.id}`} icon={TagIcon} size={2} />\n <PlaybackIds playback_ids={displayInfo.playback_ids} />\n </Stack>\n </Stack>\n </TabPanel>\n <TabPanel\n aria-labelledby=\"references-tab\"\n id=\"references-panel\"\n hidden={tab !== 'references'}\n >\n <VideoReferences references={references} isLoaded={!referencesLoading} />\n </TabPanel>\n </Stack>\n </Flex>\n </Card>\n </Dialog>","title","displayInfo.title","{playback_ids}: {playback_ids?: MuxPlaybackId[]}","playback_ids.map((entry) => (\n <IconInfo\n key={entry.id}\n text={`Playback ID [${policyToText(entry.policy)}]: ${entry.id}`}\n icon={TagIcon}\n size={2}\n />\n ))","(entry) => (\n <IconInfo\n key={entry.id}\n text={`Playback ID [${policyToText(entry.policy)}]: ${entry.id}`}\n icon={TagIcon}\n size={2}\n />\n )","<IconInfo text={'No Playback ID'} icon={TagIcon} size={2} />","_c","FormField","_Fragment","_temp","_temp2","Inline","Stack","3","displayInfo?.duration && (\n <IconInfo text={displayInfo.duration} icon={ClockIcon} size={1} muted />\n )","<IconInfo\n text={displayInfo.createdAt.toISOString().split('T')[0]!}\n icon={CalendarIcon}\n size={1}\n muted\n />","displayInfo.title != displayInfo.id.slice(0, 12) && (\n <IconInfo text={displayInfo.id.slice(0, 12)} icon={TagIcon} size={1} muted />\n )","2","displayInfo.title && (\n <Text\n size={1}\n weight=\"semibold\"\n style={{\n wordWrap: 'break-word',\n }}\n >\n {displayInfo.title}\n </Text>\n )","asset","<Inline gap={3}>\n {displayInfo?.duration && (\n <IconInfo text={displayInfo.duration} icon={ClockIcon} size={1} muted />\n )}\n <IconInfo\n text={displayInfo.createdAt.toISOString().split('T')[0]!}\n icon={CalendarIcon}\n size={1}\n muted\n />\n {displayInfo.title != displayInfo.id.slice(0, 12) && (\n <IconInfo text={displayInfo.id.slice(0, 12)} icon={TagIcon} size={1} muted />\n )}\n </Inline>","<Stack gap={2}>\n {displayInfo.title && (\n <Text\n size={1}\n weight=\"semibold\"\n style={{\n wordWrap: 'break-word',\n }}\n >\n {displayInfo.title}\n </Text>\n )}\n <Inline gap={3}>\n {displayInfo?.duration && (\n <IconInfo text={displayInfo.duration} icon={ClockIcon} size={1} muted />\n )}\n <IconInfo\n text={displayInfo.createdAt.toISOString().split('T')[0]!}\n icon={CalendarIcon}\n size={1}\n muted\n />\n {displayInfo.title != displayInfo.id.slice(0, 12) && (\n <IconInfo text={displayInfo.id.slice(0, 12)} icon={TagIcon} size={1} muted />\n )}\n </Inline>\n </Stack>","_c","{\n onSelect,\n onEdit,\n asset,\n}: {\n onSelect?: (asset: VideoAssetDocument) => void\n onEdit?: (asset: VideoAssetDocument) => void\n asset: VideoAssetDocument\n}","() => onSelect?.(asset)","useCallback(() => onSelect?.(asset), [onSelect, asset])","() => onEdit?.(asset)","useCallback(() => onEdit?.(asset), [onEdit, asset])","getPlaybackPolicy(asset)","() => {\n if (playbackPolicy?.policy === 'drm' && !hasShownWarning) {\n setRenderVideo('pre-render-warn')\n } else {\n setRenderVideo('render-video')\n }\n }","policy","{\n position: 'relative',\n }","playbackPolicy?.policy === 'signed' && (\n <Tooltip\n animate\n content={\n <Card padding={2} radius={2}>\n <IconInfo icon={LockIcon} text=\"Signed playback policy\" size={2} />\n </Card>\n }\n placement=\"right\"\n fallbackPlacements={['top', 'bottom']}\n portal\n >\n <Card\n tone=\"caution\"\n style={{\n borderRadius: '100%',\n position: 'absolute',\n left: '1em',\n top: '1em',\n zIndex: 11,\n }}\n padding={2}\n border\n >\n <Text muted size={1}>\n <LockIcon />\n </Text>\n </Card>\n </Tooltip>\n )","playbackPolicy?.policy === 'drm' && (\n <Tooltip\n animate\n content={\n <Card padding={2} radius={2}>\n <IconInfo icon={LockIcon} text=\"DRM playback policy\" size={2} />\n </Card>\n }\n placement=\"right\"\n fallbackPlacements={['top', 'bottom']}\n portal\n >\n <Card\n tone=\"caution\"\n style={{\n borderRadius: '0.25rem',\n position: 'absolute',\n left: '1em',\n top: '1em',\n zIndex: 11,\n }}\n padding={2}\n border\n >\n <Text muted size={1} weight=\"semibold\" style={{color: 'var(--card-icon-color)'}}>\n DRM\n </Text>\n </Card>\n </Tooltip>\n )","{\n gridTemplateRows: 'min-content min-content 1fr',\n }","renderVideo === 'pre-render-warn' && (\n <DRMWarningDialog\n onClose={() => {\n setRenderVideo('render-video')\n }}\n />\n )","renderVideo === 'render-video' ? (\n <VideoPlayer asset={asset} autoPlay forceAspectRatio={THUMBNAIL_ASPECT_RATIO} />\n ) : (\n <PlayButton onClick={onClickPlay}>\n <div data-play>\n <PlayIcon />\n </div>\n {assetIsAudio(asset) ? (\n <div\n style={{\n aspectRatio: THUMBNAIL_ASPECT_RATIO,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <AudioIcon width=\"3em\" height=\"3em\" />\n </div>\n ) : (\n <VideoThumbnail asset={asset} />\n )}\n </PlayButton>\n )","<VideoMetadata asset={asset} />","{\n display: 'flex',\n width: '100%',\n alignItems: 'flex-end',\n justifyContent: 'flex-start',\n gap: '.35rem',\n }","onSelect && (\n <Button\n icon={CheckmarkIcon}\n fontSize={2}\n padding={2}\n mode=\"ghost\"\n text=\"Select\"\n style={{flex: 1}}\n tone=\"positive\"\n onClick={select}\n />\n )","{flex: 1}","<Button\n icon={EditIcon}\n fontSize={2}\n padding={2}\n mode=\"ghost\"\n text=\"Details\"\n style={{flex: 1}}\n onClick={edit}\n />","<div\n style={{\n display: 'flex',\n width: '100%',\n alignItems: 'flex-end',\n justifyContent: 'flex-start',\n gap: '.35rem',\n }}\n >\n {onSelect && (\n <Button\n icon={CheckmarkIcon}\n fontSize={2}\n padding={2}\n mode=\"ghost\"\n text=\"Select\"\n style={{flex: 1}}\n tone=\"positive\"\n onClick={select}\n />\n )}\n <Button\n icon={EditIcon}\n fontSize={2}\n padding={2}\n mode=\"ghost\"\n text=\"Details\"\n style={{flex: 1}}\n onClick={edit}\n />\n </div>","<Stack\n gap={3}\n height=\"fill\"\n style={{\n gridTemplateRows: 'min-content min-content 1fr',\n }}\n >\n {renderVideo === 'pre-render-warn' && (\n <DRMWarningDialog\n onClose={() => {\n setRenderVideo('render-video')\n }}\n />\n )}\n {renderVideo === 'render-video' ? (\n <VideoPlayer asset={asset} autoPlay forceAspectRatio={THUMBNAIL_ASPECT_RATIO} />\n ) : (\n <PlayButton onClick={onClickPlay}>\n <div data-play>\n <PlayIcon />\n </div>\n {assetIsAudio(asset) ? (\n <div\n style={{\n aspectRatio: THUMBNAIL_ASPECT_RATIO,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <AudioIcon width=\"3em\" height=\"3em\" />\n </div>\n ) : (\n <VideoThumbnail asset={asset} />\n )}\n </PlayButton>\n )}\n <VideoMetadata asset={asset} />\n <div\n style={{\n display: 'flex',\n width: '100%',\n alignItems: 'flex-end',\n justifyContent: 'flex-start',\n gap: '.35rem',\n }}\n >\n {onSelect && (\n <Button\n icon={CheckmarkIcon}\n fontSize={2}\n padding={2}\n mode=\"ghost\"\n text=\"Select\"\n style={{flex: 1}}\n tone=\"positive\"\n onClick={select}\n />\n )}\n <Button\n icon={EditIcon}\n fontSize={2}\n padding={2}\n mode=\"ghost\"\n text=\"Details\"\n style={{flex: 1}}\n onClick={edit}\n />\n </div>\n </Stack>","<Card\n border\n padding={2}\n sizing=\"border\"\n radius={2}\n style={{\n position: 'relative',\n }}\n >\n {playbackPolicy?.policy === 'signed' && (\n <Tooltip\n animate\n content={\n <Card padding={2} radius={2}>\n <IconInfo icon={LockIcon} text=\"Signed playback policy\" size={2} />\n </Card>\n }\n placement=\"right\"\n fallbackPlacements={['top', 'bottom']}\n portal\n >\n <Card\n tone=\"caution\"\n style={{\n borderRadius: '100%',\n position: 'absolute',\n left: '1em',\n top: '1em',\n zIndex: 11,\n }}\n padding={2}\n border\n >\n <Text muted size={1}>\n <LockIcon />\n </Text>\n </Card>\n </Tooltip>\n )}\n {playbackPolicy?.policy === 'drm' && (\n <Tooltip\n animate\n content={\n <Card padding={2} radius={2}>\n <IconInfo icon={LockIcon} text=\"DRM playback policy\" size={2} />\n </Card>\n }\n placement=\"right\"\n fallbackPlacements={['top', 'bottom']}\n portal\n >\n <Card\n tone=\"caution\"\n style={{\n borderRadius: '0.25rem',\n position: 'absolute',\n left: '1em',\n top: '1em',\n zIndex: 11,\n }}\n padding={2}\n border\n >\n <Text muted size={1} weight=\"semibold\" style={{color: 'var(--card-icon-color)'}}>\n DRM\n </Text>\n </Card>\n </Tooltip>\n )}\n <Stack\n gap={3}\n height=\"fill\"\n style={{\n gridTemplateRows: 'min-content min-content 1fr',\n }}\n >\n {renderVideo === 'pre-render-warn' && (\n <DRMWarningDialog\n onClose={() => {\n setRenderVideo('render-video')\n }}\n />\n )}\n {renderVideo === 'render-video' ? (\n <VideoPlayer asset={asset} autoPlay forceAspectRatio={THUMBNAIL_ASPECT_RATIO} />\n ) : (\n <PlayButton onClick={onClickPlay}>\n <div data-play>\n <PlayIcon />\n </div>\n {assetIsAudio(asset) ? (\n <div\n style={{\n aspectRatio: THUMBNAIL_ASPECT_RATIO,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <AudioIcon width=\"3em\" height=\"3em\" />\n </div>\n ) : (\n <VideoThumbnail asset={asset} />\n )}\n </PlayButton>\n )}\n <VideoMetadata asset={asset} />\n <div\n style={{\n display: 'flex',\n width: '100%',\n alignItems: 'flex-end',\n justifyContent: 'flex-start',\n gap: '.35rem',\n }}\n >\n {onSelect && (\n <Button\n icon={CheckmarkIcon}\n fontSize={2}\n padding={2}\n mode=\"ghost\"\n text=\"Select\"\n style={{flex: 1}}\n tone=\"positive\"\n onClick={select}\n />\n )}\n <Button\n icon={EditIcon}\n fontSize={2}\n padding={2}\n mode=\"ghost\"\n text=\"Details\"\n style={{flex: 1}}\n onClick={edit}\n />\n </div>\n </Stack>\n </Card>","_c","{onSelect, config}: VideosBrowserProps","assets.find((a) => a._id === editedAsset?._id) || editedAsset","editedAsset?._id","useMemo(\n () => assets.find((a) => a._id === editedAsset?._id) || editedAsset,\n [editedAsset, assets],\n )","{minHeight: '50vh'}","(e: InputEvent<HTMLInputElement>) => setSearchQuery(e.currentTarget.value)","<TextInput\n value={searchQuery}\n icon={SearchIcon}\n onInput={(e: InputEvent<HTMLInputElement>) => setSearchQuery(e.currentTarget.value)}\n placeholder=\"Search videos\"\n />","<SelectSortOptions setSort={setSort} sort={sort} />","<PageSelector page={page} setPage={setPage} total={pageTotal} />","<Flex align=\"center\" gap={3}>\n <TextInput\n value={searchQuery}\n icon={SearchIcon}\n onInput={(e: InputEvent<HTMLInputElement>) => setSearchQuery(e.currentTarget.value)}\n placeholder=\"Search videos\"\n />\n <SelectSortOptions setSort={setSort} sort={sort} />\n <PageSelector page={page} setPage={setPage} total={pageTotal} />\n </Flex>","placement === 'tool' && (\n <Inline gap={2}>\n <ImportVideosFromMux />\n <ResyncMetadata />\n <ConfigureApi />\n </Inline>\n )","<Flex justify=\"space-between\" align=\"center\">\n <Flex align=\"center\" gap={3}>\n <TextInput\n value={searchQuery}\n icon={SearchIcon}\n onInput={(e: InputEvent<HTMLInputElement>) => setSearchQuery(e.currentTarget.value)}\n placeholder=\"Search videos\"\n />\n <SelectSortOptions setSort={setSort} sort={sort} />\n <PageSelector page={page} setPage={setPage} total={pageTotal} />\n </Flex>\n {placement === 'tool' && (\n <Inline gap={2}>\n <ImportVideosFromMux />\n <ResyncMetadata />\n <ConfigureApi />\n </Inline>\n )}\n </Flex>","assets?.length > 0 && (\n <Label muted>\n {assets.length} video{assets.length > 1 ? 's' : null}{' '}\n {searchQuery ? `matching \"${searchQuery}\"` : 'found'}\n </Label>\n )","length","{\n gridTemplateColumns: 'repeat(auto-fill, minmax(250px, 1fr))',\n }","assets.slice(pageStart, pageEnd).map((asset) => (\n <VideoInBrowser\n key={asset._id}\n asset={asset}\n onEdit={setEditedAsset}\n onSelect={onSelect}\n />\n ))","(asset) => (\n <VideoInBrowser\n key={asset._id}\n asset={asset}\n onEdit={setEditedAsset}\n onSelect={onSelect}\n />\n )","<Grid\n gap={2}\n style={{\n gridTemplateColumns: 'repeat(auto-fill, minmax(250px, 1fr))',\n }}\n >\n {assets.slice(pageStart, pageEnd).map((asset) => (\n <VideoInBrowser\n key={asset._id}\n asset={asset}\n onEdit={setEditedAsset}\n onSelect={onSelect}\n />\n ))}\n </Grid>","<Stack gap={3}>\n {assets?.length > 0 && (\n <Label muted>\n {assets.length} video{assets.length > 1 ? 's' : null}{' '}\n {searchQuery ? `matching \"${searchQuery}\"` : 'found'}\n </Label>\n )}\n <Grid\n gap={2}\n style={{\n gridTemplateColumns: 'repeat(auto-fill, minmax(250px, 1fr))',\n }}\n >\n {assets.slice(pageStart, pageEnd).map((asset) => (\n <VideoInBrowser\n key={asset._id}\n asset={asset}\n onEdit={setEditedAsset}\n onSelect={onSelect}\n />\n ))}\n </Grid>\n </Stack>","isLoading && <SpinnerBox />","!isLoading && assets.length === 0 && (\n <Card marginY={4} paddingX={4} paddingY={6} border radius={2} tone=\"transparent\">\n <Text align=\"center\" muted size={3}>\n {searchQuery ? `No videos found for \"${searchQuery}\"` : 'No videos in this dataset'}\n </Text>\n </Card>\n )","<Stack padding={4} gap={4} style={{minHeight: '50vh'}}>\n <Flex justify=\"space-between\" align=\"center\">\n <Flex align=\"center\" gap={3}>\n <TextInput\n value={searchQuery}\n icon={SearchIcon}\n onInput={(e: InputEvent<HTMLInputElement>) => setSearchQuery(e.currentTarget.value)}\n placeholder=\"Search videos\"\n />\n <SelectSortOptions setSort={setSort} sort={sort} />\n <PageSelector page={page} setPage={setPage} total={pageTotal} />\n </Flex>\n {placement === 'tool' && (\n <Inline gap={2}>\n <ImportVideosFromMux />\n <ResyncMetadata />\n <ConfigureApi />\n </Inline>\n )}\n </Flex>\n <Stack gap={3}>\n {assets?.length > 0 && (\n <Label muted>\n {assets.length} video{assets.length > 1 ? 's' : null}{' '}\n {searchQuery ? `matching \"${searchQuery}\"` : 'found'}\n </Label>\n )}\n <Grid\n gap={2}\n style={{\n gridTemplateColumns: 'repeat(auto-fill, minmax(250px, 1fr))',\n }}\n >\n {assets.slice(pageStart, pageEnd).map((asset) => (\n <VideoInBrowser\n key={asset._id}\n asset={asset}\n onEdit={setEditedAsset}\n onSelect={onSelect}\n />\n ))}\n </Grid>\n </Stack>\n {isLoading && <SpinnerBox />}\n\n {!isLoading && assets.length === 0 && (\n <Card marginY={4} paddingX={4} paddingY={6} border radius={2} tone=\"transparent\">\n <Text align=\"center\" muted size={3}>\n {searchQuery ? `No videos found for \"${searchQuery}\"` : 'No videos in this dataset'}\n </Text>\n </Card>\n )}\n </Stack>","freshEditedAsset && (\n <VideoDetails closeDialog={() => setEditedAsset(null)} asset={freshEditedAsset} />\n )","<DrmPlaybackWarningContextProvider config={config}>\n <Stack padding={4} gap={4} style={{minHeight: '50vh'}}>\n <Flex justify=\"space-between\" align=\"center\">\n <Flex align=\"center\" gap={3}>\n <TextInput\n value={searchQuery}\n icon={SearchIcon}\n onInput={(e: InputEvent<HTMLInputElement>) => setSearchQuery(e.currentTarget.value)}\n placeholder=\"Search videos\"\n />\n <SelectSortOptions setSort={setSort} sort={sort} />\n <PageSelector page={page} setPage={setPage} total={pageTotal} />\n </Flex>\n {placement === 'tool' && (\n <Inline gap={2}>\n <ImportVideosFromMux />\n <ResyncMetadata />\n <ConfigureApi />\n </Inline>\n )}\n </Flex>\n <Stack gap={3}>\n {assets?.length > 0 && (\n <Label muted>\n {assets.length} video{assets.length > 1 ? 's' : null}{' '}\n {searchQuery ? `matching \"${searchQuery}\"` : 'found'}\n </Label>\n )}\n <Grid\n gap={2}\n style={{\n gridTemplateColumns: 'repeat(auto-fill, minmax(250px, 1fr))',\n }}\n >\n {assets.slice(pageStart, pageEnd).map((asset) => (\n <VideoInBrowser\n key={asset._id}\n asset={asset}\n onEdit={setEditedAsset}\n onSelect={onSelect}\n />\n ))}\n </Grid>\n </Stack>\n {isLoading && <SpinnerBox />}\n\n {!isLoading && assets.length === 0 && (\n <Card marginY={4} paddingX={4} paddingY={6} border radius={2} tone=\"transparent\">\n <Text align=\"center\" muted size={3}>\n {searchQuery ? `No videos found for \"${searchQuery}\"` : 'No videos in this dataset'}\n </Text>\n </Card>\n )}\n </Stack>\n {freshEditedAsset && (\n <VideoDetails closeDialog={() => setEditedAsset(null)} asset={freshEditedAsset} />\n )}\n </DrmPlaybackWarningContextProvider>","_c","<VideosBrowser config={config} />","<MuxApiHostProvider muxApiHost={config.muxApiHost}>\n <VideosBrowser config={config} />\n </MuxApiHostProvider>","muxApiHost","_c","!config?.allowedRolesForConfiguration?.length ||\n user?.roles?.some((role) => config.allowedRolesForConfiguration.includes(role.name))","config?.allowedRolesForConfiguration?.length","roles","{hasConfigAccess}","_c","useMemo(() => {\n // Legacy: If static_renditions has a status field, it was created with mp4_support (deprecated)\n // We don't process this old format, just return false\n // Note: 'disabled' status is valid in the new format when no renditions were requested\n if (\n asset?.data?.static_renditions?.status &&\n asset?.data?.static_renditions?.status !== 'disabled'\n ) {\n return false\n }\n\n const files = asset?.data?.static_renditions?.files\n if (!files || files.length === 0) {\n return false\n }\n return files.some((file) => file.status === 'preparing')\n }, [asset?.data?.static_renditions?.status, asset?.data?.static_renditions?.files])","(file) => file.status === 'preparing'","async () => {\n try {\n const {data} = await getMuxAddonClient(client).request<{data: MuxAsset}>({\n url: `/addons/mux/assets/${dataset}/data/${asset!.assetId}`,\n withCredentials: true,\n method: 'GET',\n query: PLUGIN_VERSION_QUERY,\n })\n if (!asset?._id || !data) return\n await client\n .patch(asset._id)\n .set({status: data.status, data: addKeysToMuxData(data)})\n .commit({returnDocuments: false})\n errorLoggedRef.current = false\n } catch (error) {\n // Input re-throws `poll.error`, so a background polling failure would\n // crash the whole field. Swallow it instead.\n if (!errorLoggedRef.current) {\n errorLoggedRef.current = true\n console.error('[sanity-plugin-mux-input] Mux polling failed', {\n assetId: asset?.assetId,\n documentId: asset?._id,\n error,\n })\n }\n }\n }","asset!.assetId","error","{refreshInterval: 2000, refreshWhenHidden: true, dedupingInterval: 1000}","_c","useClient","_temp","{\n // oxlint-disable-next-line no-unstable-nested-components\n onDidCatch: (err, errorInfo) => {\n console.group(err.toString())\n console.groupCollapsed('console.error')\n console.error(err)\n console.groupEnd()\n if (err.stack) {\n console.groupCollapsed('error.stack')\n console.log(err.stack)\n console.groupEnd()\n }\n if (errorInfo?.componentStack) {\n console.groupCollapsed('errorInfo.componentStack')\n console.log(errorInfo.componentStack)\n console.groupEnd()\n }\n console.groupEnd()\n pushToast({\n status: 'error',\n title: 'Plugin crashed',\n description: (\n <Flex align=\"center\">\n <Inline gap={1}>\n An error happened while rendering\n <Button\n padding={1}\n fontSize={1}\n style={{transform: 'translateY(1px)'}}\n mode=\"ghost\"\n text={schemaType.title}\n onClick={() => {\n if (errorRef.current) {\n scrollIntoView(errorRef.current, {\n behavior: 'smooth',\n scrollMode: 'if-needed',\n block: 'center',\n })\n }\n }}\n />\n </Inline>\n </Flex>\n ),\n })\n },\n }","schemaType.title","() => {\n // Purge request cache before retrying, otherwise the cached errors will rethrow\n clear([name])\n\n reset()\n }","useCallback(() => {\n // Purge request cache before retrying, otherwise the cached errors will rethrow\n clear([name])\n\n reset()\n }, [reset])","[2, 3, 4, 4]","<Heading as=\"h1\">\n The <code>{name}</code> plugin crashed\n </Heading>","error?.message && (\n <Card padding={3} tone=\"critical\" shadow={1} radius={2}>\n <Text>{error.message}</Text>\n </Card>\n )","error?.message","<Inline>\n <Button onClick={handleRetry} text=\"Retry\" />\n </Inline>","<Card ref={errorRef} paddingX={[2, 3, 4, 4]} height=\"fill\" shadow={1} overflow=\"auto\">\n <Flex justify=\"flex-start\" align=\"center\" height=\"fill\">\n <Grid gridTemplateColumns={1} gap={[2, 3, 4, 4]}>\n <Heading as=\"h1\">\n The <code>{name}</code> plugin crashed\n </Heading>\n {error?.message && (\n <Card padding={3} tone=\"critical\" shadow={1} radius={2}>\n <Text>{error.message}</Text>\n </Card>\n )}\n <Inline>\n <Button onClick={handleRetry} text=\"Retry\" />\n </Inline>\n </Grid>\n </Flex>\n </Card>","<ErrorBoundary>{children}</ErrorBoundary>","_c","{padding: 1}","{aspectRatio: '16/9', width: '100%', borderRadius: '1px'}","<Spinner muted />","<div style={{padding: 1}}>\n <Card\n shadow={1}\n sizing=\"border\"\n style={{aspectRatio: '16/9', width: '100%', borderRadius: '1px'}}\n >\n <Flex align=\"center\" direction=\"column\" height=\"fill\" justify=\"center\">\n <Spinner muted />\n <Box marginTop={3}>\n <Text align=\"center\" muted size={1}>\n Loading…\n </Text>\n </Box>\n </Flex>\n </Card>\n </div>","_c","() => setDialogState('secrets')","useCallback(() => setDialogState('secrets'), [setDialogState])","{padding: 2}","{\n aspectRatio: '16/9',\n width: '100%',\n boxShadow: 'var(--card-bg-color) 0 0 0 2px',\n }","[2, 3, 4, 4]","<Inline paddingY={1}>\n <div style={{height: '32px'}}>\n <MuxLogo />\n </div>\n </Inline>","<Inline paddingY={1}>\n <Heading size={[0, 1, 2, 2]}>\n Upload and preview videos directly from your studio.\n </Heading>\n </Inline>","<>\n <div style={{padding: 2}}>\n <Card\n display=\"flex\"\n sizing=\"border\"\n style={{\n aspectRatio: '16/9',\n width: '100%',\n boxShadow: 'var(--card-bg-color) 0 0 0 2px',\n }}\n paddingX={[2, 3, 4, 4]}\n radius={1}\n tone=\"transparent\"\n >\n <Flex justify=\"flex-start\" align=\"center\">\n <Grid gridTemplateColumns={1} gap={[2, 3, 4, 4]}>\n <Inline paddingY={1}>\n <div style={{height: '32px'}}>\n <MuxLogo />\n </div>\n </Inline>\n <Inline paddingY={1}>\n <Heading size={[0, 1, 2, 2]}>\n Upload and preview videos directly from your studio.\n </Heading>\n </Inline>\n <Inline paddingY={1}>\n {hasConfigAccess ? (\n <Button mode=\"ghost\" icon={PlugIcon} text=\"Configure API\" onClick={handleOpen} />\n ) : (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"critical\">\n <Text>\n You do not have access to configure the Mux API. Please contact your\n administrator.\n </Text>\n </Card>\n )}\n </Inline>\n </Grid>\n </Flex>\n </Card>\n </div>\n </>","_c","_Fragment","uuid","generateUuid","{\n asset: selectedAsset,\n onChange,\n setDialogState,\n config,\n}: Props","(chosenAsset) => {\n if (!chosenAsset?._id) {\n onChange(PatchEvent.from([unset(['asset'])]))\n }\n if (chosenAsset._id !== selectedAsset?._id) {\n onChange(\n PatchEvent.from([\n setIfMissing({asset: {}, _type: 'mux.video'}),\n set({_type: 'reference', _weak: true, _ref: chosenAsset._id}, ['asset']),\n ]),\n )\n }\n setDialogState(false)\n }","_id","useCallback<Required<VideosBrowserProps>['onSelect']>(\n (chosenAsset) => {\n if (!chosenAsset?._id) {\n onChange(PatchEvent.from([unset(['asset'])]))\n }\n if (chosenAsset._id !== selectedAsset?._id) {\n onChange(\n PatchEvent.from([\n setIfMissing({asset: {}, _type: 'mux.video'}),\n set({_type: 'reference', _weak: true, _ref: chosenAsset._id}, ['asset']),\n ]),\n )\n }\n setDialogState(false)\n },\n [onChange, setDialogState, selectedAsset],\n )","<VideosBrowser onSelect={handleSelect} config={config} />","_c","{\n setDialogState,\n asset,\n onChange,\n config,\n}: Pick<SelectAssetProps, 'onChange' | 'asset' | 'config'> & {\n setDialogState: SetDialogState\n}","() => setDialogState(false)","useCallback(() => setDialogState(false), [setDialogState])","<SelectAsset\n config={config}\n asset={asset}\n onChange={onChange}\n setDialogState={setDialogState}\n />","<StyledDialog\n __unstable_autoFocus\n header=\"Select video\"\n id={id}\n onClose={handleClose}\n width={2}\n >\n <SelectAsset\n config={config}\n asset={asset}\n onChange={onChange}\n setDialogState={setDialogState}\n />\n </StyledDialog>","_c","SelectAsset","() => {\n if (!asset) {\n return\n }\n onChange(PatchEvent.from(unset()))\n if (asset.assetId) {\n void deleteAssetOnMux(client, asset.assetId)\n }\n if (asset._id) {\n void client.delete(asset._id)\n }\n }","useCallback(() => {\n if (!asset) {\n return\n }\n onChange(PatchEvent.from(unset()))\n if (asset.assetId) {\n void deleteAssetOnMux(client, asset.assetId)\n }\n if (asset._id) {\n void client.delete(asset._id)\n }\n }, [asset, client, onChange])","_c","useClient","{\n progress = 100,\n onCancel,\n filename,\n text = 'Uploading',\n}: {\n progress: number\n filename?: React.ReactNode\n onCancel?: React.MouseEventHandler<HTMLButtonElement>\n text?: React.ReactNode\n}","progress = 100","text = 'Uploading'","[3, 3, 2, 2]","['column', 'column', 'row']","<CodeWrapper size={1}>{filename ? filename : '...'}</CodeWrapper>","filename ? filename : '...'","<Flex justify=\"center\" gap={[3, 3, 2, 2]} direction={['column', 'column', 'row']}>\n <Text size={1}>\n <Inline gap={2}>\n {text}\n <CodeWrapper size={1}>{filename ? filename : '...'}</CodeWrapper>\n </Inline>\n </Text>\n </Flex>","<Card marginTop={3} radius={5} shadow={1}>\n <LinearProgress value={progress} />\n </Card>","<LeftSection>\n <Flex justify=\"center\" gap={[3, 3, 2, 2]} direction={['column', 'column', 'row']}>\n <Text size={1}>\n <Inline gap={2}>\n {text}\n <CodeWrapper size={1}>{filename ? filename : '...'}</CodeWrapper>\n </Inline>\n </Text>\n </Flex>\n\n <Card marginTop={3} radius={5} shadow={1}>\n <LinearProgress value={progress} />\n </Card>\n </LeftSection>","onCancel ? (\n <Button\n fontSize={2}\n text=\"Cancel upload\"\n mode=\"ghost\"\n tone=\"critical\"\n onClick={onCancel}\n disabled={isCancelDisabled}\n />\n ) : null","<CardWrapper tone=\"primary\" padding={4} border height=\"fill\">\n <FlexWrapper align=\"center\" justify=\"space-between\" height=\"fill\" direction=\"row\" gap={2}>\n <LeftSection>\n <Flex justify=\"center\" gap={[3, 3, 2, 2]} direction={['column', 'column', 'row']}>\n <Text size={1}>\n <Inline gap={2}>\n {text}\n <CodeWrapper size={1}>{filename ? filename : '...'}</CodeWrapper>\n </Inline>\n </Text>\n </Flex>\n\n <Card marginTop={3} radius={5} shadow={1}>\n <LinearProgress value={progress} />\n </Card>\n </LeftSection>\n\n {onCancel ? (\n <Button\n fontSize={2}\n text=\"Cancel upload\"\n mode=\"ghost\"\n tone=\"critical\"\n onClick={onCancel}\n disabled={isCancelDisabled}\n />\n ) : null}\n </FlexWrapper>\n </CardWrapper>","_c","gap = 3","(event: React.ChangeEvent<HTMLInputElement>) => {\n if (onSelect && event.target.files) {\n onSelect(Array.from(event.target.files))\n }\n }","useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n if (onSelect && event.target.files) {\n onSelect(Array.from(event.target.files))\n }\n },\n [onSelect],\n )","Icon && (\n <Box marginRight={text ? gap : undefined}>\n <Text size={fontSize}>\n {isValidElement(Icon) && Icon}\n {isValidElementType(Icon) && <Icon />}\n </Text>\n </Box>\n )","text && (\n <Text align={textAlign} size={fontSize} textOverflow=\"ellipsis\">\n {text}\n </Text>\n )","<Flex align=\"center\" justify=\"flex-start\">\n {/* Icon */}\n {Icon && (\n <Box marginRight={text ? gap : undefined}>\n <Text size={fontSize}>\n {isValidElement(Icon) && Icon}\n {isValidElementType(Icon) && <Icon />}\n </Text>\n </Box>\n )}\n\n {/* Text */}\n {text && (\n <Text align={textAlign} size={fontSize} textOverflow=\"ellipsis\">\n {text}\n </Text>\n )}\n </Flex>","<input\n data-testid=\"file-button-input\"\n accept={accept}\n capture={capture}\n id={id}\n multiple={multiple}\n onChange={handleChange}\n type=\"file\"\n value=\"\"\n disabled={disabled}\n />","<FileButton {...rest} htmlFor={id} disabled={disabled} ref={ref}>\n {content}\n\n {/* Visibly hidden input */}\n <input\n data-testid=\"file-button-input\"\n accept={accept}\n capture={capture}\n id={id}\n multiple={multiple}\n onChange={handleChange}\n type=\"file\"\n value=\"\"\n disabled={disabled}\n />\n </FileButton>","_c","{showToast: true}","() => onChange(PatchEvent.from(unset([])))","useCallback(() => onChange(PatchEvent.from(unset([]))), [onChange])","async () => {\n setOpen(false)\n await resyncAsset(asset)\n }","useCallback(async () => {\n setOpen(false)\n await resyncAsset(asset)\n }, [resyncAsset, asset])","() => {\n if (open && dialogState) {\n // oxlint-disable-next-line react/set-state-in-effect\n setOpen(false)\n }\n }","[dialogState, open]","() => setOpen(false)","() => [menuElement]","isSigned && (\n <Tooltip\n animate\n content={\n <Box padding={2}>\n <Text muted size={1}>\n Signed playback policy\n </Text>\n </Box>\n }\n placement=\"right\"\n portal\n >\n <LockCard radius={2} margin={2} scheme=\"dark\" tone=\"positive\">\n <LockButton icon={LockIcon} mode=\"bleed\" tone=\"positive\" />\n </LockCard>\n </Tooltip>\n )","<Box padding={2}>\n <Label muted size={1}>\n Replace\n </Label>\n </Box>","<FileInputMenuItem\n accept={accept}\n icon={UploadIcon}\n onSelect={onSelect}\n text=\"Upload\"\n disabled={readOnly}\n fontSize={1}\n />","<MenuItem\n icon={SearchIcon}\n text=\"Browse\"\n onClick={() => setDialogState('select-video')}\n />","isVideoAsset(asset) && (\n <>\n <MenuItem\n icon={ImageIcon}\n text=\"Thumbnail\"\n onClick={() => setDialogState('edit-thumbnail')}\n />\n <MenuItem\n icon={TranslateIcon}\n text=\"Captions\"\n onClick={() => setDialogState('edit-captions')}\n />\n <MenuItem\n icon={SyncIcon}\n text=\"Resync from Mux\"\n onClick={handleResync}\n disabled={readOnly || isResyncing}\n />\n </>\n )","<MenuDivider />","<MenuItem\n icon={DownloadIcon}\n text=\"Mezzanine\"\n onClick={() => setDialogState('mezzanine')}\n />","hasConfigAccess && (\n <>\n <MenuItem\n icon={PlugIcon}\n text=\"Configure API\"\n onClick={() => setDialogState('secrets')}\n />\n <MenuDivider />\n </>\n )","<MenuItem\n tone=\"critical\"\n icon={ResetIcon}\n text=\"Clear field\"\n onClick={onReset}\n disabled={readOnly}\n />","<Menu ref={setMenuRef}>\n <Box padding={2}>\n <Label muted size={1}>\n Replace\n </Label>\n </Box>\n <FileInputMenuItem\n accept={accept}\n icon={UploadIcon}\n onSelect={onSelect}\n text=\"Upload\"\n disabled={readOnly}\n fontSize={1}\n />\n <MenuItem\n icon={SearchIcon}\n text=\"Browse\"\n onClick={() => setDialogState('select-video')}\n />\n {isVideoAsset(asset) && (\n <>\n <MenuItem\n icon={ImageIcon}\n text=\"Thumbnail\"\n onClick={() => setDialogState('edit-thumbnail')}\n />\n <MenuItem\n icon={TranslateIcon}\n text=\"Captions\"\n onClick={() => setDialogState('edit-captions')}\n />\n <MenuItem\n icon={SyncIcon}\n text=\"Resync from Mux\"\n onClick={handleResync}\n disabled={readOnly || isResyncing}\n />\n </>\n )}\n <MenuDivider />\n <MenuItem\n icon={DownloadIcon}\n text=\"Mezzanine\"\n onClick={() => setDialogState('mezzanine')}\n />\n <MenuDivider />\n {hasConfigAccess && (\n <>\n <MenuItem\n icon={PlugIcon}\n text=\"Configure API\"\n onClick={() => setDialogState('secrets')}\n />\n <MenuDivider />\n </>\n )}\n <MenuItem\n tone=\"critical\"\n icon={ResetIcon}\n text=\"Clear field\"\n onClick={onReset}\n disabled={readOnly}\n />\n </Menu>","<Button\n icon={EllipsisHorizontalIcon}\n mode=\"ghost\"\n fontSize={1}\n onClick={() => {\n setDialogState(false)\n setOpen(true)\n }}\n />","<Popover\n animate\n content={\n <Menu ref={setMenuRef}>\n <Box padding={2}>\n <Label muted size={1}>\n Replace\n </Label>\n </Box>\n <FileInputMenuItem\n accept={accept}\n icon={UploadIcon}\n onSelect={onSelect}\n text=\"Upload\"\n disabled={readOnly}\n fontSize={1}\n />\n <MenuItem\n icon={SearchIcon}\n text=\"Browse\"\n onClick={() => setDialogState('select-video')}\n />\n {isVideoAsset(asset) && (\n <>\n <MenuItem\n icon={ImageIcon}\n text=\"Thumbnail\"\n onClick={() => setDialogState('edit-thumbnail')}\n />\n <MenuItem\n icon={TranslateIcon}\n text=\"Captions\"\n onClick={() => setDialogState('edit-captions')}\n />\n <MenuItem\n icon={SyncIcon}\n text=\"Resync from Mux\"\n onClick={handleResync}\n disabled={readOnly || isResyncing}\n />\n </>\n )}\n <MenuDivider />\n <MenuItem\n icon={DownloadIcon}\n text=\"Mezzanine\"\n onClick={() => setDialogState('mezzanine')}\n />\n <MenuDivider />\n {hasConfigAccess && (\n <>\n <MenuItem\n icon={PlugIcon}\n text=\"Configure API\"\n onClick={() => setDialogState('secrets')}\n />\n <MenuDivider />\n </>\n )}\n <MenuItem\n tone=\"critical\"\n icon={ResetIcon}\n text=\"Clear field\"\n onClick={onReset}\n disabled={readOnly}\n />\n </Menu>\n }\n portal\n open={open}\n >\n <Button\n icon={EllipsisHorizontalIcon}\n mode=\"ghost\"\n fontSize={1}\n onClick={() => {\n setDialogState(false)\n setOpen(true)\n }}\n />\n </Popover>","<Inline gap={1} padding={2}>\n {isSigned && (\n <Tooltip\n animate\n content={\n <Box padding={2}>\n <Text muted size={1}>\n Signed playback policy\n </Text>\n </Box>\n }\n placement=\"right\"\n portal\n >\n <LockCard radius={2} margin={2} scheme=\"dark\" tone=\"positive\">\n <LockButton icon={LockIcon} mode=\"bleed\" tone=\"positive\" />\n </LockCard>\n </Tooltip>\n )}\n <Popover\n animate\n content={\n <Menu ref={setMenuRef}>\n <Box padding={2}>\n <Label muted size={1}>\n Replace\n </Label>\n </Box>\n <FileInputMenuItem\n accept={accept}\n icon={UploadIcon}\n onSelect={onSelect}\n text=\"Upload\"\n disabled={readOnly}\n fontSize={1}\n />\n <MenuItem\n icon={SearchIcon}\n text=\"Browse\"\n onClick={() => setDialogState('select-video')}\n />\n {isVideoAsset(asset) && (\n <>\n <MenuItem\n icon={ImageIcon}\n text=\"Thumbnail\"\n onClick={() => setDialogState('edit-thumbnail')}\n />\n <MenuItem\n icon={TranslateIcon}\n text=\"Captions\"\n onClick={() => setDialogState('edit-captions')}\n />\n <MenuItem\n icon={SyncIcon}\n text=\"Resync from Mux\"\n onClick={handleResync}\n disabled={readOnly || isResyncing}\n />\n </>\n )}\n <MenuDivider />\n <MenuItem\n icon={DownloadIcon}\n text=\"Mezzanine\"\n onClick={() => setDialogState('mezzanine')}\n />\n <MenuDivider />\n {hasConfigAccess && (\n <>\n <MenuItem\n icon={PlugIcon}\n text=\"Configure API\"\n onClick={() => setDialogState('secrets')}\n />\n <MenuDivider />\n </>\n )}\n <MenuItem\n tone=\"critical\"\n icon={ResetIcon}\n text=\"Clear field\"\n onClick={onReset}\n disabled={readOnly}\n />\n </Menu>\n }\n portal\n open={open}\n >\n <Button\n icon={EllipsisHorizontalIcon}\n mode=\"ghost\"\n fontSize={1}\n onClick={() => {\n setDialogState(false)\n setOpen(true)\n }}\n />\n </Popover>\n </Inline>","_c","_Fragment","() => {\n // Fetch URL Upload file size\n if (stagedUpload.type === 'url') {\n // oxlint-disable-next-line react/set-state-in-effect\n setIsLoadingFileSize(false)\n setCanSkipFileSizeValidation(false)\n setFileSize(null)\n const url = stagedUpload.url\n\n // Get file size from URL\n const fetchFileSize = async () => {\n setIsLoadingFileSize(true)\n try {\n const response = await fetch(url, {method: 'HEAD'})\n const contentLength = response.headers.get('content-length')\n const newFileSize = contentLength ? parseInt(contentLength, 10) : null\n\n setIsLoadingFileSize(false)\n if (newFileSize) {\n setFileSize(newFileSize)\n }\n if (newFileSize === null && maxFileSize !== undefined) {\n // Size unknown but size limit is configured - skip file size validation\n setCanSkipFileSizeValidation(true)\n }\n } catch {\n console.warn('Could not validate file size from URL')\n // Skip validation of file size, but still validate duration\n setCanSkipFileSizeValidation(true)\n setIsLoadingFileSize(false)\n }\n }\n\n void fetchFileSize()\n }\n if (stagedUpload.type === 'file') {\n setFileSize(stagedUpload.files[0]!.size)\n }\n }","files","type","url","[maxFileSize, stagedUpload, stagedUpload.type]","{\n fileSize,\n isLoadingFileSize,\n canSkipFileSizeValidation,\n }","_c","() => {\n let videoSrc = null\n // Validate file uploads\n if (stagedUpload.type === 'file') {\n const file = stagedUpload.files[0]\n videoSrc = URL.createObjectURL(file!)\n }\n\n // Validate URL uploads\n if (stagedUpload.type === 'url') {\n videoSrc = stagedUpload.url\n }\n\n // oxlint-disable-next-line react/set-state-in-effect\n setVideoAssetMetadata((old) => ({\n ...old,\n duration: undefined,\n width: undefined,\n height: undefined,\n }))\n\n if (!videoSrc) return () => null\n\n setIsLoadingMetadata(true)\n const videoElement = document.createElement('video')\n videoElement.preload = 'metadata'\n\n const metadataListeners = [\n () => {\n setIsLoadingMetadata(false)\n },\n () => {\n const duration = videoElement.duration\n const width = videoElement.videoWidth\n const height = videoElement.videoHeight\n const isAudioOnly = width <= 0 && height <= 0\n const aspectRatio = width / height\n setVideoAssetMetadata((old) => {\n return {\n ...old,\n duration: duration,\n width: width,\n height: height,\n isAudioOnly: isAudioOnly,\n aspectRatio: aspectRatio,\n }\n })\n },\n ]\n\n const cleanupVideo = (videoEl: HTMLVideoElement) => {\n const currentVideoSrc = videoEl?.src\n if (videoEl) {\n metadataListeners.forEach((listener) =>\n videoEl.removeEventListener('loadedmetadata', listener),\n )\n videoEl.onerror = null\n videoEl.src = ''\n videoEl.load()\n }\n if (currentVideoSrc?.startsWith('blob:')) {\n URL.revokeObjectURL(currentVideoSrc)\n }\n }\n metadataListeners.push(() => setTimeout(() => cleanupVideo(videoElement), 0))\n\n videoElement.onerror = () => {\n setIsLoadingMetadata(false)\n console.warn('Could not read video metadata for validation')\n cleanupVideo(videoElement)\n }\n\n metadataListeners.forEach((listener) =>\n videoElement.addEventListener('loadedmetadata', listener),\n )\n videoElement.src = videoSrc\n\n return () => {\n cleanupVideo(videoElement)\n }\n }","files","type","url","(old) => ({\n ...old,\n duration: undefined,\n width: undefined,\n height: undefined,\n })","() => null","old","listener","[stagedUpload.type, stagedUpload]","stagedUpload.type","{\n videoAssetMetadata,\n setVideoAssetMetadata,\n isLoadingMetadata,\n }","_c","_temp","_temp2","_Fragment","{\n tracks,\n dispatch,\n defaultLang,\n}: {\n /**\n * Although the schema for tracks is an array, which we'll eventually support to allow uploading\n * multiple custom subtitles, for now we only support a single auto-generated track.\n */\n tracks: (Partial<UploadTextTrack> & {_id: string})[]\n dispatch: Dispatch<TrackAction>\n defaultLang: PluginConfig['defaultAutogeneratedSubtitleLang']\n}","[]","{display: 'block'}","() => {\n if (track) {\n dispatch({action: 'track', id: track._id, subAction: 'delete'})\n } else {\n dispatch({\n action: 'track',\n id: uuid(),\n subAction: 'add',\n value: {\n type: 'autogenerated',\n name: defaultLang || undefined,\n language_code: defaultLang || undefined,\n },\n })\n }\n }","<Checkbox\n id=\"include-autogenerated-track\"\n style={{display: 'block'}}\n checked={!!track?.language_code}\n onChange={() => {\n if (track) {\n dispatch({action: 'track', id: track._id, subAction: 'delete'})\n } else {\n dispatch({\n action: 'track',\n id: uuid(),\n subAction: 'add',\n value: {\n type: 'autogenerated',\n name: defaultLang || undefined,\n language_code: defaultLang || undefined,\n },\n })\n }\n }}\n />","!!track?.language_code","<Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor=\"checkbox\">Generate captions</label>\n </Text>\n </Box>","<Flex align=\"center\">\n <Checkbox\n id=\"include-autogenerated-track\"\n style={{display: 'block'}}\n checked={!!track?.language_code}\n onChange={() => {\n if (track) {\n dispatch({action: 'track', id: track._id, subAction: 'delete'})\n } else {\n dispatch({\n action: 'track',\n id: uuid(),\n subAction: 'add',\n value: {\n type: 'autogenerated',\n name: defaultLang || undefined,\n language_code: defaultLang || undefined,\n },\n })\n }\n }}\n />\n <Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor=\"checkbox\">Generate captions</label>\n </Text>\n </Box>\n </Flex>","track && (\n <Autocomplete\n id={`text-tract-editor--language`}\n value={track.language_code}\n onChange={(newValue) =>\n dispatch({\n action: 'track',\n id: track._id,\n subAction: 'update',\n value: {\n language_code: newValue,\n name: LanguagesList.getNativeName(newValue),\n },\n })\n }\n options={SUBTITLE_LANGUAGES[track.type!]}\n icon={TranslateIcon}\n placeholder=\"Select language\"\n filterOption={(query, option) =>\n option.label.toLowerCase().indexOf(query.toLowerCase()) > -1 ||\n option.value.toLowerCase().indexOf(query.toLowerCase()) > -1\n }\n openButton\n renderValue={(value) =>\n SUBTITLE_LANGUAGES[track.type!].find((l) => l.value === value)?.label || value\n }\n renderOption={(option) => (\n <Card data-as=\"button\" padding={3} radius={2} tone=\"inherit\">\n <Text size={2} textOverflow=\"ellipsis\">\n {option.label} ({option.value})\n </Text>\n </Card>\n )}\n />\n )","(query, option) =>\n option.label.toLowerCase().indexOf(query.toLowerCase()) > -1 ||\n option.value.toLowerCase().indexOf(query.toLowerCase()) > -1","(option) => (\n <Card data-as=\"button\" padding={3} radius={2} tone=\"inherit\">\n <Text size={2} textOverflow=\"ellipsis\">\n {option.label} ({option.value})\n </Text>\n </Card>\n )","<FormField title=\"Auto-generated subtitle or caption\" path={[]}>\n <Stack gap={2}>\n <Flex align=\"center\">\n <Checkbox\n id=\"include-autogenerated-track\"\n style={{display: 'block'}}\n checked={!!track?.language_code}\n onChange={() => {\n if (track) {\n dispatch({action: 'track', id: track._id, subAction: 'delete'})\n } else {\n dispatch({\n action: 'track',\n id: uuid(),\n subAction: 'add',\n value: {\n type: 'autogenerated',\n name: defaultLang || undefined,\n language_code: defaultLang || undefined,\n },\n })\n }\n }}\n />\n <Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor=\"checkbox\">Generate captions</label>\n </Text>\n </Box>\n </Flex>\n {track && (\n <Autocomplete\n id={`text-tract-editor--language`}\n value={track.language_code}\n onChange={(newValue) =>\n dispatch({\n action: 'track',\n id: track._id,\n subAction: 'update',\n value: {\n language_code: newValue,\n name: LanguagesList.getNativeName(newValue),\n },\n })\n }\n options={SUBTITLE_LANGUAGES[track.type!]}\n icon={TranslateIcon}\n placeholder=\"Select language\"\n filterOption={(query, option) =>\n option.label.toLowerCase().indexOf(query.toLowerCase()) > -1 ||\n option.value.toLowerCase().indexOf(query.toLowerCase()) > -1\n }\n openButton\n renderValue={(value) =>\n SUBTITLE_LANGUAGES[track.type!].find((l) => l.value === value)?.label || value\n }\n renderOption={(option) => (\n <Card data-as=\"button\" padding={3} radius={2} tone=\"inherit\">\n <Text size={2} textOverflow=\"ellipsis\">\n {option.label} ({option.value})\n </Text>\n </Card>\n )}\n />\n )}\n </Stack>\n </FormField>","option","_c","_temp","_temp2","{\n id,\n checked,\n optionName,\n description,\n dispatch,\n action,\n disabled,\n}: {\n id: string\n checked: boolean\n optionName: string\n description: string | ReactNode\n dispatch: ActionDispatch<[action: UploadConfigurationStateAction]>\n action?: 'public_policy' | 'signed_policy' | 'drm_policy'\n disabled?: boolean\n}","{\n outline: '0.01rem solid grey',\n transform: `scale(${scale})`,\n transition: 'transform 0.1s ease-in-out',\n cursor: disabled ? 'not-allowed' : 'pointer',\n borderRadius: '0.25rem',\n }","`scale(${scale})`","disabled ? 'not-allowed' : 'pointer'","() => {\n setScale(0.98)\n setTimeout(() => {\n setScale(1)\n }, 100)\n }","() => {\n if (!action) return\n triggerAnimation()\n dispatch({\n action,\n value: !checked,\n })\n }","typeof description === 'string' ? (\n <Text size={2} muted>\n {description}\n </Text>\n ) : (\n description\n )","<Checkbox\n id={id}\n required\n checked={checked}\n onChange={handleBoxClick}\n disabled={disabled}\n />","<Text size={3} weight=\"bold\">\n {optionName}\n </Text>","<Grid gap={3}>\n <Text size={3} weight=\"bold\">\n {optionName}\n </Text>\n {descriptionJsx}\n </Grid>","<label>\n <Flex gap={3} padding={3} style={boxStyle}>\n <Checkbox\n id={id}\n required\n checked={checked}\n onChange={handleBoxClick}\n disabled={disabled}\n />\n <Grid gap={3}>\n <Text size={3} weight=\"bold\">\n {optionName}\n </Text>\n {descriptionJsx}\n </Grid>\n </Flex>\n </label>","_c","{\n color: '#13141A',\n fontWeight: 500,\n }","{\n outline: '0.01rem solid grey',\n backgroundColor: '#979cb0',\n borderRadius: '0.5rem',\n width: 'max-content',\n color: '#13141A',\n }","<Box padding={2} style={boxStyle}>\n <Flex align=\"center\" gap={2}>\n <WarningFilledIcon />\n <Text size={1} style={textStyle}>\n Please select at least one Playback Policy\n </Text>\n </Flex>\n </Box>","_c","{\n id,\n config,\n secrets,\n dispatch,\n}: {\n id: string\n config: UploadConfig\n secrets: Secrets\n dispatch: ActionDispatch<[action: UploadConfigurationStateAction]>\n}","<Text weight=\"bold\">Advanced Playback Policies</Text>","<>\n <Text size={2} muted>\n Playback IDs are accessible by constructing an HLS URL like\n </Text>\n <Code>{'https://stream.mux.com/{PLAYBACK_ID}'}</Code>\n </>","<PlaybackPolicyOption\n id={`${id}--public`}\n checked={config.public_policy}\n optionName=\"Public\"\n description={\n <>\n <Text size={2} muted>\n Playback IDs are accessible by constructing an HLS URL like\n </Text>\n <Code>{'https://stream.mux.com/{PLAYBACK_ID}'}</Code>\n </>\n }\n dispatch={dispatch}\n action=\"public_policy\"\n />","public_policy","`${id}--public`","secrets.enableSignedUrls && (\n <PlaybackPolicyOption\n id={`${id}--signed`}\n checked={config.signed_policy}\n optionName=\"Signed\"\n description={\n <>\n <Text size={2} muted>\n Playback IDs should be used with tokens\n </Text>\n <Code>{'https://stream.mux.com/{PLAYBACK_ID}?token={TOKEN}'}</Code>\n <Text size={2} muted>\n See{' '}\n <a\n href=\"https://www.mux.com/docs/guides/secure-video-playback\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Secure video playback\n </a>{' '}\n for details about creating tokens.\n </Text>\n </>\n }\n // See Secure video playback for details about creating tokens.\"\n dispatch={dispatch}\n action=\"signed_policy\"\n />\n )","signed_policy","enableSignedUrls","drmPolicyDisabled ? (\n <PlaybackPolicyOption\n id={`${id}--drm`}\n checked={false}\n optionName=\"DRM - Disabled\"\n description={\n <>\n <Text size={2} muted>\n To enable DRM add your DRM Configuration Id to your plugin configuration in the API\n Credentials view.{' '}\n <a\n href=\"https://www.mux.com/support/human\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Contact us\n </a>{' '}\n to get started using DRM.\n </Text>\n </>\n }\n dispatch={dispatch}\n disabled\n />\n ) : (\n <PlaybackPolicyOption\n id={`${id}--drm`}\n checked={config.drm_policy}\n optionName=\"DRM\"\n description={\n <>\n <Text size={2} muted>\n Playback IDs should be used with tokens as with Signed playback, but require extra\n configuration.\n </Text>\n <Code>{'https://stream.mux.com/{PLAYBACK_ID}?token={TOKEN}'}</Code>\n <Text size={2} muted>\n See{' '}\n <a\n href=\"https://www.mux.com/docs/guides/protect-videos-with-drm#play-drm-protected-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Protect videos with DRM\n </a>{' '}\n for details about configuring your player for DRM playback and{' '}\n <a\n href=\"https://www.mux.com/docs/guides/secure-video-playback\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Secure video playback\n </a>{' '}\n for details about creating tokens.\n </Text>\n </>\n }\n dispatch={dispatch}\n action=\"drm_policy\"\n />\n )","drm_policy","noPolicySelected && <PlaybackPolicyWarning />","<Grid gap={3}>\n <Text weight=\"bold\">Advanced Playback Policies</Text>\n <PlaybackPolicyOption\n id={`${id}--public`}\n checked={config.public_policy}\n optionName=\"Public\"\n description={\n <>\n <Text size={2} muted>\n Playback IDs are accessible by constructing an HLS URL like\n </Text>\n <Code>{'https://stream.mux.com/{PLAYBACK_ID}'}</Code>\n </>\n }\n dispatch={dispatch}\n action=\"public_policy\"\n />\n {secrets.enableSignedUrls && (\n <PlaybackPolicyOption\n id={`${id}--signed`}\n checked={config.signed_policy}\n optionName=\"Signed\"\n description={\n <>\n <Text size={2} muted>\n Playback IDs should be used with tokens\n </Text>\n <Code>{'https://stream.mux.com/{PLAYBACK_ID}?token={TOKEN}'}</Code>\n <Text size={2} muted>\n See{' '}\n <a\n href=\"https://www.mux.com/docs/guides/secure-video-playback\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Secure video playback\n </a>{' '}\n for details about creating tokens.\n </Text>\n </>\n }\n // See Secure video playback for details about creating tokens.\"\n dispatch={dispatch}\n action=\"signed_policy\"\n />\n )}\n {drmPolicyDisabled ? (\n <PlaybackPolicyOption\n id={`${id}--drm`}\n checked={false}\n optionName=\"DRM - Disabled\"\n description={\n <>\n <Text size={2} muted>\n To enable DRM add your DRM Configuration Id to your plugin configuration in the API\n Credentials view.{' '}\n <a\n href=\"https://www.mux.com/support/human\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Contact us\n </a>{' '}\n to get started using DRM.\n </Text>\n </>\n }\n dispatch={dispatch}\n disabled\n />\n ) : (\n <PlaybackPolicyOption\n id={`${id}--drm`}\n checked={config.drm_policy}\n optionName=\"DRM\"\n description={\n <>\n <Text size={2} muted>\n Playback IDs should be used with tokens as with Signed playback, but require extra\n configuration.\n </Text>\n <Code>{'https://stream.mux.com/{PLAYBACK_ID}?token={TOKEN}'}</Code>\n <Text size={2} muted>\n See{' '}\n <a\n href=\"https://www.mux.com/docs/guides/protect-videos-with-drm#play-drm-protected-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Protect videos with DRM\n </a>{' '}\n for details about configuring your player for DRM playback and{' '}\n <a\n href=\"https://www.mux.com/docs/guides/secure-video-playback\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Secure video playback\n </a>{' '}\n for details about creating tokens.\n </Text>\n </>\n }\n dispatch={dispatch}\n action=\"drm_policy\"\n />\n )}\n {noPolicySelected && <PlaybackPolicyWarning />}\n </Grid>","_c","_Fragment","{\n id,\n config,\n dispatch,\n maxSupportedResolution,\n}: {\n id: string\n config: UploadConfig\n dispatch: ActionDispatch<[action: UploadConfigurationStateAction]>\n maxSupportedResolution: number\n}","[]","<>\n The maximum{' '}\n <a\n href=\"https://docs.mux.com/api-reference#video/operation/create-direct-upload\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n resolution_tier\n </a>{' '}\n your asset is encoded, stored, and streamed at.\n </>","RESOLUTION_TIERS.map(({value, label}, index) => {\n const inputId = `${id}--type-${value}`\n\n if (index > maxSupportedResolution) return null\n\n return (\n <Flex key={value} align=\"center\" gap={2}>\n <Radio\n checked={config.max_resolution_tier === value}\n name=\"asset-resolutiontier\"\n onChange={(e) =>\n dispatch({\n action: 'max_resolution_tier',\n value: e.currentTarget.value as UploadConfig['max_resolution_tier'],\n })\n }\n value={value}\n id={inputId}\n />\n <Text as=\"label\" htmlFor={inputId}>\n {label}\n </Text>\n </Flex>\n )\n })","config.max_resolution_tier","{value, label}","<FormField\n path={[]}\n title=\"Resolution Tier\"\n description={\n <>\n The maximum{' '}\n <a\n href=\"https://docs.mux.com/api-reference#video/operation/create-direct-upload\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n resolution_tier\n </a>{' '}\n your asset is encoded, stored, and streamed at.\n </>\n }\n >\n <Flex gap={3} wrap={'wrap'}>\n {RESOLUTION_TIERS.map(({value, label}, index) => {\n const inputId = `${id}--type-${value}`\n\n if (index > maxSupportedResolution) return null\n\n return (\n <Flex key={value} align=\"center\" gap={2}>\n <Radio\n checked={config.max_resolution_tier === value}\n name=\"asset-resolutiontier\"\n onChange={(e) =>\n dispatch({\n action: 'max_resolution_tier',\n value: e.currentTarget.value as UploadConfig['max_resolution_tier'],\n })\n }\n value={value}\n id={inputId}\n />\n <Text as=\"label\" htmlFor={inputId}>\n {label}\n </Text>\n </Flex>\n )\n })}\n </Flex>\n </FormField>","_c","_Fragment","{\n id,\n config,\n dispatch,\n}: {\n id: string\n config: UploadConfig\n dispatch: ActionDispatch<[action: UploadConfigurationStateAction]>\n}","(r) => r !== 'highest' && r !== 'audio-only'","(rendition: StaticRenditionResolution) => {\n const current = config.static_renditions\n const hasRendition = current.includes(rendition)\n\n if (hasRendition) {\n dispatch({\n action: 'static_renditions',\n value: current.filter((r) => r !== rendition),\n })\n } else {\n dispatch({\n action: 'static_renditions',\n value: [...current, rendition],\n })\n }\n }","static_renditions","r","(mode: 'standard' | 'advanced') => {\n setRenditionMode(mode)\n if (mode === 'standard') {\n // Remove specific resolutions, keep only highest and audio-only\n dispatch({\n action: 'static_renditions',\n value: config.static_renditions.filter((r) => r === 'highest' || r === 'audio-only'),\n })\n } else {\n // Remove highest, keep specific resolutions and audio-only\n dispatch({\n action: 'static_renditions',\n value: config.static_renditions.filter((r) => r !== 'highest'),\n })\n }\n }","(r) => r === 'highest' || r === 'audio-only'","(r) => r !== 'highest'","[]","() => handleModeChange('standard')","<Radio\n checked={renditionMode === 'standard'}\n name=\"rendition-mode\"\n onChange={() => handleModeChange('standard')}\n value=\"standard\"\n id={`${id}--mode-standard`}\n />","renditionMode === 'standard'","`${id}--mode-standard`","<Text as=\"label\" htmlFor={`${id}--mode-standard`}>\n Standard\n </Text>","<Flex align=\"center\" gap={2}>\n <Radio\n checked={renditionMode === 'standard'}\n name=\"rendition-mode\"\n onChange={() => handleModeChange('standard')}\n value=\"standard\"\n id={`${id}--mode-standard`}\n />\n <Text as=\"label\" htmlFor={`${id}--mode-standard`}>\n Standard\n </Text>\n </Flex>","() => handleModeChange('advanced')","<Radio\n checked={renditionMode === 'advanced'}\n name=\"rendition-mode\"\n onChange={() => handleModeChange('advanced')}\n value=\"advanced\"\n id={`${id}--mode-advanced`}\n />","renditionMode === 'advanced'","`${id}--mode-advanced`","<Text as=\"label\" htmlFor={`${id}--mode-advanced`}>\n Advanced\n </Text>","<Flex align=\"center\" gap={2}>\n <Radio\n checked={renditionMode === 'advanced'}\n name=\"rendition-mode\"\n onChange={() => handleModeChange('advanced')}\n value=\"advanced\"\n id={`${id}--mode-advanced`}\n />\n <Text as=\"label\" htmlFor={`${id}--mode-advanced`}>\n Advanced\n </Text>\n </Flex>","<Flex gap={3}>\n <Flex align=\"center\" gap={2}>\n <Radio\n checked={renditionMode === 'standard'}\n name=\"rendition-mode\"\n onChange={() => handleModeChange('standard')}\n value=\"standard\"\n id={`${id}--mode-standard`}\n />\n <Text as=\"label\" htmlFor={`${id}--mode-standard`}>\n Standard\n </Text>\n </Flex>\n <Flex align=\"center\" gap={2}>\n <Radio\n checked={renditionMode === 'advanced'}\n name=\"rendition-mode\"\n onChange={() => handleModeChange('advanced')}\n value=\"advanced\"\n id={`${id}--mode-advanced`}\n />\n <Text as=\"label\" htmlFor={`${id}--mode-advanced`}>\n Advanced\n </Text>\n </Flex>\n </Flex>","renditionMode === 'standard' && (\n <Stack gap={2}>\n <Flex align=\"center\" gap={2} padding={[0, 2]}>\n <Checkbox\n id={`${id}--highest`}\n style={{display: 'block'}}\n checked={config.static_renditions.includes('highest')}\n onChange={() => toggleRendition('highest')}\n />\n <Text as=\"label\" htmlFor={`${id}--highest`}>\n Highest Resolution (up to 4K)\n </Text>\n </Flex>\n <Flex align=\"center\" gap={2} padding={[0, 2]}>\n <Checkbox\n id={`${id}--audio-only-standard`}\n style={{display: 'block'}}\n checked={config.static_renditions.includes('audio-only')}\n onChange={() => toggleRendition('audio-only')}\n />\n <Text as=\"label\" htmlFor={`${id}--audio-only-standard`}>\n Audio Only (M4A)\n </Text>\n </Flex>\n </Stack>\n )","renditionMode === 'advanced' && (\n <Stack gap={2}>\n <Label size={1} muted>\n Select specific resolutions:\n </Label>\n <Flex gap={2} wrap=\"wrap\">\n {ADVANCED_RESOLUTIONS.map(({value, label}) => {\n const inputId = `${id}--resolution-${value}`\n return (\n <Flex key={value} align=\"center\" gap={2}>\n <Checkbox\n id={inputId}\n style={{display: 'block'}}\n checked={config.static_renditions.includes(value)}\n onChange={() => toggleRendition(value)}\n />\n <Text as=\"label\" htmlFor={inputId} size={1}>\n {label}\n </Text>\n </Flex>\n )\n })}\n </Flex>\n <Flex align=\"center\" gap={2} padding={[2, 2, 0, 2]}>\n <Checkbox\n id={`${id}--audio-only-advanced`}\n style={{display: 'block'}}\n checked={config.static_renditions.includes('audio-only')}\n onChange={() => toggleRendition('audio-only')}\n />\n <Text as=\"label\" htmlFor={`${id}--audio-only-advanced`}>\n Audio Only (M4A)\n </Text>\n </Flex>\n </Stack>\n )","{value, label}","<Stack gap={3}>\n <FormField\n path={[]}\n title=\"Static Renditions\"\n description=\"Generate downloadable MP4 or M4A files. Note: Mux will not upscale to produce MP4 renditions - renditions that would cause upscaling are skipped.\"\n >\n <Stack gap={3}>\n {/* Mode Selector */}\n <Flex gap={3}>\n <Flex align=\"center\" gap={2}>\n <Radio\n checked={renditionMode === 'standard'}\n name=\"rendition-mode\"\n onChange={() => handleModeChange('standard')}\n value=\"standard\"\n id={`${id}--mode-standard`}\n />\n <Text as=\"label\" htmlFor={`${id}--mode-standard`}>\n Standard\n </Text>\n </Flex>\n <Flex align=\"center\" gap={2}>\n <Radio\n checked={renditionMode === 'advanced'}\n name=\"rendition-mode\"\n onChange={() => handleModeChange('advanced')}\n value=\"advanced\"\n id={`${id}--mode-advanced`}\n />\n <Text as=\"label\" htmlFor={`${id}--mode-advanced`}>\n Advanced\n </Text>\n </Flex>\n </Flex>\n\n {/* Standard Mode Options */}\n {renditionMode === 'standard' && (\n <Stack gap={2}>\n <Flex align=\"center\" gap={2} padding={[0, 2]}>\n <Checkbox\n id={`${id}--highest`}\n style={{display: 'block'}}\n checked={config.static_renditions.includes('highest')}\n onChange={() => toggleRendition('highest')}\n />\n <Text as=\"label\" htmlFor={`${id}--highest`}>\n Highest Resolution (up to 4K)\n </Text>\n </Flex>\n <Flex align=\"center\" gap={2} padding={[0, 2]}>\n <Checkbox\n id={`${id}--audio-only-standard`}\n style={{display: 'block'}}\n checked={config.static_renditions.includes('audio-only')}\n onChange={() => toggleRendition('audio-only')}\n />\n <Text as=\"label\" htmlFor={`${id}--audio-only-standard`}>\n Audio Only (M4A)\n </Text>\n </Flex>\n </Stack>\n )}\n\n {/* Advanced Mode Options */}\n {renditionMode === 'advanced' && (\n <Stack gap={2}>\n <Label size={1} muted>\n Select specific resolutions:\n </Label>\n <Flex gap={2} wrap=\"wrap\">\n {ADVANCED_RESOLUTIONS.map(({value, label}) => {\n const inputId = `${id}--resolution-${value}`\n return (\n <Flex key={value} align=\"center\" gap={2}>\n <Checkbox\n id={inputId}\n style={{display: 'block'}}\n checked={config.static_renditions.includes(value)}\n onChange={() => toggleRendition(value)}\n />\n <Text as=\"label\" htmlFor={inputId} size={1}>\n {label}\n </Text>\n </Flex>\n )\n })}\n </Flex>\n <Flex align=\"center\" gap={2} padding={[2, 2, 0, 2]}>\n <Checkbox\n id={`${id}--audio-only-advanced`}\n style={{display: 'block'}}\n checked={config.static_renditions.includes('audio-only')}\n onChange={() => toggleRendition('audio-only')}\n />\n <Text as=\"label\" htmlFor={`${id}--audio-only-advanced`}>\n Audio Only (M4A)\n </Text>\n </Flex>\n </Stack>\n )}\n </Stack>\n </FormField>\n </Stack>","_c","{\n config,\n dispatch,\n stagedUpload,\n videoAssetMetadata,\n watermarkPreviewContainerRef,\n watermarkPreviewVideoRef,\n onValidationChange,\n}: {\n config: UploadConfig\n dispatch: (action: UploadConfigurationStateAction) => void\n stagedUpload: StagedUpload\n videoAssetMetadata: VideoAssetMetadata | null\n watermarkPreviewContainerRef: React.RefObject<HTMLDivElement | null>\n watermarkPreviewVideoRef: React.RefObject<HTMLVideoElement | null>\n onValidationChange: (error: string | null) => void\n}","[]","<>\n Add a watermark overlay to your video using Mux's native watermark support.{' '}\n <a\n href=\"https://www.mux.com/docs/guides/add-watermarks-to-your-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Learn more about Mux watermarks.\n </a>\n </>","config.watermark || {enabled: false}","watermark","(watermark) => {\n dispatch({action: 'watermark', value: watermark})\n }","<WatermarkControls\n watermark={config.watermark || {enabled: false}}\n onChange={(watermark) => {\n dispatch({action: 'watermark', value: watermark})\n }}\n onValidationChange={onValidationChange}\n previewContainerRef={watermarkPreviewContainerRef}\n previewVideoRef={watermarkPreviewVideoRef}\n />","config.watermark?.imageUrl &&\n stagedUpload.type === 'file' &&\n // Canvas preview is only shown in \"Canvas\" mode (no explicit overlay_settings)\n !config.watermark.overlay_settings && (\n <WatermarkPreview\n stagedUpload={stagedUpload}\n watermark={config.watermark}\n videoAspectRatio={videoAssetMetadata.aspectRatio}\n onWatermarkChange={(watermark) => {\n dispatch({action: 'watermark', value: watermark})\n }}\n previewContainerRef={watermarkPreviewContainerRef}\n videoRef={watermarkPreviewVideoRef}\n />\n )","stagedUpload.type","videoAssetMetadata.aspectRatio","<FormField\n path={[]}\n title=\"Watermark\"\n description={\n <>\n Add a watermark overlay to your video using Mux's native watermark support.{' '}\n <a\n href=\"https://www.mux.com/docs/guides/add-watermarks-to-your-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Learn more about Mux watermarks.\n </a>\n </>\n }\n >\n <Stack gap={3}>\n <WatermarkControls\n watermark={config.watermark || {enabled: false}}\n onChange={(watermark) => {\n dispatch({action: 'watermark', value: watermark})\n }}\n onValidationChange={onValidationChange}\n previewContainerRef={watermarkPreviewContainerRef}\n previewVideoRef={watermarkPreviewVideoRef}\n />\n {config.watermark?.imageUrl &&\n stagedUpload.type === 'file' &&\n // Canvas preview is only shown in \"Canvas\" mode (no explicit overlay_settings)\n !config.watermark.overlay_settings && (\n <WatermarkPreview\n stagedUpload={stagedUpload}\n watermark={config.watermark}\n videoAspectRatio={videoAssetMetadata.aspectRatio}\n onWatermarkChange={(watermark) => {\n dispatch({action: 'watermark', value: watermark})\n }}\n previewContainerRef={watermarkPreviewContainerRef}\n videoRef={watermarkPreviewVideoRef}\n />\n )}\n </Stack>\n </FormField>","{\n stagedUpload,\n watermark,\n onWatermarkChange,\n videoAspectRatio,\n previewContainerRef,\n videoRef,\n}: {\n stagedUpload: StagedUpload\n watermark: WatermarkConfig\n onWatermarkChange: (watermark: WatermarkConfig) => void\n videoAspectRatio?: number | null\n previewContainerRef: React.RefObject<HTMLDivElement | null>\n videoRef: React.RefObject<HTMLVideoElement | null>\n}","() => {\n if (videoRef.current && stagedUpload.type === 'file') {\n const file = stagedUpload.files[0]\n const url = URL.createObjectURL(file!)\n videoRef.current.src = url\n\n return () => {\n URL.revokeObjectURL(url)\n }\n }\n return undefined\n }","[stagedUpload, videoRef]","videoRef.current","{\n overflow: 'hidden',\n // For vertical videos, center the preview and limit its width\n display: 'flex',\n justifyContent: 'center',\n }","isVertical ? {height: '400px', maxHeight: '50vh'} : {minHeight: '200px'}","{\n position: 'relative',\n // For vertical videos: limit width so the preview doesn't get too tall\n // For horizontal videos: use full width\n width: isVertical ? 'auto' : '100%',\n aspectRatio: videoAspectRatio ? String(videoAspectRatio) : '16/9',\n ...(isVertical ? {height: '400px', maxHeight: '50vh'} : {minHeight: '200px'}),\n overflow: 'hidden',\n }","isVertical ? 'auto' : '100%'","videoAspectRatio ? String(videoAspectRatio) : '16/9'","{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n objectFit: 'fill',\n display: 'block',\n }","<video\n ref={videoRef}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n objectFit: 'fill',\n display: 'block',\n }}\n />","<DraggableWatermark\n watermark={watermark}\n onChange={onWatermarkChange}\n containerRef={previewContainerRef as React.RefObject<HTMLDivElement>}\n videoElementRef={videoRef as React.RefObject<HTMLVideoElement>}\n />","previewContainerRef as React.RefObject<HTMLDivElement>","videoRef as React.RefObject<HTMLVideoElement>","<Card\n tone=\"transparent\"\n border\n style={{\n overflow: 'hidden',\n // For vertical videos, center the preview and limit its width\n display: 'flex',\n justifyContent: 'center',\n }}\n >\n {/* Inner container that exactly matches the video aspect ratio - no padding, no letterbox */}\n <div\n ref={previewContainerRef}\n style={{\n position: 'relative',\n // For vertical videos: limit width so the preview doesn't get too tall\n // For horizontal videos: use full width\n width: isVertical ? 'auto' : '100%',\n aspectRatio: videoAspectRatio ? String(videoAspectRatio) : '16/9',\n ...(isVertical ? {height: '400px', maxHeight: '50vh'} : {minHeight: '200px'}),\n overflow: 'hidden',\n }}\n >\n <video\n ref={videoRef}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n objectFit: 'fill',\n display: 'block',\n }}\n />\n <DraggableWatermark\n watermark={watermark}\n onChange={onWatermarkChange}\n containerRef={previewContainerRef as React.RefObject<HTMLDivElement>}\n videoElementRef={videoRef as React.RefObject<HTMLVideoElement>}\n />\n </div>\n </Card>","_Fragment","_c","{\n children,\n tone,\n onPaste,\n onDrop,\n onDragEnter,\n onDragLeave,\n onDragOver,\n ref,\n}: UploadCardProps & {ref?: React.Ref<HTMLDivElement>}","(event) => {\n const target = event.target as HTMLElement\n\n // Don't steal focus when pasting into the VTT input\n if (target.closest('#vtt-url')) {\n return\n }\n\n if ((event.ctrlKey || event.metaKey) && event.key === 'v') {\n inputRef.current!.focus()\n }\n }","useCallback<React.KeyboardEventHandler<HTMLDivElement>>((event) => {\n const target = event.target as HTMLElement\n\n // Don't steal focus when pasting into the VTT input\n if (target.closest('#vtt-url')) {\n return\n }\n\n if ((event.ctrlKey || event.metaKey) && event.key === 'v') {\n inputRef.current!.focus()\n }\n }, [])","<HiddenInput ref={inputRef} />","<UploadCardWithFocusRing\n tone={tone}\n ref={ref}\n padding={0}\n radius={2}\n shadow={0}\n tabIndex={0}\n onKeyDown={handleKeyDown}\n onPaste={onPaste}\n onDrop={onDrop}\n onDragEnter={onDragEnter}\n onDragLeave={onDragLeave}\n onDragOver={onDragOver}\n >\n <HiddenInput ref={inputRef} />\n {children}\n </UploadCardWithFocusRing>","_c","HiddenInput","{onSelect, accept, ...props}: FileInputButtonProps","(event) => {\n if (onSelect) {\n onSelect(event.target.files!)\n }\n }","useCallback<React.ChangeEventHandler<HTMLInputElement>>(\n (event) => {\n if (onSelect) {\n onSelect(event.target.files!)\n }\n },\n [onSelect],\n )","() => inputRef.current?.click()","useCallback(() => inputRef.current?.click(), [])","<HiddenInput\n accept={accept}\n ref={inputRef}\n tabIndex={0}\n type=\"file\"\n id={inputId}\n onChange={handleSelect}\n value=\"\"\n />","{width: '100%'}","<Button\n onClick={handleButtonClick}\n mode=\"default\"\n tone=\"primary\"\n style={{width: '100%'}}\n {...props}\n />","<Label htmlFor={inputId}>\n <HiddenInput\n accept={accept}\n ref={inputRef}\n tabIndex={0}\n type=\"file\"\n id={inputId}\n onChange={handleSelect}\n value=\"\"\n />\n <Button\n onClick={handleButtonClick}\n mode=\"default\"\n tone=\"primary\"\n style={{width: '100%'}}\n {...props}\n />\n </Label>","Label","_c","() => setDialogState('select-video')","useCallback(() => setDialogState('select-video'), [setDialogState])","() => setDialogState('secrets')","useCallback(() => setDialogState('secrets'), [setDialogState])","hovering ? {borderColor: 'transparent'} : undefined","['column', 'column', 'row']","<Flex justify=\"center\">\n <Text muted>\n <DocumentVideoIcon />\n </Text>\n </Flex>","formatAcceptString(accept)","<Flex align=\"center\" justify=\"flex-start\" gap={2} flex={1}>\n <Flex justify=\"center\">\n <Text muted>\n <DocumentVideoIcon />\n </Text>\n </Flex>\n <Flex justify=\"center\">\n <Text size={1} muted>\n Drag {formatAcceptString(accept)} file or paste URL here\n </Text>\n </Flex>\n </Flex>","<FileInputButton\n accept={accept}\n mode=\"bleed\"\n tone=\"default\"\n icon={UploadIcon}\n text=\"Upload\"\n onSelect={onSelect}\n />","<Button mode=\"bleed\" icon={SearchIcon} text=\"Select\" onClick={handleBrowse} />","hasConfigAccess && (\n <Button\n padding={3}\n radius={3}\n tone={needsSetup ? 'critical' : undefined}\n onClick={handleConfigureApi}\n icon={PlugIcon}\n mode=\"bleed\"\n title=\"Configure plugin credentials\"\n />\n )","<Inline gap={2}>\n <FileInputButton\n accept={accept}\n mode=\"bleed\"\n tone=\"default\"\n icon={UploadIcon}\n text=\"Upload\"\n onSelect={onSelect}\n />\n <Button mode=\"bleed\" icon={SearchIcon} text=\"Select\" onClick={handleBrowse} />\n\n {hasConfigAccess && (\n <Button\n padding={3}\n radius={3}\n tone={needsSetup ? 'critical' : undefined}\n onClick={handleConfigureApi}\n icon={PlugIcon}\n mode=\"bleed\"\n title=\"Configure plugin credentials\"\n />\n )}\n </Inline>","<Flex\n align=\"center\"\n justify=\"space-between\"\n gap={4}\n direction={['column', 'column', 'row']}\n paddingY={2}\n sizing=\"border\"\n >\n <Flex align=\"center\" justify=\"flex-start\" gap={2} flex={1}>\n <Flex justify=\"center\">\n <Text muted>\n <DocumentVideoIcon />\n </Text>\n </Flex>\n <Flex justify=\"center\">\n <Text size={1} muted>\n Drag {formatAcceptString(accept)} file or paste URL here\n </Text>\n </Flex>\n </Flex>\n <Inline gap={2}>\n <FileInputButton\n accept={accept}\n mode=\"bleed\"\n tone=\"default\"\n icon={UploadIcon}\n text=\"Upload\"\n onSelect={onSelect}\n />\n <Button mode=\"bleed\" icon={SearchIcon} text=\"Select\" onClick={handleBrowse} />\n\n {hasConfigAccess && (\n <Button\n padding={3}\n radius={3}\n tone={needsSetup ? 'critical' : undefined}\n onClick={handleConfigureApi}\n icon={PlugIcon}\n mode=\"bleed\"\n title=\"Configure plugin credentials\"\n />\n )}\n </Inline>\n </Flex>","<Card\n sizing=\"border\"\n tone={readOnly ? 'transparent' : 'inherit'}\n border\n radius={2}\n paddingX={3}\n paddingY={1}\n style={hovering ? {borderColor: 'transparent'} : undefined}\n >\n <Flex\n align=\"center\"\n justify=\"space-between\"\n gap={4}\n direction={['column', 'column', 'row']}\n paddingY={2}\n sizing=\"border\"\n >\n <Flex align=\"center\" justify=\"flex-start\" gap={2} flex={1}>\n <Flex justify=\"center\">\n <Text muted>\n <DocumentVideoIcon />\n </Text>\n </Flex>\n <Flex justify=\"center\">\n <Text size={1} muted>\n Drag {formatAcceptString(accept)} file or paste URL here\n </Text>\n </Flex>\n </Flex>\n <Inline gap={2}>\n <FileInputButton\n accept={accept}\n mode=\"bleed\"\n tone=\"default\"\n icon={UploadIcon}\n text=\"Upload\"\n onSelect={onSelect}\n />\n <Button mode=\"bleed\" icon={SearchIcon} text=\"Select\" onClick={handleBrowse} />\n\n {hasConfigAccess && (\n <Button\n padding={3}\n radius={3}\n tone={needsSetup ? 'critical' : undefined}\n onClick={handleConfigureApi}\n icon={PlugIcon}\n mode=\"bleed\"\n title=\"Configure plugin credentials\"\n />\n )}\n </Inline>\n </Flex>\n </Card>","readOnly ? 'transparent' : 'inherit'","_c","_Fragment","PlayerActionsMenu","<InputFallback />","<Suspense fallback={<InputFallback />}>\n {isLoading ? (\n <InputFallback />\n ) : (\n <>\n {secretDocumentValues.value.needsSetup && !assetDocumentValues.value ? (\n <Onboard setDialogState={setDialogState} config={props.config} />\n ) : (\n <Uploader\n {...props}\n config={props.config}\n onChange={props.onChange}\n client={client}\n secrets={secretDocumentValues.value.secrets}\n asset={assetDocumentValues.value}\n dialogState={dialogState}\n setDialogState={setDialogState}\n needsSetup={secretDocumentValues.value.needsSetup}\n />\n )}\n\n {dialogState === 'secrets' && hasConfigAccess && (\n <ConfigureApiDialog\n setDialogState={setDialogState}\n secrets={secretDocumentValues.value.secrets}\n />\n )}\n </>\n )}\n </Suspense>","assetDocumentValues.value","props.config","value","<Card>\n <ErrorBoundaryCard schemaType={props.schemaType}>\n <Suspense fallback={<InputFallback />}>\n {isLoading ? (\n <InputFallback />\n ) : (\n <>\n {secretDocumentValues.value.needsSetup && !assetDocumentValues.value ? (\n <Onboard setDialogState={setDialogState} config={props.config} />\n ) : (\n <Uploader\n {...props}\n config={props.config}\n onChange={props.onChange}\n client={client}\n secrets={secretDocumentValues.value.secrets}\n asset={assetDocumentValues.value}\n dialogState={dialogState}\n setDialogState={setDialogState}\n needsSetup={secretDocumentValues.value.needsSetup}\n />\n )}\n\n {dialogState === 'secrets' && hasConfigAccess && (\n <ConfigureApiDialog\n setDialogState={setDialogState}\n secrets={secretDocumentValues.value.secrets}\n />\n )}\n </>\n )}\n </Suspense>\n </ErrorBoundaryCard>\n </Card>","schemaType","_c","useClient","_Fragment","ErrorBoundaryCard","Input","\"title\"","\"horizontal_margin\"","\"vertical_margin\"","\"width\"","\"filename\""],"sources":["../src/context/MuxApiHostContext.tsx","../src/components/icons/ToolIcon.tsx","../src/context/DrmPlaybackWarningContext.tsx","../src/util/muxAddonClient.ts","../src/hooks/useClient.ts","../src/util/createSearchFilter.ts","../src/hooks/useAssets.ts","../src/hooks/useDialogState.ts","../src/constants.ts","../src/util/pluginVersion.ts","../src/actions/secrets.ts","../src/hooks/useSaveSecrets.ts","../src/util/constants.ts","../src/hooks/useSecretsDocumentValues.ts","../src/hooks/useSecretsFormState.ts","../src/util/readSecrets.ts","../src/components/MuxLogo.tsx","../src/components/ConfigureApi.styled.tsx","../src/components/FormField.tsx","../src/components/ConfigureApi.tsx","../src/util/assetTitlePlaceholder.ts","../src/util/parsers.ts","../src/actions/assets.ts","../src/hooks/useMuxAssets.ts","../src/hooks/useImportMuxAssets.ts","../src/hooks/useInView.ts","../src/util/getPlaybackPolicy.ts","../src/util/generateJwt.ts","../src/util/createUrlParamsObject.ts","../src/util/getAnimatedPosterSrc.ts","../src/util/getPosterSrc.ts","../src/util/tryWithSuspend.ts","../src/components/VideoThumbnail.tsx","../src/components/ImportVideosFromMux.tsx","../src/components/PageSelector.tsx","../src/util/addKeysToMuxData.ts","../src/hooks/useResyncMuxMetadata.ts","../src/components/ResyncMetadata.tsx","../src/components/SelectSortOptions.tsx","../src/components/SpinnerBox.tsx","../src/components/IconInfo.tsx","../src/components/icons/Resolution.tsx","../src/components/icons/StopWatch.tsx","../src/hooks/useMezzanine.ts","../src/components/MezzanineExplanation.tsx","../src/components/Mezzanine.tsx","../src/hooks/useResyncAsset.ts","../src/util/textTracks.ts","../src/util/types.ts","../src/components/AddCaptionDialog.tsx","../src/components/EditCaptionDialog.tsx","../src/components/TextTracksManager.tsx","../src/context/DialogStateContext.tsx","../src/util/getVideoSrc.ts","../src/components/CaptionsDialog.tsx","../src/util/formatSeconds.ts","../src/components/EditThumbnailDialog.tsx","../src/components/icons/Audio.tsx","../src/components/MezzanineDialog.tsx","../src/components/VideoPlayer.tsx","../src/components/documentPreview/MissingSchemaType.tsx","../src/components/documentPreview/TimeAgo.tsx","../src/components/documentPreview/DraftStatus.tsx","../src/components/documentPreview/PublishedStatus.tsx","../src/components/documentPreview/PaneItemPreview.tsx","../src/components/documentPreview/DocumentPreview.tsx","../src/components/VideoDetails/VideoReferences.tsx","../src/components/VideoDetails/DeleteDialog.tsx","../src/hooks/useDocReferences.ts","../src/util/getVideoMetadata.ts","../src/components/VideoDetails/useVideoDetails.ts","../src/components/VideoDetails/VideoDetails.tsx","../src/components/VideoMetadata.tsx","../src/components/VideoInBrowser.tsx","../src/components/VideosBrowser.tsx","../src/components/StudioTool.tsx","../src/hooks/useAccessControl.ts","../src/hooks/useAssetDocumentValues.ts","../src/hooks/useMuxPolling.ts","../src/components/ErrorBoundaryCard.tsx","../src/components/Input.styled.tsx","../src/components/Onboard.tsx","../src/clients/upChunkObservable.ts","../src/util/formatDriveShareLink.ts","../src/util/roundPxString.ts","../src/actions/upload.ts","../src/util/asserters.ts","../src/util/extractFiles.ts","../src/components/SelectAsset.tsx","../src/components/InputBrowser.tsx","../src/hooks/useCancelUpload.ts","../src/components/Player.styled.tsx","../src/components/UploadProgress.tsx","../src/components/Player.tsx","../src/components/withFocusRing/helpers.ts","../src/components/FileInputMenuItem.styled.tsx","../src/components/FileInputMenuItem.tsx","../src/components/PlayerActionsMenu.tsx","../src/hooks/useFetchFileSize.ts","../src/hooks/useMediaMetadata.ts","../src/util/convertWatermarkToMux.ts","../src/util/formatBytes.ts","../src/components/DraggableWatermark.tsx","../src/components/TextTracksEditor.tsx","../src/components/uploadConfiguration/PlaybackPolicyOption.tsx","../src/components/uploadConfiguration/PlaybackPolicyWarning.tsx","../src/components/uploadConfiguration/PlaybackPolicy.tsx","../src/components/uploadConfiguration/ResolutionTierSelector.tsx","../src/components/uploadConfiguration/StaticRenditionSelector.tsx","../src/components/UploadConfiguration.tsx","../src/components/withFocusRing/withFocusRing.ts","../src/components/Uploader.styled.tsx","../src/components/FileInputButton.tsx","../src/components/UploadPlaceholder.tsx","../src/components/Uploader.tsx","../src/components/Input.tsx","../src/plugin.tsx","../src/schema.ts","../src/_exports/index.ts"],"sourcesContent":["import {createContext, useContext} from 'react'\n\nconst MuxApiHostContext = createContext<string | undefined>(undefined)\n\nexport function MuxApiHostProvider({\n muxApiHost,\n children,\n}: {\n muxApiHost: string | undefined\n children: React.ReactNode\n}) {\n return <MuxApiHostContext.Provider value={muxApiHost}>{children}</MuxApiHostContext.Provider>\n}\n\nexport function useMuxApiHost() {\n return useContext(MuxApiHostContext)\n}\n","/**\n * Icon of a monitor with a play button.\n * Credits: material design icons & react-icons\n */\nconst ToolIcon = () => (\n <svg\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 24 24\"\n height=\"1em\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M21 3H3c-1.11 0-2 .89-2 2v12c0 1.1.89 2 2 2h5v2h8v-2h5c1.1 0 1.99-.9 1.99-2L23 5c0-1.11-.9-2-2-2zm0 14H3V5h18v12zm-5-6l-7 4V7z\" />\n </svg>\n)\n\nexport default ToolIcon\n","import {Button, Card, Dialog, Stack, Text} from '@sanity/ui'\nimport {createContext, useCallback, useContext, useMemo, useState} from 'react'\n\nimport {type PluginConfig} from '../util/types'\n\nconst LOCAL_STORAGE_HAS_SHOWN_WARNING_KEY = 'mux-plugin-has-shown-drm-playback-warning'\n\ntype DrmPlaybackWarningContextContextProps = {\n hasShownWarning: boolean\n setHasWarnedAboutDrmPlayback: (b: boolean) => void\n}\n\nconst DrmPlaybackWarningContext = createContext<DrmPlaybackWarningContextContextProps>({\n hasShownWarning: false,\n setHasWarnedAboutDrmPlayback: () => {\n return null\n },\n})\n\ninterface DrmPlaybackWarningContextProviderProps {\n config?: PluginConfig\n children: React.ReactNode\n}\n\nexport const DrmPlaybackWarningContextProvider = ({\n config,\n children,\n}: DrmPlaybackWarningContextProviderProps) => {\n const warningDisabled = config?.disableDrmPlaybackWarning ?? false\n const hasWarned: boolean =\n warningDisabled || window.localStorage.getItem(LOCAL_STORAGE_HAS_SHOWN_WARNING_KEY) === 'true'\n const [hasWarnedAboutDrmPlayback, setHasWarnedAboutDrmPlayback] = useState(hasWarned)\n\n const setHasShownWarning = useCallback((b: boolean) => {\n window.localStorage.setItem(LOCAL_STORAGE_HAS_SHOWN_WARNING_KEY, b.toString())\n setHasWarnedAboutDrmPlayback(b)\n }, [])\n\n const value = useMemo(\n () => ({\n hasShownWarning: hasWarnedAboutDrmPlayback,\n setHasWarnedAboutDrmPlayback: setHasShownWarning,\n }),\n [hasWarnedAboutDrmPlayback, setHasShownWarning],\n )\n\n return (\n <DrmPlaybackWarningContext.Provider value={value}>\n {children}\n </DrmPlaybackWarningContext.Provider>\n )\n}\n\nexport const useDrmPlaybackWarningContext = () => {\n const context = useContext(DrmPlaybackWarningContext)\n return context\n}\n\nexport const DRMWarningDialog = ({onClose}: {onClose: () => void}) => {\n const {setHasWarnedAboutDrmPlayback} = useDrmPlaybackWarningContext()\n const _onClose = () => {\n setHasWarnedAboutDrmPlayback(true)\n onClose()\n }\n return (\n <Dialog\n open\n id=\"drm-playback-warn\"\n onClose={_onClose}\n header=\"DRM Playback Warning\"\n footer={\n <Stack padding={3}>\n <Button mode=\"ghost\" tone=\"primary\" onClick={_onClose} text=\"Ok\" />\n </Stack>\n }\n >\n <Stack gap={3} padding={3}>\n <Card padding={[3, 3, 3]} radius={2}>\n <Stack gap={3}>\n <Text size={1} weight=\"semibold\">\n DRM-protected playback will generate a license with a small associated cost. The\n plugin will attempt to play signed or public playback IDs instead whenever possible.\n </Text>\n </Stack>\n </Card>\n <Card padding={[3, 3, 3]} radius={2} tone=\"suggest\">\n <Stack gap={3}>\n <Text size={1} weight=\"semibold\">\n This is a one time warning. If it persists, you can disable it from your plugin\n configuration.\n </Text>\n </Stack>\n </Card>\n </Stack>\n </Dialog>\n )\n}\n","import type {SanityClient} from 'sanity'\n\n/**\n * Maps a Studio client handed out by the plugin's `useClient` hook to the client that\n * sends Mux addon (`/addons/mux/...`) requests. Only populated when `muxApiHost` is set.\n */\nconst muxAddonClients = new WeakMap<SanityClient, SanityClient>()\n\n/**\n * Validates `muxApiHost` and strips trailing slashes, so it can be used as `apiHost`.\n * Throws if it is not an absolute `http(s)` URL without a path, query or hash.\n */\nexport function normalizeMuxApiHost(muxApiHost: string): string {\n let url: URL\n try {\n url = new URL(muxApiHost)\n } catch {\n throw new Error(\n `[sanity-plugin-mux-input] \\`muxApiHost\\` must be an absolute URL, like \"http://127.0.0.1:8080\". Got: \"${muxApiHost}\"`,\n )\n }\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n throw new Error(\n `[sanity-plugin-mux-input] \\`muxApiHost\\` must use http or https. Got: \"${muxApiHost}\"`,\n )\n }\n if ((url.pathname && url.pathname !== '/') || url.search || url.hash) {\n throw new Error(\n `[sanity-plugin-mux-input] \\`muxApiHost\\` must not have a path, query or hash. The plugin adds \"/v<apiVersion>/addons/mux/...\". Got: \"${muxApiHost}\"`,\n )\n }\n return url.origin\n}\n\n/**\n * Creates the client for Mux addon requests from a Studio client.\n *\n * The host is used as-is: no project id is prepended (`useProjectHostname: false`).\n * `@sanity/client` then sends the project id in a request header.\n * Auth config (`token`, `withCredentials`) is copied from the Studio client.\n */\nfunction createMuxAddonClient(client: SanityClient, muxApiHost: string): SanityClient {\n return client.withConfig({\n apiHost: normalizeMuxApiHost(muxApiHost),\n // oxlint-disable-next-line no-deprecated -- only way to keep the project id out of the hostname\n useProjectHostname: false,\n useCdn: false,\n })\n}\n\n/**\n * Returns a copy of the Studio client that is linked to a Mux addon client on `muxApiHost`.\n * Content Lake requests on the returned client still use the Studio API host.\n */\nexport function withMuxApiHost(client: SanityClient, muxApiHost: string): SanityClient {\n const studioClient = client.withConfig({})\n muxAddonClients.set(studioClient, createMuxAddonClient(client, muxApiHost))\n return studioClient\n}\n\n/**\n * Returns the client to use for Mux addon requests.\n * Without a `muxApiHost` override, this is the same client that was passed in.\n */\nexport function getMuxAddonClient(client: SanityClient): SanityClient {\n return muxAddonClients.get(client) ?? client\n}\n","// As it's required to specify the API Version this custom hook ensures it's all using the same version\nimport {useMemo} from 'react'\nimport {useClient as useSanityClient} from 'sanity'\n\nimport {useMuxApiHost} from '../context/MuxApiHostContext'\nimport {withMuxApiHost} from '../util/muxAddonClient'\n\nexport const SANITY_API_VERSION = '2024-03-05'\n\nexport function useClient() {\n const client = useSanityClient({apiVersion: SANITY_API_VERSION})\n const muxApiHost = useMuxApiHost()\n // Without `muxApiHost`, return the Studio client unchanged.\n // With it, Mux addon requests made via `getMuxAddonClient(client)` go to that host.\n return useMemo(\n () => (muxApiHost ? withMuxApiHost(client, muxApiHost) : client),\n [client, muxApiHost],\n )\n}\n","// Adaptation of Sanity's createSearchQuery for our limited use case:\n// https://github.com/sanity-io/sanity/blob/next/packages/sanity/src/core/search/weighted/createSearchQuery.ts\nimport {compact, toLower, trim, uniq, words} from 'lodash'\n\nconst SPECIAL_CHARS = /([^!@#$%^&*(),\\\\/?\";:{}|[\\]+<>\\s-])+/g\nconst STRIP_EDGE_CHARS = /(^[.]+)|([.]+$)/\n\nfunction tokenize(string: string): string[] {\n return (string.match(SPECIAL_CHARS) || []).map((token) => token.replace(STRIP_EDGE_CHARS, ''))\n}\n\nfunction toGroqParams(terms: string[]): Record<string, string> {\n const params: Record<string, string> = {}\n return terms.reduce((acc, term, i) => {\n acc[`t${i}`] = `*${term}*` // \"t\" is short for term\n return acc\n }, params)\n}\n\n/**\n * Convert a string into an array of tokenized terms.\n *\n * Any (multi word) text wrapped in double quotes will be treated as \"phrases\", or separate tokens that\n * will not have its special characters removed.\n * E.g.`\"the\" \"fantastic mr\" fox fox book` =\\> [\"the\", `\"fantastic mr\"`, \"fox\", \"book\"]\n *\n * Phrases wrapped in quotes are assigned relevance scoring differently from regular words.\n *\n * @internal\n */\nfunction extractTermsFromQuery(query: string): string[] {\n const quotedQueries = [] as string[]\n const unquotedQuery = query.replace(/(\"[^\"]*\")/g, (match) => {\n if (words(match).length > 1) {\n quotedQueries.push(match)\n return ''\n }\n return match\n })\n\n // Lowercase and trim quoted queries\n const quotedTerms = quotedQueries.map((str) => trim(toLower(str)))\n\n /**\n * Convert (remaining) search query into an array of deduped, sanitized tokens.\n * All white space and special characters are removed.\n * e.g. \"The saint of Saint-Germain-des-Prés\" =\\> ['the', 'saint', 'of', 'germain', 'des', 'pres']\n */\n const remainingTerms = uniq(compact(tokenize(toLower(unquotedQuery))))\n\n return [...quotedTerms, ...remainingTerms]\n}\n\n/**\n * Create GROQ constraints, given search terms and the full spec of available document types and fields.\n * Essentially a large list of all possible fields (joined by logical OR) to match our search terms against.\n */\nfunction createConstraints(terms: string[], includeAssetId: boolean) {\n const searchPaths = includeAssetId ? ['filename', 'assetId'] : ['filename']\n const constraints = terms\n .map((_term, i) => searchPaths.map((joinedPath) => `${joinedPath} match $t${i}`))\n .filter((constraint) => constraint.length > 0)\n\n return constraints.map((constraint) => `(${constraint.join(' || ')})`)\n}\n\nexport function createSearchFilter(query: string) {\n const terms = extractTermsFromQuery(query)\n\n return {\n filter: createConstraints(terms, query.length >= 8), // if the search is big enough, include the assetId (mux id) in the results\n params: {\n ...toGroqParams(terms),\n },\n }\n}\n","import {useMemo, useState} from 'react'\nimport {\n collate,\n createHookFromObservableFactory,\n type DocumentStore,\n useDocumentStore,\n} from 'sanity'\n\nimport {SANITY_API_VERSION} from '../hooks/useClient'\nimport {createSearchFilter} from '../util/createSearchFilter'\nimport type {VideoAssetDocument} from '../util/types'\n\nexport const ASSET_SORT_OPTIONS = {\n createdDesc: {groq: '_createdAt desc', label: 'Newest first'},\n createdAsc: {groq: '_createdAt asc', label: 'First created (oldest)'},\n filenameAsc: {groq: 'filename asc', label: 'By filename (A-Z)'},\n filenameDesc: {groq: 'filename desc', label: 'By filename (Z-A)'},\n}\n\nexport type SortOption = keyof typeof ASSET_SORT_OPTIONS\n\nconst useAssetDocuments = createHookFromObservableFactory<\n VideoAssetDocument[],\n {\n documentStore: DocumentStore\n sort: SortOption\n searchQuery: string\n }\n>(({documentStore, sort, searchQuery}) => {\n const search = createSearchFilter(searchQuery)\n const filter = [`_type == \"mux.videoAsset\"`, ...search.filter].filter(Boolean).join(' && ')\n\n const sortFragment = ASSET_SORT_OPTIONS[sort].groq\n return documentStore.listenQuery(\n /* groq */ `*[${filter}] | order(${sortFragment})`,\n search.params,\n {\n apiVersion: SANITY_API_VERSION,\n },\n )\n})\n\nexport default function useAssets() {\n const documentStore = useDocumentStore()\n const [sort, setSort] = useState<SortOption>('createdDesc')\n const [searchQuery, setSearchQuery] = useState('')\n\n const [assetDocuments = [], isLoading] = useAssetDocuments(\n useMemo(() => ({documentStore, sort, searchQuery}), [documentStore, sort, searchQuery]),\n )\n\n const assets = useMemo(\n () =>\n // Avoid displaying both drafts & published assets by collating them together and giving preference to drafts\n collate<VideoAssetDocument>(assetDocuments).map(\n (collated) =>\n ({\n ...(collated.draft || collated.published),\n _id: collated.id,\n }) as VideoAssetDocument,\n ),\n [assetDocuments],\n )\n\n return {\n assets,\n isLoading,\n sort,\n searchQuery,\n setSort,\n setSearchQuery,\n }\n}\n","// Handy little state machine to simplify managing which root level dialog to open\n\nimport {useState} from 'react'\n\nexport type DialogState =\n | 'secrets'\n | 'mezzanine'\n | 'select-video'\n | 'edit-thumbnail'\n | 'edit-captions'\n | false\n\nexport function useDialogState() {\n return useState<DialogState>(false)\n}\n\nexport type SetDialogState = ReturnType<typeof useDialogState>[1]\n","declare global {\n var __PKG_VERSION__: string | undefined\n}\nexport const PLUGIN_VERSION = typeof __PKG_VERSION__ === 'string' ? __PKG_VERSION__ : '0.0.0-dev'\n","import {PLUGIN_VERSION} from '../constants'\n\nexport const PLUGIN_VERSION_QUERY = {\n sanityVersion: PLUGIN_VERSION,\n}\n","import {defer} from 'rxjs'\nimport type {SanityClient} from 'sanity'\n\nimport {getMuxAddonClient} from '../util/muxAddonClient'\nimport {PLUGIN_VERSION_QUERY} from '../util/pluginVersion'\n\ninterface SecretsDocument {\n _id: 'secrets.mux'\n _type: 'mux.apiKey'\n token: string\n secretKey: string\n enableSignedUrls: boolean\n signingKeyId: string\n signingKeyPrivate: string\n drmConfigId: string\n}\nexport function saveSecrets(\n client: SanityClient,\n token: string,\n secretKey: string,\n enableSignedUrls: boolean,\n signingKeyId: string,\n signingKeyPrivate: string,\n drmConfigId: string,\n): Promise<SecretsDocument> {\n const doc: SecretsDocument = {\n _id: 'secrets.mux',\n _type: 'mux.apiKey',\n token,\n secretKey,\n enableSignedUrls,\n signingKeyId,\n signingKeyPrivate,\n drmConfigId,\n }\n doc.signingKeyId = enableSignedUrls ? signingKeyId : ''\n doc.signingKeyPrivate = enableSignedUrls ? signingKeyPrivate : ''\n\n return client.createOrReplace(doc)\n}\n\nexport async function createSigningKeys(client: SanityClient) {\n try {\n const {dataset} = client.config()\n const res = await getMuxAddonClient(client).request<{\n data: {private_key: string; id: string; created_at: string}\n }>({\n url: `/addons/mux/signing-keys/${dataset}`,\n withCredentials: true,\n method: 'POST',\n query: PLUGIN_VERSION_QUERY,\n })\n return res\n } catch (error: any) {\n console.error('Error creating signing keys', error)\n const message =\n error.response?.statusCode === 401\n ? 'Unauthorized - Failed to create the Signing Key. Please ensure that the token has \"System\" permissions'\n : error.message\n throw new Error(message, {cause: error})\n }\n}\n\nexport function testSecrets(client: SanityClient) {\n const {dataset} = client.config()\n return getMuxAddonClient(client).request<{status: boolean}>({\n url: `/addons/mux/secrets/${dataset}/test`,\n withCredentials: true,\n method: 'GET',\n query: PLUGIN_VERSION_QUERY,\n })\n}\n\nexport async function haveValidSigningKeys(\n client: SanityClient,\n signingKeyId: string,\n signingKeyPrivate: string,\n) {\n if (!(signingKeyId && signingKeyPrivate)) {\n return false\n }\n\n const {dataset} = client.config()\n try {\n const res = await getMuxAddonClient(client).request<{data: {id: string; created_at: string}}>({\n url: `/addons/mux/signing-keys/${dataset}/${signingKeyId}`,\n withCredentials: true,\n method: 'GET',\n query: PLUGIN_VERSION_QUERY,\n })\n //\n // if this signing key is valid it will return { data: { id: 'xxxx' } }\n //\n return !!(res.data && res.data.id)\n } catch (e) {\n console.error('Error fetching signingKeyId', signingKeyId, 'assuming it is not valid', e)\n return false\n }\n}\n\nexport function testSecretsObservable(client: SanityClient) {\n const {dataset} = client.config()\n return defer(() =>\n getMuxAddonClient(client).observable.request<{status: boolean}>({\n url: `/addons/mux/secrets/${dataset}/test`,\n withCredentials: true,\n method: 'GET',\n query: PLUGIN_VERSION_QUERY,\n }),\n )\n}\n","import {useCallback} from 'react'\nimport type {SanityClient} from 'sanity'\n\nimport {createSigningKeys, haveValidSigningKeys, saveSecrets, testSecrets} from '../actions/secrets'\nimport type {Secrets} from '../util/types'\n\nexport const useSaveSecrets = (client: SanityClient, secrets: Secrets) => {\n return useCallback(\n async ({\n token,\n secretKey,\n enableSignedUrls,\n drmConfigId,\n }: Pick<\n Secrets,\n 'token' | 'secretKey' | 'enableSignedUrls' | 'drmConfigId'\n >): Promise<Secrets> => {\n let {signingKeyId, signingKeyPrivate} = secrets\n\n try {\n await saveSecrets(\n client,\n token!,\n secretKey!,\n enableSignedUrls,\n signingKeyId!,\n signingKeyPrivate!,\n drmConfigId!,\n )\n const valid = await testSecrets(client)\n if (!valid?.status && token && secretKey) {\n // oxlint-disable-next-line react/todo\n throw new Error('Invalid secrets')\n }\n } catch (err) {\n console.error('Error while trying to save secrets:', err)\n throw err\n }\n\n if (enableSignedUrls) {\n const hasValidSigningKeys = await haveValidSigningKeys(\n client,\n signingKeyId!,\n signingKeyPrivate!,\n )\n\n if (!hasValidSigningKeys) {\n try {\n const {data} = await createSigningKeys(client)\n signingKeyId = data.id\n signingKeyPrivate = data.private_key\n await saveSecrets(\n client,\n token!,\n secretKey!,\n enableSignedUrls,\n signingKeyId,\n signingKeyPrivate,\n drmConfigId ?? '',\n )\n } catch (err: any) {\n // eslint-disable-next-line no-console\n console.log('Error while creating and saving signing key:', err?.message)\n throw err\n }\n }\n }\n return {\n token,\n secretKey,\n enableSignedUrls,\n signingKeyId,\n signingKeyPrivate,\n drmConfigId,\n }\n },\n [client, secrets],\n )\n}\n","export const name = 'mux-input' as const\n\n// Caching namespace, as suspend-react might be in use by other components on the page we must ensure we don't collide\nexport const cacheNs = 'sanity-plugin-mux-input' as const\n\nexport const muxSecretsDocumentId = 'secrets.mux' as const\n\nexport const DIALOGS_Z_INDEX = 60_000\n\n/** Mux guide explaining the mezzanine (\"master access\") file and how it differs from MP4 renditions. */\nexport const MEZZANINE_LEARN_MORE_URL =\n 'https://www.mux.com/docs/guides/download-for-offline-editing#enable-master-access'\n\nexport const THUMBNAIL_ASPECT_RATIO = 16 / 9\n\n/** To prevent excessive height, thumbnails and input should not go beyond to this aspect ratio. */\nexport const MIN_ASPECT_RATIO = 5 / 4\n\nexport const AUDIO_ASPECT_RATIO = 5 / 1\n","import {useMemo} from 'react'\nimport {useDocumentValues} from 'sanity'\n\nimport {muxSecretsDocumentId} from '../util/constants'\nimport type {Secrets} from '../util/types'\n\nconst path = [\n 'token',\n 'secretKey',\n 'enableSignedUrls',\n 'signingKeyId',\n 'signingKeyPrivate',\n 'drmConfigId',\n]\nexport const useSecretsDocumentValues = () => {\n const {error, isLoading, value} = useDocumentValues<Partial<Secrets> | null | undefined>(\n muxSecretsDocumentId,\n path,\n )\n const cache = useMemo(() => {\n const exists = Boolean(value)\n const secrets: Secrets = {\n token: value?.token || null,\n secretKey: value?.secretKey || null,\n enableSignedUrls: value?.enableSignedUrls || false,\n signingKeyId: value?.signingKeyId || null,\n signingKeyPrivate: value?.signingKeyPrivate || null,\n drmConfigId: value?.drmConfigId || null,\n }\n return {\n isInitialSetup: !exists,\n needsSetup: !secrets?.token || !secrets?.secretKey,\n secrets,\n }\n }, [value])\n\n return {error, isLoading, value: cache}\n}\n","import {useReducer} from 'react'\n\nimport type {Secrets} from '../util/types'\n\nexport interface State extends Pick<\n Secrets,\n 'token' | 'secretKey' | 'enableSignedUrls' | 'drmConfigId'\n> {\n submitting: boolean\n error: string | null\n}\nexport type Action =\n | {type: 'submit'}\n | {type: 'error'; payload: string}\n | {type: 'reset'; payload: Secrets}\n | {type: 'change'; payload: {name: 'token'; value: string}}\n | {type: 'change'; payload: {name: 'secretKey'; value: string}}\n | {type: 'change'; payload: {name: 'enableSignedUrls'; value: boolean}}\n | {type: 'change'; payload: {name: 'drmConfigId'; value: string}}\nfunction init({token, secretKey, enableSignedUrls, drmConfigId}: Secrets): State {\n return {\n submitting: false,\n error: null,\n // Form inputs don't set the state back to null when clearing a field, but uses empty strings\n // This ensures the `dirty` check works correctly\n token: token ?? '',\n secretKey: secretKey ?? '',\n enableSignedUrls: enableSignedUrls ?? false,\n drmConfigId: drmConfigId ?? '',\n }\n}\nfunction reducer(state: State, action: Action) {\n switch (action?.type) {\n case 'submit':\n return {...state, submitting: true, error: null}\n case 'error':\n return {...state, submitting: false, error: action.payload}\n case 'reset':\n return init(action.payload)\n case 'change':\n return {...state, [action.payload.name]: action.payload.value}\n default:\n throw new Error(`Unknown action type: ${(action as unknown as Action)?.type}`)\n }\n}\n\nexport const useSecretsFormState = (secrets: Secrets) => useReducer(reducer, secrets, init)\n","// Utils with a readName prefix are suspendable and should only be called in the render body\n// Not inside event callbacks or a useEffect.\n// They may be called dynamically, unlike useEffect\n\n// @TODO rename to readSigningPair\n\nimport type {SanityClient} from 'sanity'\nimport {suspend} from 'suspend-react'\n\nimport {cacheNs} from '../util/constants'\nimport {type Secrets} from '../util/types'\n\nexport const _id = 'secrets.mux' as const\n\nexport function readSecrets(client: SanityClient): Secrets {\n const {projectId, dataset} = client.config()\n return suspend(async () => {\n const data = await client.fetch(\n /* groq */ `*[_id == $_id][0]{\n token,\n secretKey,\n enableSignedUrls,\n signingKeyId,\n signingKeyPrivate,\n drmConfigId\n }`,\n {_id},\n )\n return {\n token: data?.token || null,\n secretKey: data?.secretKey || null,\n enableSignedUrls: Boolean(data?.enableSignedUrls) || false,\n signingKeyId: data?.signingKeyId || null,\n signingKeyPrivate: data?.signingKeyPrivate || null,\n drmConfigId: data?.drmConfigId || null,\n }\n }, [cacheNs, _id, projectId, dataset])\n}\n","import {useTheme_v2} from '@sanity/ui'\nimport {type CSSProperties, useId, useMemo} from 'react'\n\nexport interface Props {\n height?: number\n}\nexport default function MuxLogo({height = 26}: Props) {\n const id = useId()\n const theme = useTheme_v2()\n const fillColor = theme.color._dark ? 'white' : 'black'\n const titleId = useMemo(() => `${id}-title`, [id])\n\n const pathStyle: CSSProperties = {\n fillRule: 'nonzero',\n }\n\n return (\n <svg\n aria-labelledby={titleId}\n style={{height: `${height}px`}}\n viewBox=\"0 0 1600 500\"\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlSpace=\"preserve\"\n >\n <g id=\"Layer-1\" fill={fillColor}>\n <path\n d=\"M994.287,93.486c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m0,-93.486c-34.509,-0 -62.484,27.976 -62.484,62.486l0,187.511c0,68.943 -56.09,125.033 -125.032,125.033c-68.942,-0 -125.03,-56.09 -125.03,-125.033l0,-187.511c0,-34.51 -27.976,-62.486 -62.485,-62.486c-34.509,-0 -62.484,27.976 -62.484,62.486l0,187.511c0,137.853 112.149,250.003 249.999,250.003c137.851,-0 250.001,-112.15 250.001,-250.003l0,-187.511c0,-34.51 -27.976,-62.486 -62.485,-62.486\"\n style={pathStyle}\n />\n <path\n d=\"M1537.51,468.511c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m-275.883,-218.509l-143.33,143.329c-24.402,24.402 -24.402,63.966 0,88.368c24.402,24.402 63.967,24.402 88.369,-0l143.33,-143.329l143.328,143.329c24.402,24.4 63.967,24.402 88.369,-0c24.403,-24.402 24.403,-63.966 0.001,-88.368l-143.33,-143.329l0.001,-0.004l143.329,-143.329c24.402,-24.402 24.402,-63.965 0,-88.367c-24.402,-24.402 -63.967,-24.402 -88.369,-0l-143.329,143.328l-143.329,-143.328c-24.402,-24.401 -63.967,-24.402 -88.369,-0c-24.402,24.402 -24.402,63.965 0,88.367l143.329,143.329l0,0.004Z\"\n style={pathStyle}\n />\n <path\n d=\"M437.511,468.521c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m23.915,-463.762c-23.348,-9.672 -50.226,-4.327 -68.096,13.544l-143.331,143.329l-143.33,-143.329c-17.871,-17.871 -44.747,-23.216 -68.096,-13.544c-23.349,9.671 -38.574,32.455 -38.574,57.729l0,375.026c0,34.51 27.977,62.486 62.487,62.486c34.51,-0 62.486,-27.976 62.486,-62.486l0,-224.173l80.843,80.844c24.404,24.402 63.965,24.402 88.369,-0l80.843,-80.844l0,224.173c0,34.51 27.976,62.486 62.486,62.486c34.51,-0 62.486,-27.976 62.486,-62.486l0,-375.026c0,-25.274 -15.224,-48.058 -38.573,-57.729\"\n style={pathStyle}\n />\n </g>\n </svg>\n )\n}\n","import {styled} from 'styled-components'\n\nimport MuxLogo from './MuxLogo'\n\nconst Logo = styled.span`\n display: inline-block;\n height: 0.8em;\n margin-right: 1em;\n transform: translate(0.3em, -0.2em);\n`\n\nexport const Header = () => (\n <>\n <Logo>\n <MuxLogo height={13} />\n </Logo>\n API Credentials\n </>\n)\n","import {Box, Flex, Stack, Text} from '@sanity/ui'\nimport {memo} from 'react'\n\n// @TODO: get rid of this once v3 core is stable\n\nexport interface Props {\n children: React.ReactNode\n title: React.ReactNode\n description?: React.ReactNode\n inputId: string\n}\n\nfunction FormField(props: Props) {\n const {children, title, description, inputId} = props\n\n return (\n <Stack gap={1}>\n <Flex align=\"flex-end\">\n <Box flex={1} paddingY={2}>\n <Stack gap={2}>\n <Text as=\"label\" htmlFor={inputId} weight=\"semibold\" size={1}>\n {title || <em>Untitled</em>}\n </Text>\n\n {description && (\n <Text muted size={1}>\n {description}\n </Text>\n )}\n </Stack>\n </Box>\n </Flex>\n <div>{children}</div>\n </Stack>\n )\n}\n\nexport default memo(FormField)\n","import {Box, Button, Card, Checkbox, Dialog, Flex, Inline, Stack, Text, TextInput} from '@sanity/ui'\nimport {Code} from '@sanity/ui/code'\nimport {\n type ChangeEvent,\n type SubmitEvent,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n} from 'react'\nimport {clear, preload} from 'suspend-react'\n\nimport {useClient} from '../hooks/useClient'\nimport type {SetDialogState} from '../hooks/useDialogState'\nimport {useDialogState} from '../hooks/useDialogState'\nimport {useSaveSecrets} from '../hooks/useSaveSecrets'\nimport {useSecretsDocumentValues} from '../hooks/useSecretsDocumentValues'\nimport {useSecretsFormState} from '../hooks/useSecretsFormState'\nimport {cacheNs, DIALOGS_Z_INDEX} from '../util/constants'\nimport {_id as secretsId} from '../util/readSecrets'\nimport type {Secrets} from '../util/types'\nimport {Header} from './ConfigureApi.styled'\nimport FormField from './FormField'\n\n// Props for the dialog component when used with external state management\nexport interface ConfigureApiDialogProps {\n setDialogState: SetDialogState\n secrets: Secrets\n}\n\nconst fieldNames = ['token', 'secretKey', 'enableSignedUrls', 'drmConfigId'] as const\n\n// Internal dialog component that can be used with external state\nexport function ConfigureApiDialog({secrets, setDialogState}: ConfigureApiDialogProps) {\n const client = useClient()\n const [state, dispatch] = useSecretsFormState(secrets)\n const hasSecretsInitially = useMemo(() => secrets.token && secrets.secretKey, [secrets])\n const handleClose = useCallback(() => setDialogState(false), [setDialogState])\n const dirty = useMemo(\n () =>\n secrets.token !== state.token ||\n secrets.secretKey !== state.secretKey ||\n secrets.enableSignedUrls !== state.enableSignedUrls ||\n secrets.drmConfigId !== state.drmConfigId,\n [secrets, state],\n )\n const id = `ConfigureApi${useId()}`\n const [tokenId, secretKeyId, enableSignedUrlsId, drmConfigIdId] = useMemo<typeof fieldNames>(\n () => fieldNames.map((field) => `${id}-${field}`) as unknown as typeof fieldNames,\n [id],\n )\n const firstField = useRef<HTMLInputElement>(null)\n const handleSaveSecrets = useSaveSecrets(client, secrets)\n const saving = useRef(false)\n\n const handleSubmit = useCallback(\n (event: SubmitEvent<HTMLFormElement>) => {\n event.preventDefault()\n\n if (!saving.current && event.currentTarget.reportValidity()) {\n saving.current = true\n dispatch({type: 'submit'})\n const {token, secretKey, enableSignedUrls, drmConfigId} = state\n handleSaveSecrets({token, secretKey, enableSignedUrls, drmConfigId})\n .then((savedSecrets) => {\n const {projectId, dataset} = client.config()\n clear([cacheNs, secretsId, projectId, dataset])\n preload(() => Promise.resolve(savedSecrets), [cacheNs, secretsId, projectId, dataset])\n setDialogState(false)\n })\n .catch((err) => dispatch({type: 'error', payload: err.message}))\n .finally(() => {\n saving.current = false\n })\n }\n },\n [client, dispatch, handleSaveSecrets, setDialogState, state],\n )\n const handleChangeToken = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'token', value: event.currentTarget.value},\n })\n },\n [dispatch],\n )\n const handleChangeSecretKey = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'secretKey', value: event.currentTarget.value},\n })\n },\n [dispatch],\n )\n const handleChangeEnableSignedUrls = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'enableSignedUrls', value: event.currentTarget.checked},\n })\n },\n [dispatch],\n )\n const handleChangeDrmConfigId = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'drmConfigId', value: event.currentTarget.value},\n })\n },\n [dispatch],\n )\n\n useEffect(() => {\n if (firstField.current) {\n firstField.current.focus()\n }\n }, [firstField])\n\n return (\n <Dialog\n animate\n id={id}\n onClose={handleClose}\n onClickOutside={handleClose}\n header={<Header />}\n zOffset={DIALOGS_Z_INDEX}\n position=\"fixed\"\n width={1}\n >\n <Box padding={3}>\n <form onSubmit={handleSubmit} noValidate>\n <Stack gap={4}>\n {!hasSecretsInitially && (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"primary\">\n <Stack gap={3}>\n <Text size={1}>\n To set up a new access token, go to your{' '}\n <a\n href=\"https://dashboard.mux.com/settings/access-tokens\"\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n >\n account on mux.com\n </a>\n .\n </Text>\n <Text size={1}>\n The access token needs permissions: <strong>Mux Video </strong>\n (Full Access) and <strong>Mux Data</strong> (Read)\n <br />\n To use Signed URLs, the token must also have System permissions.\n <br />\n The credentials will be stored safely in a hidden document only available to\n editors.\n </Text>\n </Stack>\n </Card>\n )}\n <FormField title=\"Access Token\" inputId={tokenId}>\n <TextInput\n id={tokenId}\n ref={firstField}\n onChange={handleChangeToken}\n type=\"text\"\n value={state.token ?? ''}\n required={!!state.secretKey || state.enableSignedUrls}\n />\n </FormField>\n <FormField title=\"Secret Key\" inputId={secretKeyId}>\n <TextInput\n id={secretKeyId}\n onChange={handleChangeSecretKey}\n type=\"text\"\n value={state.secretKey ?? ''}\n required={!!state.token || state.enableSignedUrls}\n />\n </FormField>\n\n <Stack gap={4}>\n <Flex align=\"center\">\n <Checkbox\n id={enableSignedUrlsId}\n onChange={handleChangeEnableSignedUrls}\n checked={state.enableSignedUrls}\n style={{display: 'block'}}\n />\n <Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor={enableSignedUrlsId}>Enable Signed Urls</label>\n </Text>\n </Box>\n </Flex>\n {secrets.signingKeyId && state.enableSignedUrls ? (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"caution\">\n <Stack gap={3}>\n <Text size={1}>The signing key ID that Sanity will use is:</Text>\n <Code size={1}>{secrets.signingKeyId}</Code>\n <Text size={1}>\n This key is only used for previewing content in the Sanity UI.\n <br />\n You should generate a different key to use in your application server.\n </Text>\n </Stack>\n </Card>\n ) : null}\n </Stack>\n\n <FormField title=\"DRM Configuration ID\" inputId={drmConfigIdId}>\n <TextInput\n id={drmConfigIdId}\n onChange={handleChangeDrmConfigId}\n type=\"text\"\n value={state.drmConfigId ?? ''}\n required={false}\n />\n </FormField>\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"neutral\">\n <Stack gap={3}>\n <Text size={1}>\n DRM (Digital Rights Management) provides an extra layer of content security for\n video content streamed from Mux. For additional information check out our{' '}\n <a\n href=\"https://www.mux.com/docs/guides/protect-videos-with-drm#play-drm-protected-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n DRM Guide\n </a>\n .\n </Text>\n <Text size={1}>\n <a\n href=\"https://www.mux.com/support/human\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Contact us\n </a>{' '}\n to get started using DRM.\n </Text>\n </Stack>\n </Card>\n\n <Inline gap={2}>\n <Button\n text=\"Save\"\n disabled={!dirty}\n loading={state.submitting}\n tone=\"primary\"\n mode=\"default\"\n type=\"submit\"\n />\n <Button\n disabled={state.submitting}\n text=\"Cancel\"\n mode=\"bleed\"\n onClick={handleClose}\n />\n </Inline>\n {state.error && (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"critical\">\n <Text>{state.error}</Text>\n </Card>\n )}\n </Stack>\n </form>\n </Box>\n </Dialog>\n )\n}\n\n// Wrapper component that manages its own dialog state (used in VideosBrowser)\nexport default function ConfigureApi() {\n const [dialogOpen, setDialogOpen] = useDialogState()\n const secretDocumentValues = useSecretsDocumentValues()\n\n const openDialog = useCallback(() => setDialogOpen('secrets'), [setDialogOpen])\n\n if (dialogOpen === 'secrets') {\n return (\n <ConfigureApiDialog\n secrets={secretDocumentValues.value.secrets}\n setDialogState={setDialogOpen}\n />\n )\n }\n\n return <Button mode=\"bleed\" text=\"Configure plugin\" onClick={openDialog} />\n}\n","import {truncateString} from 'sanity'\n\n/**\n * Generates a placeholder title for a Mux asset when no title is available.\n * This format is used when importing assets that don't have a title in Mux.\n *\n * @param assetId - The Mux asset ID\n * @returns A placeholder title in the format \"Asset #[truncated-id]\"\n */\nexport function generateAssetPlaceholder(assetId: string): string {\n return `Asset #${truncateString(assetId, 15)}`\n}\n\n/**\n * Checks if a filename is empty or has the placeholder format.\n * This is used to determine if a video title should be updated during metadata sync.\n *\n * @param filename - The current filename/title of the video\n * @param assetId - The Mux asset ID to check against\n * @returns true if the filename is empty or matches the placeholder format\n */\nexport function isEmptyOrPlaceholderTitle(filename: string | undefined, assetId: string): boolean {\n // Check if filename is empty/undefined\n if (!filename || filename.trim() === '') {\n return true\n }\n\n // Check if filename matches the placeholder format for this asset\n const placeholder = generateAssetPlaceholder(assetId)\n return filename === placeholder\n}\n","import type {MuxAsset} from './types'\n\nexport function parseMuxDate(date: MuxAsset['created_at']): Date {\n return new Date(Number(date) * 1000)\n}\n","import type {SanityClient} from 'sanity'\n\nimport {getMuxAddonClient} from '../util/muxAddonClient'\nimport {PLUGIN_VERSION_QUERY} from '../util/pluginVersion'\nimport type {MuxAsset, VideoAssetDocument} from '../util/types'\n\nexport function deleteAssetOnMux(client: SanityClient, assetId: string) {\n const {dataset} = client.config()\n return getMuxAddonClient(client).request<void>({\n url: `/addons/mux/assets/${dataset}/${assetId}`,\n withCredentials: true,\n method: 'DELETE',\n query: PLUGIN_VERSION_QUERY,\n })\n}\n\nexport async function deleteAsset({\n client,\n asset,\n deleteOnMux,\n}: {\n client: SanityClient\n asset: VideoAssetDocument\n deleteOnMux: boolean\n}) {\n if (!asset?._id) return true\n\n try {\n await client.delete(asset._id)\n } catch {\n return 'failed-sanity'\n }\n\n if (deleteOnMux && asset?.assetId) {\n try {\n await deleteAssetOnMux(client, asset.assetId)\n } catch {\n return 'failed-mux'\n }\n }\n\n return true\n}\n\nexport function getAsset(client: SanityClient, assetId: string) {\n const {dataset} = client.config()\n return getMuxAddonClient(client).request<{data: MuxAsset}>({\n url: `/addons/mux/assets/${dataset}/data/${assetId}`,\n withCredentials: true,\n method: 'GET',\n query: PLUGIN_VERSION_QUERY,\n })\n}\n\nexport function listAssets(\n client: SanityClient,\n options: {limit?: number; cursor?: string | null},\n) {\n const {dataset} = client.config()\n const query: {limit?: string; cursor?: string} = {}\n\n if (options.limit) {\n query.limit = options.limit.toString()\n }\n if (options.cursor) {\n query.cursor = options.cursor\n }\n\n return getMuxAddonClient(client).request<{data: MuxAsset[]; next_cursor?: string | null}>({\n url: `/addons/mux/assets/${dataset}/data/list`,\n withCredentials: true,\n method: 'GET',\n query: {...query, ...PLUGIN_VERSION_QUERY},\n })\n}\n\n/**\n * Adds a new text track to an existing asset using a VTT file URL\n */\nexport function addTextTrackFromUrl(\n client: SanityClient,\n assetId: string,\n vttUrl: string,\n options: {\n language_code: string\n name: string\n text_type?: 'subtitles'\n },\n) {\n const {dataset} = client.config()\n\n return getMuxAddonClient(client).request<{data: MuxAsset}>({\n url: `/addons/mux/assets/${dataset}/${assetId}/tracks`,\n withCredentials: true,\n method: 'POST',\n body: {\n url: vttUrl,\n type: 'text',\n language_code: options.language_code,\n name: options.name,\n text_type: options.text_type || 'subtitles',\n },\n headers: {\n 'Content-Type': 'application/json',\n },\n query: PLUGIN_VERSION_QUERY,\n })\n}\n\n/**\n * Generates subtitles automatically for an audio track\n */\nexport function generateSubtitles(\n client: SanityClient,\n assetId: string,\n audioTrackId: string,\n options: {\n language_code: string\n name: string\n },\n) {\n const {dataset} = client.config()\n return getMuxAddonClient(client).request<{data: MuxAsset}>({\n url: `/addons/mux/assets/${dataset}/${assetId}/tracks/${audioTrackId}/generate-subtitles`,\n withCredentials: true,\n method: 'POST',\n body: {\n generated_subtitles: [\n {\n language_code: options.language_code,\n name: options.name,\n },\n ],\n },\n headers: {\n 'Content-Type': 'application/json',\n },\n query: PLUGIN_VERSION_QUERY,\n })\n}\n\n/**\n * Deletes a text track from an asset\n */\nexport function deleteTextTrack(client: SanityClient, assetId: string, trackId: string) {\n const {dataset} = client.config()\n return getMuxAddonClient(client).request<{data: MuxAsset}>({\n url: `/addons/mux/assets/${dataset}/${assetId}/tracks/${trackId}`,\n withCredentials: true,\n method: 'DELETE',\n query: PLUGIN_VERSION_QUERY,\n })\n}\n\n/**\n * Updates master access (the \"mezzanine\" file in Mux's docs) on a Mux asset, via the addon proxy.\n * @see {@link https://docs.mux.com/api-reference/video/assets/update-asset-master-access}\n */\nexport function updateMasterAccess(\n client: SanityClient,\n assetId: string,\n masterAccess: 'temporary' | 'none',\n) {\n const {dataset} = client.config()\n return getMuxAddonClient(client).request<{data: MuxAsset}>({\n url: `/addons/mux/assets/${dataset}/${assetId}/master-access`,\n withCredentials: true,\n method: 'PUT',\n body: {master_access: masterAccess},\n headers: {\n 'Content-Type': 'application/json',\n },\n query: PLUGIN_VERSION_QUERY,\n })\n}\n","import {useEffect, useState} from 'react'\nimport {defer, of, timer} from 'rxjs'\nimport {concatMap, expand, tap} from 'rxjs/operators'\nimport type {SanityClient} from 'sanity'\n\nimport {listAssets} from '../actions/assets'\nimport type {MuxAsset} from '../util/types'\n\nconst ASSETS_PER_PAGE = 100\n\ntype MuxAssetsState = {\n cursor: string | null\n loading: boolean\n data?: MuxAsset[]\n error?: FetchError\n hasSkippedAssetsWithoutPlayback?: boolean\n}\n\ntype FetchError =\n | {\n _tag: 'FetchError'\n }\n | {_tag: 'MuxError'; error: unknown}\n\ntype PageResult = (\n | {\n data: MuxAsset[]\n next_cursor: string | null\n }\n | {\n error: FetchError\n }\n) & {\n cursor: string | null\n}\n\n/**\n * @docs {@link https://docs.mux.com/api-reference#video/operation/list-assets}\n */\nasync function fetchMuxAssetsPage(\n client: SanityClient,\n cursor: string | null,\n): Promise<PageResult> {\n try {\n const response = await listAssets(client, {\n limit: ASSETS_PER_PAGE,\n cursor,\n })\n\n return {\n cursor,\n data: response.data,\n next_cursor: response.next_cursor || null,\n }\n } catch {\n return {\n cursor,\n error: {_tag: 'FetchError'},\n }\n }\n}\n\nfunction accumulateIntermediateState(\n currentState: MuxAssetsState,\n pageResult: PageResult,\n): MuxAssetsState {\n const currentData = ('data' in currentState && currentState.data) || []\n const newAssets = ('data' in pageResult && pageResult.data) || []\n\n // Filter assets and check for skipped items\n const {validAssets, skippedInThisPage} = newAssets.reduce<{\n validAssets: MuxAsset[]\n skippedInThisPage: boolean\n }>(\n (acc, asset) => {\n const hasPlaybackIds = asset.playback_ids && asset.playback_ids.length > 0\n const isDuplicate = currentData.some((a) => a.id === asset.id)\n\n if (!hasPlaybackIds) {\n acc.skippedInThisPage = true\n }\n\n if (hasPlaybackIds && !isDuplicate) {\n acc.validAssets.push(asset)\n }\n\n return acc\n },\n {validAssets: [], skippedInThisPage: false},\n )\n\n return {\n ...currentState,\n data: [...currentData, ...validAssets],\n error:\n 'error' in pageResult\n ? pageResult.error\n : // Reset error if current page is successful\n undefined,\n cursor: 'next_cursor' in pageResult ? pageResult.next_cursor : pageResult.cursor,\n loading: true,\n hasSkippedAssetsWithoutPlayback:\n currentState.hasSkippedAssetsWithoutPlayback || skippedInThisPage,\n }\n}\n\nfunction hasMorePages(pageResult: PageResult) {\n return (\n typeof pageResult === 'object' && 'next_cursor' in pageResult && pageResult.next_cursor !== null\n )\n}\n\n/**\n * Fetches all assets from a Mux environment. Rules:\n * - One page at a time\n * - Uses cursor-based pagination\n * - We've finished fetching when `next_cursor` is null\n * - Rate limiting to one request per 2 seconds\n * - Update state while still fetching to give feedback to users\n */\nexport default function useMuxAssets({client, enabled}: {client: SanityClient; enabled: boolean}) {\n const [state, setState] = useState<MuxAssetsState>({loading: true, cursor: null})\n\n useEffect(() => {\n if (!enabled) return\n\n const subscription = defer(() =>\n fetchMuxAssetsPage(\n client,\n // When we've already successfully loaded before (fully or partially), we start from the next cursor to avoid re-fetching\n 'data' in state && state.data && state.data.length > 0 && !state.error\n ? state.cursor\n : null,\n ),\n )\n .pipe(\n // Here we use \"expand\" to recursively fetch next pages\n expand((pageResult) => {\n // if fetched page has next_cursor, we continue emitting, requesting the next page\n // after 2s to avoid rate limiting\n if (hasMorePages(pageResult)) {\n return timer(2000).pipe(\n concatMap(() =>\n defer(() =>\n fetchMuxAssetsPage(\n client,\n 'next_cursor' in pageResult ? pageResult.next_cursor : null,\n ),\n ),\n ),\n )\n }\n\n // Else, we stop emitting\n return of()\n }),\n\n // On each iteration, persist intermediate states to give feedback to users\n tap((pageResult) =>\n setState((prevState) => accumulateIntermediateState(prevState, pageResult)),\n ),\n )\n .subscribe({\n // Once done, let the user know we've stopped loading\n complete: () => {\n setState((prev) => ({\n ...prev,\n loading: false,\n }))\n },\n })\n\n // Unsubscribe on component unmount to prevent memory leaks or fetching unnecessarily\n return () => subscription.unsubscribe()\n // oxlint-disable-next-line react/rule-suppression\n // oxlint-disable-next-line react/exhaustive-deps -- secrets/pluginConfig are stable for the asset fetch lifecycle once enabled\n }, [enabled])\n\n return state\n}\n","import {uuid} from '@sanity/uuid'\nimport {useMemo, useState} from 'react'\nimport {createHookFromObservableFactory, type DocumentStore, useDocumentStore} from 'sanity'\n\nimport {generateAssetPlaceholder} from '../util/assetTitlePlaceholder'\nimport {parseMuxDate} from '../util/parsers'\nimport type {MuxAsset, VideoAssetDocument} from '../util/types'\nimport {SANITY_API_VERSION, useClient} from './useClient'\nimport useMuxAssets from './useMuxAssets'\nimport {useSecretsDocumentValues} from './useSecretsDocumentValues'\n\ntype ImportState = 'closed' | 'idle' | 'importing' | 'done' | 'error'\n\nexport type AssetInSanity = {\n uploadId: string\n assetId: string\n}\n\nexport default function useImportMuxAssets() {\n const documentStore = useDocumentStore()\n const client = useClient()\n\n const [assetsInSanity, assetsInSanityLoading] = useAssetsInSanity(documentStore)\n\n const secretDocumentValues = useSecretsDocumentValues()\n const hasSecrets = !!secretDocumentValues.value.secrets?.secretKey\n\n const [importError, setImportError] = useState<unknown>()\n const [importState, setImportState] = useState<ImportState>('closed')\n const dialogOpen = importState !== 'closed'\n\n const muxAssets = useMuxAssets({\n client,\n enabled: hasSecrets && dialogOpen,\n })\n\n const missingAssets = useMemo(() => {\n return assetsInSanity && muxAssets.data\n ? muxAssets.data.filter((a) => !assetExistsInSanity(a, assetsInSanity))\n : undefined\n }, [assetsInSanity, muxAssets.data])\n\n const [selectedAssets, setSelectedAssets] = useState<MuxAsset[]>([])\n\n const closeDialog = () => {\n if (importState !== 'importing') setImportState('closed')\n }\n const openDialog = () => {\n if (importState === 'closed') setImportState('idle')\n }\n\n async function importAssets() {\n setImportState('importing')\n const documents = selectedAssets.flatMap((asset) => muxAssetToSanityDocument(asset) || [])\n\n const tx = client.transaction()\n documents.forEach((doc) => tx.create(doc))\n\n try {\n await tx.commit({returnDocuments: false})\n setSelectedAssets([])\n setImportState('done')\n } catch (error) {\n setImportState('error')\n setImportError(error)\n }\n }\n\n return {\n assetsInSanityLoading,\n closeDialog,\n dialogOpen,\n importState,\n importError,\n hasSecrets,\n importAssets,\n missingAssets,\n muxAssets,\n openDialog,\n selectedAssets,\n setSelectedAssets,\n }\n}\n\nfunction muxAssetToSanityDocument(asset: MuxAsset): VideoAssetDocument | undefined {\n const playbackId = (asset.playback_ids || []).find((p) => p.id)?.id\n\n if (!playbackId) return undefined\n\n return {\n _id: uuid(),\n _type: 'mux.videoAsset',\n _updatedAt: new Date().toISOString(),\n _createdAt: parseMuxDate(asset.created_at).toISOString(),\n assetId: asset.id,\n playbackId,\n filename: asset.meta?.title ?? generateAssetPlaceholder(asset.id),\n status: asset.status,\n data: asset,\n }\n}\n\nconst useAssetsInSanity = createHookFromObservableFactory<AssetInSanity[], DocumentStore>(\n (documentStore) => {\n return documentStore.listenQuery(\n /* groq */ `*[_type == \"mux.videoAsset\"] {\n \"uploadId\": coalesce(uploadId, data.upload_id),\n \"assetId\": coalesce(assetId, data.id),\n }`,\n {},\n {\n apiVersion: SANITY_API_VERSION,\n },\n )\n },\n)\n\nfunction assetExistsInSanity(asset: MuxAsset, existingAssets: AssetInSanity[]) {\n // Don't allow importing assets that are not ready\n if (asset.status !== 'ready') return false\n\n return existingAssets.some(\n (existing) => existing.assetId === asset.id || existing.uploadId === asset.upload_id,\n )\n}\n","import {useEffect, useState} from 'react'\n\ntype IntersectionOptions = {\n root?: Element | null\n rootMargin?: string\n threshold?: number\n onChange?: (inView: boolean) => void\n}\n\nexport function useInView(\n ref: React.RefObject<HTMLDivElement | null>,\n options: IntersectionOptions = {},\n) {\n const [inView, setInView] = useState(false)\n\n useEffect(() => {\n if (!ref.current) return\n\n const observer = new IntersectionObserver(([entry], obs) => {\n // ==== from react-intersection-observer ====\n // While it would be nice if you could just look at isIntersecting to determine if the component is inside the viewport, browsers can't agree on how to use it.\n // -Firefox ignores `threshold` when considering `isIntersecting`, so it will never be false again if `threshold` is > 0\n const nowInView =\n entry!.isIntersecting &&\n obs.thresholds.some((threshold) => entry!.intersectionRatio >= threshold)\n\n // Update our state when observer callback fires\n setInView(nowInView)\n options?.onChange?.(nowInView)\n }, options)\n\n const toObserve = ref.current\n observer.observe(toObserve)\n\n return () => {\n if (toObserve) observer.unobserve(toObserve)\n }\n }, [options, ref])\n\n return inView\n}\n","import type {\n AdvancedPlaybackPolicy,\n MuxPlaybackId,\n PlaybackPolicy,\n VideoAssetDocument,\n} from './types'\n\n/* - Returns the playback id of the asset based on the specified priority.\n By default chooses the \"strongest\" policy\n - Otherwise, returns the first playback id in the array.\n */\nexport function getPlaybackId(\n asset: Pick<VideoAssetDocument, 'data'>,\n priority: string[] = ['drm', 'signed', 'public'],\n): string {\n try {\n if (!asset) {\n throw new TypeError('Tried to get playback Id with no asset')\n }\n\n const playbackIds = asset.data?.playback_ids\n if (playbackIds && playbackIds.length > 0) {\n for (const policy of priority) {\n const match = playbackIds.find((entry) => entry.policy === policy)\n if (match) {\n return match.id\n }\n }\n\n return playbackIds[0]!.id\n }\n\n throw new TypeError('Missing playbackId')\n } catch (e) {\n console.error('Asset is missing a playbackId', {asset}, e)\n throw e\n }\n}\n\nexport function getPlaybackPolicy(\n asset: Pick<VideoAssetDocument, 'data' | 'playbackId'>,\n): MuxPlaybackId | undefined {\n return (\n asset.data?.playback_ids?.find(\n (playbackId) => getPlaybackId(asset, ['drm', 'signed', 'public']) === playbackId.id,\n ) ?? {id: '', policy: 'public'}\n )\n}\n\nexport function getPlaybackPolicyById(\n asset: Pick<VideoAssetDocument, 'data'>,\n playbackId: string,\n): MuxPlaybackId | undefined {\n return asset.data?.playback_ids?.find((entry) => playbackId === entry.id)\n}\n\nexport function hasPlaybackPolicy(\n data: Partial<{\n playback_policy?: PlaybackPolicy[]\n advanced_playback_policies: AdvancedPlaybackPolicy[]\n }>,\n policy: PlaybackPolicy,\n) {\n return (\n (data.advanced_playback_policies &&\n data.advanced_playback_policies.find((p) => p.policy === policy)) ||\n data.playback_policy?.find((p) => p === policy)\n )\n}\n","import type {SanityClient} from 'sanity'\nimport {suspend} from 'suspend-react'\n\nimport {readSecrets} from './readSecrets'\nimport type {AnimatedThumbnailOptions, ThumbnailOptions} from './types'\n\nexport type Audience = 'g' | 's' | 't' | 'v' | 'd'\n\nexport type Payload<T extends Audience> = T extends 'g'\n ? AnimatedThumbnailOptions\n : T extends 's'\n ? never\n : T extends 't'\n ? ThumbnailOptions\n : T extends 'v'\n ? never\n : T extends 'd'\n ? never\n : never\n\n/**\n * Uses suspend. Call this with {@link tryWithSuspend} or rethrow the Promise\n */\nexport function generateJwt<T extends Audience>(\n client: SanityClient,\n playbackId: string,\n aud: T,\n payload?: Payload<T>,\n): string {\n const {signingKeyId, signingKeyPrivate} = readSecrets(client)\n if (!signingKeyId) {\n throw new TypeError(\"Missing `signingKeyId`.\\n Check your plugin's configuration\")\n }\n if (!signingKeyPrivate) {\n throw new TypeError(\"Missing `signingKeyPrivate`.\\n Check your plugin's configuration\")\n }\n\n /* Using suspend means we need to use Suspense on parent components.\n Also, this will throw a Promise under the hood (apparently common in React), \n so if we want to catch errors we have to take this into account in catch blocks\n and rethrow promises. */\n // @ts-expect-error - handle missing typings for this package\n const {default: sign} = suspend(() => import('jsonwebtoken-esm/sign'), ['jsonwebtoken-esm/sign'])\n\n return sign(\n payload ? JSON.parse(JSON.stringify(payload, (_, v) => v ?? undefined)) : {},\n atob(signingKeyPrivate),\n {\n algorithm: 'RS256',\n keyid: signingKeyId,\n audience: aud,\n subject: playbackId,\n noTimestamp: true,\n expiresIn: '12h',\n },\n )\n}\n","import type {SanityClient} from 'sanity'\n\nimport {getPlaybackId} from '../util/getPlaybackPolicy'\nimport {type Audience, generateJwt} from './generateJwt'\nimport {getPlaybackPolicyById} from './getPlaybackPolicy'\nimport type {AssetThumbnailOptions} from './types'\n\n/**\n * May throw a Promise. Call this with {@link tryWithSuspend} or rethrow the Promise\n */\nexport function createUrlParamsObject(\n client: SanityClient,\n asset: AssetThumbnailOptions['asset'],\n params: object,\n audience: Audience,\n) {\n const playbackId = getPlaybackId(asset)\n\n let searchParams = new URLSearchParams(\n JSON.parse(JSON.stringify(params, (_, v) => v ?? undefined)),\n )\n const playbackPolicy = getPlaybackPolicyById(asset, playbackId)?.policy\n if (playbackPolicy === 'signed' || playbackPolicy === 'drm') {\n const token = generateJwt(client, playbackId, audience, params)\n searchParams = new URLSearchParams({token})\n }\n\n return {playbackId, searchParams}\n}\n","import type {SanityClient} from 'sanity'\n\nimport {createUrlParamsObject} from './createUrlParamsObject'\nimport type {AnimatedThumbnailOptions, MuxAnimatedThumbnailUrl} from './types'\nimport {type AssetThumbnailOptions} from './types'\n\nexport interface AnimatedPosterSrcOptions extends AnimatedThumbnailOptions {\n asset: AssetThumbnailOptions['asset']\n client: SanityClient\n}\n\nexport function getAnimatedPosterSrc({\n asset,\n client,\n height,\n width,\n start = asset.thumbTime ? Math.max(0, asset.thumbTime - 2.5) : 0,\n end = start + 5,\n fps = 15,\n}: AnimatedPosterSrcOptions): MuxAnimatedThumbnailUrl {\n const params = {height, width, start, end, fps}\n\n const {playbackId, searchParams} = createUrlParamsObject(client, asset, params, 'g')\n\n return `https://image.mux.com/${playbackId}/animated.gif?${searchParams}`\n}\n","import type {SanityClient} from 'sanity'\n\nimport {createUrlParamsObject} from './createUrlParamsObject'\nimport type {MuxThumbnailUrl, ThumbnailOptions} from './types'\nimport {type AssetThumbnailOptions} from './types'\n\nexport interface PosterSrcOptions extends ThumbnailOptions {\n asset: AssetThumbnailOptions['asset']\n client: SanityClient\n}\n\nexport function getPosterSrc({\n asset,\n client,\n fit_mode,\n height,\n time = asset.thumbTime ?? undefined,\n width,\n}: PosterSrcOptions): MuxThumbnailUrl {\n const params = {fit_mode, height, width}\n if (time !== undefined) {\n ;(params as any).time = time\n }\n\n const {playbackId, searchParams} = createUrlParamsObject(client, asset, params, 't')\n\n return `https://image.mux.com/${playbackId}/thumbnail.png?${searchParams}`\n}\n","/**\n * When running `suspend()` from react-suspend a function may throw a Promise\n * causing unexpected behavior when catching.\n * @param block Your block of code that uses suspend\n * @param onError (optional) How to handle a regular Error\n * @returns Whatever is returned by the block if it succeeds, otherwise whatever is resolved by onError if defined\n * @throws rethrows the caught Promise to comply with Suspense logic\n */\nexport function tryWithSuspend<T, E>(\n block: () => T,\n onError?: (error: Error) => E,\n): T | E | undefined {\n try {\n return block()\n } catch (errorOrPromise) {\n if (errorOrPromise instanceof Promise) {\n // react-suspend will throw a Promise\n throw errorOrPromise\n }\n return onError ? onError(errorOrPromise as Error) : undefined\n }\n}\n","import {ErrorOutlineIcon} from '@sanity/icons/ErrorOutline'\nimport {Box, Card, type CardTone, Spinner, Stack, Text} from '@sanity/ui'\nimport {Suspense, useMemo, useRef, useState} from 'react'\nimport {styled} from 'styled-components'\n\nimport {useClient} from '../hooks/useClient'\nimport {useInView} from '../hooks/useInView'\nimport {THUMBNAIL_ASPECT_RATIO} from '../util/constants'\nimport {getAnimatedPosterSrc} from '../util/getAnimatedPosterSrc'\nimport {getPosterSrc} from '../util/getPosterSrc'\nimport {tryWithSuspend} from '../util/tryWithSuspend'\nimport type {AssetThumbnailOptions, MuxAnimatedThumbnailUrl, MuxThumbnailUrl} from '../util/types'\n\nconst Image = styled.img`\n transition: opacity 0.175s ease-out 0s;\n display: block;\n width: 100%;\n height: 100%;\n object-fit: contain;\n object-position: center center;\n`\n\ntype ImageStatus = 'loading' | 'error' | 'loaded'\n\nconst STATUS_TO_TONE: Record<ImageStatus, CardTone> = {\n loading: 'transparent',\n error: 'critical',\n loaded: 'default',\n}\n\nexport default function VideoThumbnail({\n asset,\n width,\n staticImage = false,\n}: {\n asset: AssetThumbnailOptions['asset']\n width?: number\n staticImage?: boolean\n}) {\n const posterWidth = width || 250\n const client = useClient()\n const ref = useRef<HTMLDivElement | null>(null)\n const inView = useInView(ref)\n\n const [status, setStatus] = useState<ImageStatus>('loading')\n const [error, setError] = useState<string | null>(null)\n\n const thumbnailSrc = useMemo(() => {\n return tryWithSuspend(\n () => {\n let thumbnail: MuxAnimatedThumbnailUrl | MuxThumbnailUrl | undefined\n\n if (staticImage) thumbnail = getPosterSrc({asset, client, width: posterWidth})\n else thumbnail = getAnimatedPosterSrc({asset, client, width: posterWidth})\n return thumbnail\n },\n (err: Error) => {\n // oxlint-disable-next-line react/todo\n handleError(err.message)\n return undefined\n },\n )\n }, [asset, client, posterWidth, staticImage])\n\n function handleLoad() {\n setStatus('loaded')\n }\n\n function handleError(err?: string) {\n setStatus('error')\n if (err) {\n setError(err)\n } else {\n setError('Failed loading thumbnail')\n }\n }\n\n return (\n <Suspense fallback={<span>Preparing thumbnail</span>}>\n <Card\n style={{\n aspectRatio: THUMBNAIL_ASPECT_RATIO,\n position: 'relative',\n maxWidth: width ? `${width}px` : undefined,\n width: '100%',\n flex: 1,\n }}\n border\n radius={2}\n ref={ref}\n tone={STATUS_TO_TONE[status]}\n >\n {inView ? (\n <>\n {status === 'loading' && (\n <Box\n style={{\n position: 'absolute',\n left: '50%',\n top: '50%',\n transform: 'translate(-50%, -50%)',\n }}\n >\n <Spinner />\n </Box>\n )}\n {status === 'error' && (\n <Stack\n gap={4}\n style={{\n position: 'absolute',\n width: '100%',\n left: 0,\n top: '50%',\n transform: 'translateY(-50%)',\n justifyItems: 'center',\n }}\n >\n <Text size={4} muted>\n <ErrorOutlineIcon style={{fontSize: '1.75em'}} />\n </Text>\n <Text muted align=\"center\">\n {error}\n </Text>\n </Stack>\n )}\n <Image\n src={thumbnailSrc ?? undefined}\n alt={`Preview for ${staticImage ? 'image' : 'video'} ${asset.filename || asset.assetId}`}\n onLoad={handleLoad}\n onError={() => handleError()}\n style={{opacity: status === 'loaded' ? 1 : 0}}\n />\n </>\n ) : null}\n </Card>\n </Suspense>\n )\n}\n","import {CheckmarkCircleIcon} from '@sanity/icons/CheckmarkCircle'\nimport {ErrorOutlineIcon} from '@sanity/icons/ErrorOutline'\nimport {InfoOutlineIcon} from '@sanity/icons/InfoOutline'\nimport {RetrieveIcon} from '@sanity/icons/Retrieve'\nimport {RetryIcon} from '@sanity/icons/Retry'\nimport {Box, Button, Card, Checkbox, Dialog, Flex, Heading, Spinner, Stack, Text} from '@sanity/ui'\nimport {Code} from '@sanity/ui/code'\nimport {truncateString, useFormattedDuration} from 'sanity'\nimport {styled} from 'styled-components'\n\nimport useImportMuxAssets from '../hooks/useImportMuxAssets'\nimport {DIALOGS_Z_INDEX} from '../util/constants'\nimport type {MuxAsset} from '../util/types'\nimport VideoThumbnail from './VideoThumbnail'\n\nconst MissingAssetCheckbox = styled(Checkbox)`\n position: static !important;\n\n input::after {\n content: '';\n position: absolute;\n inset: 0;\n display: block;\n cursor: pointer;\n z-index: 1000;\n }\n`\n\nfunction MissingAsset({\n asset,\n selectAsset,\n selected,\n}: {\n asset: MuxAsset\n selectAsset: (selected: boolean) => void\n selected: boolean\n}) {\n const duration = useFormattedDuration(asset.duration * 1000)\n\n return (\n <Card\n key={asset.id}\n tone={selected ? 'positive' : undefined}\n border\n paddingX={2}\n paddingY={3}\n style={{position: 'relative'}}\n radius={1}\n >\n <Flex align=\"center\" gap={2}>\n <MissingAssetCheckbox\n checked={selected}\n onChange={(e) => {\n selectAsset(e.currentTarget.checked)\n }}\n aria-label={selected ? `Import video ${asset.id}` : `Skip import of video ${asset.id}`}\n />\n <VideoThumbnail\n asset={{\n assetId: asset.id,\n data: asset,\n filename: asset.id,\n playbackId: asset.playback_ids.find((p) => p.id)?.id,\n }}\n width={150}\n />\n <Stack gap={2}>\n <Flex align=\"center\" gap={1}>\n <Code size={2}>{truncateString(asset.id, 15)}</Code>{' '}\n <Text muted size={2}>\n ({duration.formatted})\n </Text>\n </Flex>\n <Text size={1}>\n Uploaded at{' '}\n {new Date(Number(asset.created_at) * 1000).toLocaleDateString('en', {\n year: 'numeric',\n day: '2-digit',\n month: '2-digit',\n })}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )\n}\n\nfunction ImportVideosDialog(props: ReturnType<typeof useImportMuxAssets>) {\n const {importState} = props\n\n const canTriggerImport =\n (importState === 'idle' || importState === 'error') && props.selectedAssets.length > 0\n const isImporting = importState === 'importing'\n const noAssetsToImport =\n props.missingAssets?.length === 0 && !props.muxAssets.loading && !props.assetsInSanityLoading\n\n return (\n <Dialog\n animate\n header={'Import videos from Mux'}\n zOffset={DIALOGS_Z_INDEX}\n id=\"video-details-dialog\"\n onClose={props.closeDialog}\n onClickOutside={props.closeDialog}\n width={1}\n position=\"fixed\"\n footer={\n importState !== 'done' &&\n !noAssetsToImport && (\n <Card padding={3}>\n <Flex justify=\"space-between\" align=\"center\">\n <Button\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Cancel\"\n tone=\"critical\"\n onClick={props.closeDialog}\n disabled={isImporting}\n />\n {props.missingAssets && (\n <Button\n icon={RetrieveIcon}\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text={\n props.selectedAssets?.length > 0\n ? `Import ${props.selectedAssets.length} video(s)`\n : 'No video(s) selected'\n }\n tone=\"positive\"\n onClick={props.importAssets}\n iconRight={isImporting && Spinner}\n disabled={!canTriggerImport}\n />\n )}\n </Flex>\n </Card>\n )\n }\n >\n <Box padding={3}>\n {/* WARNING: SKIPPED ASSETS WITHOUT PLAYBACK */}\n {props.muxAssets.hasSkippedAssetsWithoutPlayback && (\n <Card tone=\"caution\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <InfoOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Some videos were skipped\n </Text>\n <Text size={1}>\n Videos without playback IDs cannot be imported and have been excluded from the\n list.\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* LOADING ASSETS STATE */}\n {(props.muxAssets.loading || props.assetsInSanityLoading) && (\n <Card tone=\"primary\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Loading assets from Mux\n </Text>\n <Text size={1}>\n This may take a while.\n {props.missingAssets &&\n props.missingAssets.length > 0 &&\n ` There are at least ${props.missingAssets.length} video${props.missingAssets.length > 1 ? 's' : ''} currently not in Sanity...`}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR LOADING MUX */}\n {props.muxAssets.error && (\n <Card tone=\"critical\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error getting all data from Mux\n </Text>\n <Text size={1}>\n {props.missingAssets\n ? `But we've found ${props.missingAssets.length} video${props.missingAssets.length > 1 ? 's' : ''} not in Sanity, which you can start importing now.`\n : 'Please try again or contact a developer for help.'}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* IMPORTING STATE */}\n {importState === 'importing' && (\n <Card tone=\"primary\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Importing {props.selectedAssets.length} video\n {props.selectedAssets.length > 1 && 's'} from Mux\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR IMPORTING */}\n {importState === 'error' && (\n <Card tone=\"critical\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error importing videos\n </Text>\n <Text size={1}>\n {props.importError\n ? `Error: ${props.importError}`\n : 'Please try again or contact a developer for help.'}\n </Text>\n <Box marginTop={1}>\n <Button\n icon={RetryIcon}\n text=\"Retry\"\n tone=\"primary\"\n onClick={props.importAssets}\n />\n </Box>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* NO ASSETS TO IMPORT or SUCESS STATE */}\n {(noAssetsToImport || importState === 'done') && (\n <Stack paddingY={5} marginBottom={4} gap={3} style={{textAlign: 'center'}}>\n <Box>\n <CheckmarkCircleIcon fontSize={48} />\n </Box>\n <Heading size={2}>\n {importState === 'done'\n ? `Videos imported successfully`\n : 'There are no Mux videos to import'}\n </Heading>\n <Text size={2}>\n {importState === 'done'\n ? 'You can now use them in your Sanity content.'\n : \"They're all in Sanity and ready to be used in your content.\"}\n </Text>\n </Stack>\n )}\n\n {/* MISSING ASSETS SELECTOR */}\n {props.missingAssets &&\n props.missingAssets.length > 0 &&\n (importState === 'idle' || importState === 'error') && (\n <Stack gap={4}>\n <Heading size={1}>\n There are {props.missingAssets.length}\n {props.muxAssets.loading && '+'} Mux video{props.missingAssets.length > 1 && 's'}{' '}\n not in Sanity\n </Heading>\n {!props.muxAssets.loading && (\n <Flex align=\"center\" paddingX={2}>\n <Checkbox\n id=\"import-all\"\n style={{display: 'block'}}\n onClick={(e) => {\n const selectAll = e.currentTarget.checked\n if (selectAll) {\n // eslint-disable-next-line no-unused-expressions\n props.missingAssets && props.setSelectedAssets(props.missingAssets)\n } else {\n props.setSelectedAssets([])\n }\n }}\n checked={props.selectedAssets.length === props.missingAssets.length}\n />\n <Box flex={1} paddingLeft={3} as=\"label\" htmlFor=\"import-all\">\n <Text>Import all</Text>\n </Box>\n </Flex>\n )}\n {props.missingAssets.map((asset) => (\n <MissingAsset\n key={asset.id}\n asset={asset}\n selectAsset={(selected) => {\n if (selected) {\n props.setSelectedAssets([...props.selectedAssets, asset])\n } else {\n props.setSelectedAssets(props.selectedAssets.filter((a) => a.id !== asset.id))\n }\n }}\n selected={props.selectedAssets.some((a) => a.id === asset.id)}\n />\n ))}\n </Stack>\n )}\n </Box>\n </Dialog>\n )\n}\n\nexport default function ImportVideosFromMux() {\n const importAssets = useImportMuxAssets()\n\n if (!importAssets.hasSecrets) {\n return\n }\n\n if (importAssets.dialogOpen) {\n return <ImportVideosDialog {...importAssets} />\n }\n\n return <Button mode=\"bleed\" text=\"Import from Mux\" onClick={importAssets.openDialog} />\n}\n","import {ChevronLeftIcon} from '@sanity/icons/ChevronLeft'\nimport {ChevronRightIcon} from '@sanity/icons/ChevronRight'\nimport {Button, Label} from '@sanity/ui'\nimport {type Dispatch, type SetStateAction, useEffect} from 'react'\n\nconst PageSelector = (props: {\n page: number\n setPage: Dispatch<SetStateAction<number>>\n total: number\n}) => {\n const page = props.page\n const setPage = props.setPage\n\n useEffect(() => {\n // Constraint in bounds.\n const clamped = Math.min(props.total - 1, Math.max(0, page))\n if (page !== clamped) {\n setPage(clamped)\n }\n }, [page, props.total, setPage])\n\n return (\n <>\n <Button\n icon={ChevronLeftIcon}\n mode=\"bleed\"\n padding={3}\n style={{cursor: 'pointer'}}\n disabled={page <= 0}\n onClick={() => {\n setPage((p) => {\n return Math.min(props.total - 1, Math.max(0, p - 1))\n })\n }}\n />\n <Label muted>\n Page {page + 1}/{props.total}\n </Label>\n <Button\n icon={ChevronRightIcon}\n mode=\"bleed\"\n padding={3}\n style={{cursor: 'pointer'}}\n disabled={page >= props.total - 1}\n onClick={() => {\n setPage((p) => {\n return Math.min(props.total - 1, Math.max(0, p + 1))\n })\n }}\n />\n </>\n )\n}\n\nexport default PageSelector\n","import type {MuxAsset} from './types'\n\n/**\n * Adds a `_key` to array items in MuxAsset data (Sanity requires `_key` on array\n * items). Keys are derived from each item's stable Mux `id`, so repeated calls\n * are idempotent and don't churn the document — important because the asset is\n * persisted on every poll while it prepares.\n */\nexport function addKeysToMuxData(data: MuxAsset): MuxAsset {\n return {\n ...data,\n tracks: data.tracks?.map((track, index) => ({\n ...track,\n _key: track.id || `track-${index}`,\n })),\n playback_ids: data.playback_ids?.map((playbackId, index) => ({\n ...playbackId,\n _key: playbackId.id || `playback-${index}`,\n })),\n static_renditions: data.static_renditions\n ? {\n ...data.static_renditions,\n files: data.static_renditions.files?.map((file, index) => ({\n ...file,\n _key: file.id || `rendition-${index}`,\n })),\n }\n : undefined,\n }\n}\n","import {useMemo, useState} from 'react'\nimport {createHookFromObservableFactory, type DocumentStore, useDocumentStore} from 'sanity'\n\nimport {addKeysToMuxData} from '../util/addKeysToMuxData'\nimport {isEmptyOrPlaceholderTitle} from '../util/assetTitlePlaceholder'\nimport type {VideoAssetDocument} from '../util/types'\nimport {SANITY_API_VERSION, useClient} from './useClient'\nimport useMuxAssets from './useMuxAssets'\nimport {useSecretsDocumentValues} from './useSecretsDocumentValues'\n\ntype ResyncState = 'closed' | 'idle' | 'syncing' | 'done' | 'error'\n\nexport default function useResyncMuxMetadata() {\n const documentStore = useDocumentStore()\n const client = useClient()\n\n const [sanityAssets, sanityAssetsLoading] = useSanityAssets(documentStore)\n\n const secretDocumentValues = useSecretsDocumentValues()\n const hasSecrets = !!secretDocumentValues.value.secrets?.secretKey\n\n const [resyncError, setResyncError] = useState<unknown>()\n const [resyncState, setResyncState] = useState<ResyncState>('closed')\n const dialogOpen = resyncState !== 'closed'\n\n const muxAssets = useMuxAssets({\n client,\n enabled: hasSecrets && dialogOpen,\n })\n\n const matchedAssets = useMemo(() => {\n return sanityAssets && muxAssets.data\n ? sanityAssets.map((sanityDoc) => {\n const muxAsset = muxAssets.data?.find(\n (m) => m.id === sanityDoc.assetId || m.id === sanityDoc.data?.id,\n )\n return {\n sanityDoc,\n muxAsset,\n muxTitle: muxAsset?.meta?.title,\n currentTitle: sanityDoc.filename,\n }\n })\n : undefined\n }, [sanityAssets, muxAssets.data])\n\n const closeDialog = () => {\n if (resyncState !== 'syncing') setResyncState('closed')\n }\n\n const openDialog = () => {\n if (resyncState === 'closed') setResyncState('idle')\n }\n\n async function syncAllVideos() {\n if (!matchedAssets) return\n\n setResyncState('syncing')\n\n try {\n const tx = client.transaction()\n\n matchedAssets.forEach((matched) => {\n // Update all videos with the Mux title, even if it's undefined/empty\n const newTitle = matched.muxTitle || ''\n tx.patch(matched.sanityDoc._id, {set: {filename: newTitle}})\n })\n\n await tx.commit({returnDocuments: false})\n setResyncState('done')\n } catch (error) {\n setResyncState('error')\n setResyncError(error)\n }\n }\n\n async function syncOnlyEmpty() {\n if (!matchedAssets) return\n\n setResyncState('syncing')\n\n try {\n const tx = client.transaction()\n\n matchedAssets.forEach((matched) => {\n // Only update if the current title is empty or has the placeholder format\n // AND there's a new title available from Mux\n if (\n matched.muxAsset &&\n matched.muxTitle &&\n isEmptyOrPlaceholderTitle(matched.currentTitle, matched.muxAsset.id)\n ) {\n tx.patch(matched.sanityDoc._id, {set: {filename: matched.muxTitle}})\n }\n })\n\n await tx.commit({returnDocuments: false})\n setResyncState('done')\n } catch (error) {\n setResyncState('error')\n setResyncError(error)\n }\n }\n\n async function syncFullData() {\n if (!matchedAssets) return\n\n setResyncState('syncing')\n\n try {\n const tx = client.transaction()\n\n matchedAssets.forEach((matched) => {\n if (!matched.muxAsset) return\n\n const dataWithKeys = addKeysToMuxData(matched.muxAsset)\n\n // Update all fields: filename, status, and full data from Mux\n tx.patch(matched.sanityDoc._id, {\n set: {\n filename: matched.muxTitle || matched.currentTitle || '',\n status: matched.muxAsset.status,\n data: dataWithKeys,\n },\n })\n })\n\n await tx.commit({returnDocuments: false})\n setResyncState('done')\n } catch (error) {\n setResyncState('error')\n setResyncError(error)\n }\n }\n\n return {\n sanityAssetsLoading,\n closeDialog,\n dialogOpen,\n resyncState,\n resyncError,\n hasSecrets,\n syncAllVideos,\n syncOnlyEmpty,\n syncFullData,\n matchedAssets,\n muxAssets,\n openDialog,\n }\n}\n\nconst useSanityAssets = createHookFromObservableFactory<VideoAssetDocument[], DocumentStore>(\n (documentStore) => {\n return documentStore.listenQuery(\n /* groq */ `*[_type == \"mux.videoAsset\"]`,\n {},\n {\n apiVersion: SANITY_API_VERSION,\n },\n )\n },\n)\n","import {CheckmarkCircleIcon} from '@sanity/icons/CheckmarkCircle'\nimport {ErrorOutlineIcon} from '@sanity/icons/ErrorOutline'\nimport {SyncIcon} from '@sanity/icons/Sync'\nimport {Box, Button, Card, Dialog, Flex, Heading, Radio, Spinner, Stack, Text} from '@sanity/ui'\nimport {useState} from 'react'\n\nimport useResyncMuxMetadata from '../hooks/useResyncMuxMetadata'\nimport {isEmptyOrPlaceholderTitle} from '../util/assetTitlePlaceholder'\nimport {DIALOGS_Z_INDEX} from '../util/constants'\n\ntype SyncOption = 'fillEmpty' | 'syncTitles' | 'fullResync'\n\ninterface OptionCardProps {\n id: SyncOption\n selected: boolean\n onSelect: (id: SyncOption) => void\n title: string\n count: number\n description: string\n disabled?: boolean\n}\n\nfunction OptionCard({\n id,\n selected,\n onSelect,\n title,\n count,\n description,\n disabled,\n}: OptionCardProps) {\n return (\n <Card\n as=\"label\"\n padding={3}\n radius={2}\n border\n tone={selected ? 'primary' : 'default'}\n style={{\n cursor: disabled ? 'not-allowed' : 'pointer',\n opacity: disabled ? 0.5 : 1,\n }}\n >\n <Flex gap={3} align=\"flex-start\">\n <Box paddingTop={1}>\n <Radio\n checked={selected}\n onChange={() => onSelect(id)}\n disabled={disabled}\n name=\"sync-option\"\n />\n </Box>\n <Stack gap={2} flex={1}>\n <Flex align=\"center\" gap={2}>\n <Text size={2} weight=\"semibold\">\n {title} ({count})\n </Text>\n </Flex>\n <Text size={1} muted>\n {description}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )\n}\n\nfunction ResyncMetadataDialog(props: ReturnType<typeof useResyncMuxMetadata>) {\n const {resyncState} = props\n\n const videosToUpdate = props.matchedAssets?.filter((m) => m.muxAsset).length || 0\n const videosWithEmptyOrPlaceholder =\n props.matchedAssets?.filter(\n (m) => m.muxAsset && m.muxTitle && isEmptyOrPlaceholderTitle(m.currentTitle, m.muxAsset.id),\n ).length || 0\n\n const hasEmptyTitles = videosWithEmptyOrPlaceholder > 0\n const defaultOption: SyncOption = hasEmptyTitles ? 'fillEmpty' : 'syncTitles'\n const [selectedOption, setSelectedOption] = useState<SyncOption>(defaultOption)\n\n const canTriggerResync = resyncState === 'idle' || resyncState === 'error'\n const isResyncing = resyncState === 'syncing'\n const isDone = resyncState === 'done'\n const isLoading = props.muxAssets.loading || props.sanityAssetsLoading\n\n const handleSync = () => {\n switch (selectedOption) {\n case 'fillEmpty':\n void props.syncOnlyEmpty()\n break\n case 'syncTitles':\n void props.syncAllVideos()\n break\n case 'fullResync':\n void props.syncFullData()\n break\n default:\n break\n }\n }\n\n return (\n <Dialog\n animate\n header=\"Sync with Mux\"\n zOffset={DIALOGS_Z_INDEX}\n id=\"resync-metadata-dialog\"\n onClose={props.closeDialog}\n onClickOutside={props.closeDialog}\n width={1}\n position=\"fixed\"\n footer={\n !isDone && (\n <Card padding={3}>\n <Flex justify=\"flex-end\" gap={2}>\n <Button\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Cancel\"\n onClick={props.closeDialog}\n disabled={isResyncing}\n />\n <Button\n icon={SyncIcon}\n fontSize={2}\n padding={3}\n text=\"Run sync\"\n tone=\"primary\"\n onClick={handleSync}\n iconRight={isResyncing && Spinner}\n disabled={!canTriggerResync || isLoading}\n />\n </Flex>\n </Card>\n )\n }\n >\n <Box padding={4}>\n {/* LOADING ASSETS STATE */}\n {isLoading && (\n <Card tone=\"primary\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Loading assets from Mux\n </Text>\n <Text size={1} muted>\n This may take a while.\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR LOADING MUX */}\n {props.muxAssets.error && (\n <Card tone=\"critical\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error getting data from Mux\n </Text>\n <Text size={1}>Please try again or contact a developer for help.</Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* SYNCING STATE */}\n {resyncState === 'syncing' && (\n <Card tone=\"primary\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Syncing metadata\n </Text>\n <Text size={1} muted>\n Updating videos from Mux...\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR SYNCING */}\n {resyncState === 'error' && (\n <Card tone=\"critical\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error syncing metadata\n </Text>\n <Text size={1}>\n {props.resyncError\n ? `Error: ${props.resyncError}`\n : 'Please try again or contact a developer for help.'}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* SUCCESS STATE */}\n {resyncState === 'done' && (\n <Stack paddingY={5} gap={3} style={{textAlign: 'center'}}>\n <Box>\n <CheckmarkCircleIcon fontSize={48} />\n </Box>\n <Heading size={2}>Sync completed</Heading>\n <Text size={2} muted>\n Videos have been updated from Mux.\n </Text>\n </Stack>\n )}\n\n {/* OPTIONS */}\n {!isDone && !isLoading && !props.muxAssets.error && (\n <Stack gap={4}>\n <Text size={1} muted>\n Found {videosToUpdate} video{videosToUpdate === 1 ? '' : 's'} linked to Mux.\n </Text>\n\n <Stack gap={3}>\n {hasEmptyTitles && (\n <OptionCard\n id=\"fillEmpty\"\n selected={selectedOption === 'fillEmpty'}\n onSelect={setSelectedOption}\n title=\"Fill missing titles only\"\n count={videosWithEmptyOrPlaceholder}\n description=\"Updates only videos without a title or with placeholder titles (e.g., 'Asset #123') using the title from Mux.\"\n disabled={isResyncing}\n />\n )}\n\n <OptionCard\n id=\"syncTitles\"\n selected={selectedOption === 'syncTitles'}\n onSelect={setSelectedOption}\n title=\"Sync all titles\"\n count={videosToUpdate}\n description=\"Replaces the title in Sanity with the title from Mux for all videos.\"\n disabled={isResyncing}\n />\n\n <OptionCard\n id=\"fullResync\"\n selected={selectedOption === 'fullResync'}\n onSelect={setSelectedOption}\n title=\"Full resync\"\n count={videosToUpdate}\n description=\"Updates all fields from Mux including status, duration, tracks, captions, and renditions.\"\n disabled={isResyncing}\n />\n </Stack>\n </Stack>\n )}\n </Box>\n </Dialog>\n )\n}\n\nexport default function ResyncMetadata() {\n const resyncMetadata = useResyncMuxMetadata()\n\n if (!resyncMetadata.hasSecrets) {\n return\n }\n\n if (resyncMetadata.dialogOpen) {\n return <ResyncMetadataDialog {...resyncMetadata} />\n }\n\n return <Button mode=\"bleed\" text=\"Sync with Mux\" onClick={resyncMetadata.openDialog} />\n}\n","import {SortIcon} from '@sanity/icons/Sort'\nimport {Button} from '@sanity/ui'\nimport {Menu, MenuButton, MenuItem} from '@sanity/ui/menu'\nimport {type PopoverProps} from '@sanity/ui/popover'\nimport {useId} from 'react'\n\nimport {ASSET_SORT_OPTIONS, type SortOption} from '../hooks/useAssets'\n\nconst CONTEXT_MENU_POPOVER_PROPS: PopoverProps = {\n constrainSize: true,\n placement: 'bottom',\n portal: true,\n width: 0,\n}\n\n/**\n * @sanity/ui components adapted from:\n * https://github.com/sanity-io/sanity/blob/next/packages/sanity/src/desk/components/pane/PaneContextMenuButton.tsx#L19\n */\nexport function SelectSortOptions(props: {sort: SortOption; setSort: (s: SortOption) => void}) {\n const id = useId()\n\n return (\n <MenuButton\n button={\n <Button text=\"Sort\" icon={SortIcon} mode=\"bleed\" padding={3} style={{cursor: 'pointer'}} />\n }\n id={id}\n menu={\n <Menu>\n {Object.entries(ASSET_SORT_OPTIONS).map(([type, {label}]) => (\n <MenuItem\n key={type}\n data-as=\"button\"\n onClick={() => props.setSort(type as SortOption)}\n padding={3}\n tone=\"default\"\n text={label}\n pressed={type === props.sort}\n />\n ))}\n </Menu>\n }\n popover={CONTEXT_MENU_POPOVER_PROPS}\n />\n )\n}\n","import {Box, Spinner} from '@sanity/ui'\n\nconst SpinnerBox: React.FC = () => (\n <Box\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: '150px',\n }}\n >\n <Spinner />\n </Box>\n)\n\nexport default SpinnerBox\n","import {Flex, Text} from '@sanity/ui'\n\nconst IconInfo: React.FC<{\n text: string\n icon: React.FC\n size?: number\n muted?: boolean\n}> = (props) => {\n const Icon = props.icon\n return (\n <Flex gap={2} align=\"center\" padding={1}>\n <Text size={(props.size || 1) + 1} muted>\n <Icon />\n </Text>\n <Text size={props.size || 1} muted={props.muted}>\n {props.text}\n </Text>\n </Flex>\n )\n}\n\nexport default IconInfo\n","import type {SVGProps} from 'react'\n\nexport function ResolutionIcon(props: SVGProps<SVGSVGElement>) {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\" {...props}>\n <path\n fill=\"currentColor\"\n d=\"M20 9V6h-3V4h5v5h-2ZM2 9V4h5v2H4v3H2Zm15 11v-2h3v-3h2v5h-5ZM2 20v-5h2v3h3v2H2Zm4-4V8h12v8H6Zm2-2h8v-4H8v4Zm0 0v-4v4Z\"\n />\n </svg>\n )\n}\n","import type {SVGProps} from 'react'\n\nexport function StopWatchIcon(props: SVGProps<SVGSVGElement>) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 512 512\"\n {...props}\n >\n <path d=\"M232 306.667h48V176h-48v130.667z\" fill=\"currentColor\" />\n <path\n d=\"M407.67 170.271l30.786-30.786-33.942-33.941-30.785 30.786C341.217 111.057 300.369 96 256 96 149.961 96 64 181.961 64 288s85.961 192 192 192 192-85.961 192-192c0-44.369-15.057-85.217-40.33-117.729zm-45.604 223.795C333.734 422.398 296.066 438 256 438s-77.735-15.602-106.066-43.934C121.602 365.735 106 328.066 106 288s15.602-77.735 43.934-106.066C178.265 153.602 215.934 138 256 138s77.734 15.602 106.066 43.934C390.398 210.265 406 247.934 406 288s-15.602 77.735-43.934 106.066z\"\n fill=\"currentColor\"\n />\n <path d=\"M192 32h128v48H192z\" fill=\"currentColor\" />\n </svg>\n )\n}\n","import {useToast} from '@sanity/ui/toast'\nimport {useCallback, useEffect, useMemo, useState} from 'react'\n\nimport {getAsset, updateMasterAccess} from '../actions/assets'\nimport {addKeysToMuxData} from '../util/addKeysToMuxData'\nimport type {MuxAsset, VideoAssetDocument} from '../util/types'\nimport {useClient} from './useClient'\n\n/**\n * UI status for the mezzanine (\"master access\") file of a Mux asset, derived\n * solely from the stored `master` object.\n * - `disabled`: master access is not enabled (or reverted to `none`).\n * - `preparing`: Mux is preparing the file (we poll until it's ready).\n * - `ready`: the file is ready to download.\n * - `errored`: Mux failed to prepare the file.\n */\nexport type MezzanineStatus = 'disabled' | 'preparing' | 'ready' | 'errored'\n\n// Poll cadence while the mezzanine is preparing.\nconst POLL_INTERVAL_MS = 3000\n\nexport interface UseMezzanineReturn {\n status: MezzanineStatus\n /** `true` while an enable or pre-download check request is in flight. */\n busy: boolean\n /**\n * `true` when the last download attempt found the file gone (the 24h window\n * elapsed). Used to show a \"enable it again\" hint; the button state still\n * comes from `status`.\n */\n expired: boolean\n /** Mezzanine resolution label (e.g. `1080p`), when known. */\n resolution?: string\n /** Enables master access and starts polling until the file is ready. */\n enable: () => Promise<void>\n /** Re-fetches the asset and, if the file is still alive, triggers the download. */\n download: () => Promise<void>\n}\n\n/** Derives the mezzanine status from the persisted asset data alone (no polling or local state). */\nexport function getMezzanineStatus(\n asset: VideoAssetDocument,\n): 'disabled' | 'preparing' | 'ready' | 'errored' {\n const master = asset.data?.master\n if (master?.status === 'preparing') return 'preparing'\n if (master?.status === 'ready' && master.url) return 'ready'\n if (master?.status === 'errored') return 'errored'\n return 'disabled'\n}\n\n/**\n * Encapsulates the mezzanine (Mux \"master access\") lifecycle for an asset:\n * enabling it through the Mux addon proxy, persisting the result on the Sanity\n * document, polling until it's ready, and downloading by redirecting to the\n * fresh, short-lived Mux URL.\n *\n * The full Mux asset `data` (including the `master` object) is stored on the\n * Sanity document via `client.patch`, so the status survives reloads and is\n * already present for assets imported from Mux.\n */\nexport function useMezzanine(asset: VideoAssetDocument): UseMezzanineReturn {\n const client = useClient()\n const toast = useToast()\n\n const master = asset.data?.master\n const [busy, setBusy] = useState(false)\n const [expired, setExpired] = useState(false)\n // Track the previous assetId so we can reset transient flags during render\n // when the asset changes, without triggering a cascading setState-in-effect.\n const [prevAssetId, setPrevAssetId] = useState(asset.assetId)\n if (prevAssetId !== asset.assetId) {\n setPrevAssetId(asset.assetId)\n setExpired(false)\n }\n\n const resolution = useMemo(\n () => asset.data?.max_resolution_tier || asset.data?.max_stored_resolution || undefined,\n [asset.data?.max_resolution_tier, asset.data?.max_stored_resolution],\n )\n\n const status: MezzanineStatus = getMezzanineStatus(asset)\n\n // Persist a Mux asset payload on the Sanity document.\n const persist = useCallback(\n async (data: MuxAsset) => {\n if (!asset._id) return\n await client\n .patch(asset._id)\n .set({status: data.status, data: addKeysToMuxData(data)})\n .commit({returnDocuments: false})\n },\n [asset._id, client],\n )\n\n // Fetch the latest asset from Mux (through the proxy) and persist it on the Sanity document.\n const refresh = useCallback(async (): Promise<MuxAsset | undefined> => {\n if (!asset.assetId || !asset._id) return undefined\n const {data} = await getAsset(client, asset.assetId)\n await persist(data)\n return data\n }, [asset.assetId, asset._id, client, persist])\n\n // Poll while the mezzanine is preparing; stop once it's ready or no longer preparing.\n useEffect(() => {\n if (master?.status !== 'preparing' || !asset.assetId || !asset._id) return undefined\n\n let cancelled = false\n let running = false\n const interval = setInterval(async () => {\n // Skip this tick if the previous refresh hasn't finished, so a slow\n // request can't pile up overlapping reads/writes.\n if (running) return\n running = true\n try {\n const data = await refresh()\n if (cancelled) return\n if (!data || data.master?.status !== 'preparing') {\n clearInterval(interval)\n }\n } catch (error) {\n console.error('Failed to poll mezzanine status:', error)\n // oxlint-disable-next-line react/todo\n } finally {\n running = false\n }\n }, POLL_INTERVAL_MS)\n\n return () => {\n cancelled = true\n clearInterval(interval)\n }\n }, [master?.status, asset.assetId, asset._id, refresh])\n\n const enable = useCallback(async () => {\n if (!asset.assetId || !asset._id) return\n\n setBusy(true)\n setExpired(false)\n try {\n const {data} = await updateMasterAccess(client, asset.assetId, 'temporary')\n // Persist the PUT response directly — it already reports master.status\n // 'preparing', so polling starts without relying on a follow-up GET that\n // could read stale data and miss it.\n await persist(data)\n } catch (error) {\n toast.push({\n status: 'error',\n title: 'Could not enable the mezzanine file',\n description: error instanceof Error ? error.message : 'Please try again',\n })\n // oxlint-disable-next-line react/todo\n } finally {\n setBusy(false)\n }\n }, [asset.assetId, asset._id, client, persist, toast])\n\n const download = useCallback(async () => {\n if (!asset.assetId) return\n\n setBusy(true)\n try {\n // The Mux URL is short-lived (24h), so re-fetch the asset right before\n // downloading and only redirect if the file is still alive.\n const data = await refresh()\n const url = data?.master?.status === 'ready' ? data.master.url : undefined\n\n if (url) {\n setExpired(false)\n triggerMezzanineDownload(url)\n } else {\n // The window elapsed and master_access reverted: prompt to re-enable.\n setExpired(true)\n }\n } catch (error) {\n toast.push({\n status: 'error',\n title: 'Could not download the mezzanine file',\n description: error instanceof Error ? error.message : 'Please try again',\n })\n // oxlint-disable-next-line react/todo\n } finally {\n setBusy(false)\n }\n }, [asset.assetId, refresh, toast])\n\n return {status, busy, expired, resolution, enable, download}\n}\n\n/**\n * Redirects the browser to the Mux mezzanine URL to start the download. The URL\n * already serves the file with its default name (`mezzanine.mp4`).\n * @see {@link https://www.mux.com/docs/guides/download-for-offline-editing}\n */\nfunction triggerMezzanineDownload(masterUrl: string): void {\n if (typeof window === 'undefined') return\n\n const anchor = document.createElement('a')\n anchor.href = masterUrl\n anchor.target = '_blank'\n anchor.rel = 'noopener noreferrer'\n document.body.appendChild(anchor)\n anchor.click()\n document.body.removeChild(anchor)\n}\n","import {Stack, Text} from '@sanity/ui'\n\n/** Explains what the mezzanine file is and how it differs from the streamable MP4 renditions. */\nexport default function MezzanineExplanation() {\n return (\n <Stack gap={3}>\n <Text size={1} muted>\n When you enable the mezzanine file, Mux creates a copy equivalent in quality to your\n original video — ideal for offline editing or archiving. Unlike the streamable MP4 (static)\n renditions, it is not meant for streaming.\n </Text>\n <Text size={1} muted>\n The file is prepared in the background and may take a few minutes depending on the\n asset's duration and resolution. Enabling is free and the download stays available for\n 24 hours.\n </Text>\n </Stack>\n )\n}\n","import {DownloadIcon} from '@sanity/icons/Download'\nimport {Button, Card, Flex, Label, Spinner, Stack, Text} from '@sanity/ui'\n\nimport {useMezzanine} from '../hooks/useMezzanine'\nimport {MEZZANINE_LEARN_MORE_URL} from '../util/constants'\nimport type {VideoAssetDocument} from '../util/types'\nimport MezzanineExplanation from './MezzanineExplanation'\n\nexport interface Props {\n asset: VideoAssetDocument\n /**\n * Render the mezzanine explanation copy inside the card.\n * @defaultValue true\n */\n withExplanation?: boolean\n}\n\n/**\n * \"Mezzanine\" panel, modeled after Mux's dashboard card: enable the\n * master-access copy, watch it prepare, then download it.\n */\nexport default function Mezzanine({asset, withExplanation = true}: Props) {\n const {status, busy, expired, resolution, enable, download} = useMezzanine(asset)\n\n const assetReady = asset.status === 'ready' || asset.data?.status === 'ready'\n // Once a download finds the file gone, treat it as not-ready even if the\n // (stale) asset prop still reports `ready`, so we show the re-enable path\n // instead of a dead Download button.\n const isReady = status === 'ready' && !expired\n const isPreparing = status === 'preparing'\n const showExplanation = !isReady && !isPreparing\n\n return (\n <Card padding={3} radius={2} tone=\"transparent\" border>\n <Stack gap={4}>\n <Flex align=\"center\" justify=\"space-between\" gap={3}>\n <Label muted size={1}>\n Mezzanine\n </Label>\n <Text size={1}>\n <a href={MEZZANINE_LEARN_MORE_URL} target=\"_blank\" rel=\"noopener noreferrer\">\n Learn more\n </a>\n </Text>\n </Flex>\n\n <Stack gap={2}>\n <Text size={1} muted={!isReady}>\n mezzanine.mp4\n </Text>\n {resolution && (\n <Text size={1} muted>\n {resolution}\n </Text>\n )}\n </Stack>\n\n {withExplanation && showExplanation && <MezzanineExplanation />}\n\n {showExplanation && (expired || status === 'errored') && (\n <Stack gap={2}>\n {expired && (\n <Text size={1} muted>\n The previous mezzanine file expired. Enable it again to download.\n </Text>\n )}\n {status === 'errored' && (\n <Text size={1} style={{color: 'var(--card-critical-color)'}}>\n Mux could not prepare the mezzanine file. Please try again.\n </Text>\n )}\n </Stack>\n )}\n\n {isPreparing && (\n <Text size={1} muted>\n Preparing the mezzanine file… this can take a few minutes. You can close this and come\n back later.\n </Text>\n )}\n\n {isReady && (\n <Text size={1} muted>\n Ready to download. The link stays available for about 24 hours.\n </Text>\n )}\n\n <Flex justify=\"flex-end\" gap={2}>\n {isPreparing ? (\n <Flex align=\"center\" gap={2}>\n <Spinner muted size={1} />\n <Text size={1} muted>\n Preparing…\n </Text>\n </Flex>\n ) : isReady ? (\n <Button\n icon={DownloadIcon}\n text=\"Download\"\n tone=\"positive\"\n fontSize={1}\n padding={3}\n loading={busy}\n disabled={busy}\n onClick={() => void download()}\n />\n ) : (\n <Button\n text={status === 'errored' ? 'Try again' : 'Enable'}\n tone=\"primary\"\n fontSize={1}\n padding={3}\n loading={busy}\n disabled={busy || !assetReady}\n onClick={() => void enable()}\n />\n )}\n </Flex>\n </Stack>\n </Card>\n )\n}\n","import {useToast} from '@sanity/ui/toast'\nimport {useCallback, useState} from 'react'\n\nimport {getAsset} from '../actions/assets'\nimport {addKeysToMuxData} from '../util/addKeysToMuxData'\nimport type {MuxAsset, VideoAssetDocument} from '../util/types'\nimport {useClient} from './useClient'\n\ntype ResyncAssetState = 'idle' | 'syncing' | 'success' | 'error'\n\ninterface UseResyncAssetOptions {\n showToast?: boolean\n onSuccess?: (updatedData: MuxAsset) => void\n onError?: (error: unknown) => void\n}\n\ninterface UseResyncAssetReturn {\n resyncState: ResyncAssetState\n resyncError: unknown\n resyncAsset: (asset: VideoAssetDocument) => Promise<MuxAsset | undefined>\n isResyncing: boolean\n}\n\nexport function useResyncAsset(options?: UseResyncAssetOptions): UseResyncAssetReturn {\n const client = useClient()\n const toast = useToast()\n const [resyncState, setResyncState] = useState<ResyncAssetState>('idle')\n const [resyncError, setResyncError] = useState<unknown>(null)\n\n const showToast = options?.showToast ?? false\n\n const resyncAsset = useCallback(\n async (asset: VideoAssetDocument) => {\n if (!asset.assetId) {\n if (showToast) {\n toast.push({\n title: 'Cannot resync',\n description: 'Asset has no Mux ID',\n status: 'error',\n })\n }\n options?.onError?.(new Error('Asset has no Mux ID'))\n return undefined\n }\n\n if (!asset._id) {\n if (showToast) {\n toast.push({\n title: 'Cannot resync',\n description: 'Asset has no document ID',\n status: 'error',\n })\n }\n options?.onError?.(new Error('Asset has no document ID'))\n return undefined\n }\n\n setResyncState('syncing')\n setResyncError(null)\n\n try {\n const response = await getAsset(client, asset.assetId)\n const muxData = response.data\n const dataWithKeys = addKeysToMuxData(muxData)\n\n await client\n .patch(asset._id)\n .set({\n status: muxData.status,\n data: dataWithKeys,\n ...(muxData.meta?.title && {filename: muxData.meta.title}),\n })\n .commit({returnDocuments: false})\n\n setResyncState('success')\n if (showToast) {\n toast.push({\n title: 'Asset synced',\n description: 'Data has been updated from Mux',\n status: 'success',\n })\n }\n\n options?.onSuccess?.(muxData)\n return muxData\n } catch (error) {\n setResyncState('error')\n setResyncError(error)\n console.error('Failed to refresh asset data:', error)\n if (showToast) {\n toast.push({\n title: 'Sync failed',\n description: 'Could not sync asset from Mux',\n status: 'error',\n })\n }\n options?.onError?.(error)\n return undefined\n }\n },\n [client, toast, options, showToast],\n )\n\n return {\n resyncState,\n resyncError,\n resyncAsset,\n isResyncing: resyncState === 'syncing',\n }\n}\n","import type {SanityClient} from '@sanity/client'\n\nimport {getAsset} from '../actions/assets'\nimport {generateJwt} from './generateJwt'\nimport {getPlaybackId} from './getPlaybackPolicy'\nimport {getPlaybackPolicy} from './getPlaybackPolicy'\nimport type {MuxTextTrack, VideoAssetDocument} from './types'\n\nexport function extractErrorMessage(\n error: unknown,\n defaultMessage = 'Failed to process request',\n): string {\n let message = ''\n\n if (error && typeof error === 'object') {\n const err = error as {response?: {body?: {message?: string}}; message?: string}\n message = err.response?.body?.message || err.message || ''\n } else if (typeof error === 'string') {\n message = error\n }\n\n if (!message) {\n return defaultMessage\n }\n\n const match = message.match(/\\(([^)]+)\\)/)\n if (match && match[1]) {\n return match[1]\n }\n\n if (message.includes('responded with')) {\n const parts = message.split('(')\n if (parts.length > 1) {\n return parts[parts.length - 1]!.replace(')', '').trim()\n }\n }\n\n return message\n}\n\nexport interface PollTrackStatusOptions {\n client: SanityClient\n assetId: string\n trackName: string\n trackLanguageCode: string\n maxAttempts?: number\n onTrackFound?: (track: MuxTextTrack) => void\n onTrackErrored?: (track: MuxTextTrack) => void\n onTrackReady?: (track: MuxTextTrack) => void\n}\n\nexport interface PollTrackStatusResult {\n track: MuxTextTrack | undefined\n found: boolean\n status: 'ready' | 'preparing' | 'errored' | 'not-found'\n}\n\n/**\n * Polls Mux API to find and track the status of a newly added text track.\n * The track may be in \"preparing\" state initially, then become \"ready\" or \"errored\".\n *\n * @param options - Configuration options for polling\n * @returns Promise resolving to the poll result\n */\nexport async function pollTrackStatus(\n options: PollTrackStatusOptions,\n): Promise<PollTrackStatusResult> {\n const {\n client,\n assetId,\n trackName,\n trackLanguageCode,\n maxAttempts = 10,\n onTrackFound,\n onTrackErrored,\n onTrackReady,\n } = options\n\n const trimmedName = trackName.trim()\n const trimmedLanguageCode = trackLanguageCode.trim()\n let newTrack: MuxTextTrack | undefined\n let attempts = 0\n let trackFound = false\n\n const findTrack = (textTracks: MuxTextTrack[]): MuxTextTrack | undefined => {\n let foundTrack = textTracks.find(\n (track) => track.name === trimmedName && track.language_code === trimmedLanguageCode,\n )\n\n if (!foundTrack) {\n foundTrack = textTracks.find((track) => track.language_code === trimmedLanguageCode)\n }\n\n if (!foundTrack && textTracks.length > 0) {\n foundTrack = textTracks[textTracks.length - 1]\n }\n\n return foundTrack\n }\n\n while (attempts < maxAttempts) {\n try {\n if (attempts > 0) {\n await new Promise((resolve) => setTimeout(resolve, 1000))\n }\n\n const assetData = await getAsset(client, assetId)\n const textTracks =\n assetData.data.tracks?.filter((track): track is MuxTextTrack => track.type === 'text') || []\n\n const foundTrack = findTrack(textTracks)\n\n if (!foundTrack) {\n attempts++\n continue\n }\n\n trackFound = true\n newTrack = foundTrack\n\n if (onTrackFound) {\n onTrackFound(foundTrack)\n }\n\n if (foundTrack.status === 'ready') {\n if (onTrackReady) {\n onTrackReady(foundTrack)\n }\n break\n }\n\n if (foundTrack.status === 'errored') {\n if (onTrackErrored) {\n onTrackErrored(foundTrack)\n }\n return {\n track: foundTrack,\n found: true,\n status: 'errored',\n }\n }\n } catch (error) {\n console.error('Failed to fetch updated asset:', error)\n }\n\n attempts++\n }\n\n if (!newTrack || !trackFound) {\n return {\n track: undefined,\n found: false,\n status: 'not-found',\n }\n }\n\n if (newTrack.status === 'preparing') {\n return {\n track: newTrack,\n found: true,\n status: 'preparing',\n }\n }\n\n return {\n track: newTrack,\n found: true,\n status: 'ready',\n }\n}\n\n/**\n * May throw a Promise. Call this with {@link tryWithSuspend} or rethrow the Promise\n */\nexport async function downloadVttFile(\n client: SanityClient,\n asset: VideoAssetDocument,\n track: MuxTextTrack,\n): Promise<void> {\n if (!track.id) {\n throw new Error('Track ID is missing')\n }\n\n if (track.status !== 'ready') {\n throw new Error(`Track is not ready yet. Status: ${track.status}`)\n }\n\n if (!asset.assetId) {\n throw new Error('Asset ID is required')\n }\n\n const playbackId = getPlaybackId(asset)\n if (!playbackId) {\n throw new Error('Playback ID is required')\n }\n\n const playbackPolicy = getPlaybackPolicy(asset)?.policy\n\n let downloadUrl = `https://stream.mux.com/${playbackId}/text/${track.id}.vtt`\n\n if (playbackPolicy === 'signed' || playbackPolicy === 'drm') {\n const token = generateJwt(client, playbackId, 'v')\n downloadUrl += `?token=${token}`\n }\n\n const response = await fetch(downloadUrl)\n if (!response.ok) {\n throw new Error(`Failed to download file: ${response.statusText}`)\n }\n\n const blob = await response.blob()\n const blobUrl = URL.createObjectURL(blob)\n\n const link = document.createElement('a')\n link.href = blobUrl\n link.download = `${asset.filename || 'captions'}-${track.language_code || 'en'}.vtt`\n document.body.appendChild(link)\n link.click()\n document.body.removeChild(link)\n\n URL.revokeObjectURL(blobUrl)\n}\n","import type MuxPlayerElement from '@mux/mux-player'\nimport type {ObjectInputProps} from 'sanity'\nimport type {PartialDeep} from 'type-fest'\n\n/**\n * All static rendition resolution options supported by Mux\n */\nexport type StaticRenditionResolution =\n | 'highest'\n | 'audio-only'\n | '270p'\n | '360p'\n | '480p'\n | '540p'\n | '720p'\n | '1080p'\n | '1440p'\n | '2160p'\n\nexport interface MuxInputConfig {\n /**\n * Enable static renditions by default. Can be overwritten on a per-asset basis.\n * Supports:\n * - Standard mode: 'highest' (up to 4K MP4) and/or 'audio-only' (M4A)\n * - Advanced mode: Specific resolutions ('270p', '360p', '480p', '540p', '720p', '1080p', '1440p', '2160p') and/or 'audio-only'\n *\n * **Important**: 'highest' cannot be mixed with specific resolutions. If both are provided, only 'highest' will be used.\n *\n * @see {@link https://docs.mux.com/guides/video/enable-static-mp4-renditions}\n * @defaultValue []\n */\n static_renditions: StaticRenditionResolution[]\n\n /**\n * @deprecated Use `static_renditions` instead. This field is kept for backward compatibility.\n * Enable static renditions by setting this to 'standard'. Can be overwritten on a per-asset basis.\n * Requires `\"video_quality\": \"plus\"`\n * @see {@link https://docs.mux.com/guides/video/enable-static-mp4-renditions#why-enable-mp4-support}\n * @defaultValue 'none'\n */\n mp4_support: 'none' | 'standard'\n\n /**\n * Max resolution tier can be used to control the maximum resolution_tier your asset is encoded, stored, and streamed at.\n * Requires `\"video_quality\": \"plus\"`\n * @see {@link https://docs.mux.com/guides/stream-videos-in-4k}\n * @defaultValue '1080p'\n */\n max_resolution_tier: '2160p' | '1440p' | '1080p'\n\n /**\n * @deprecated Use {@link video_quality}\n * <br>\n * The encoding tier informs the cost, quality, and available platform features for the asset.\n * @see {@link https://docs.mux.com/guides/use-encoding-tiers}\n * @defaultValue 'smart'\n */\n encoding_tier?: 'baseline' | 'smart'\n\n /**\n * The video quality level informs the cost, quality, and available platform features for the asset.\n * @see {@link https://www.mux.com/docs/guides/use-video-quality-levels}\n * @defaultValue 'plus'\n */\n video_quality: 'basic' | 'plus' | 'premium'\n\n /**\n * Normalize the audio track loudness level.\n * @see {@link https://docs.mux.com/guides/adjust-audio-levels#how-to-turn-on-audio-normalization}\n * @defaultValue false\n */\n normalize_audio: boolean\n\n /**\n * Enables signed URLs by default, if you configured them with your API token.\n * @see {@link https://docs.mux.com/guides/secure-video-playback}\n * @defaultValue false\n */\n defaultSigned?: boolean\n\n /**\n * Enables public URLs by default.\n * @defaultValue true\n */\n defaultPublic?: boolean\n\n /**\n * Enables DRM Protection by default, if you configured your DRM Configuration Id.\n * @see {@link https://www.mux.com/docs/guides/protect-videos-with-drm}\n * @defaultValue true\n */\n defaultDrm?: boolean\n\n /**\n * Auto-generate captions for these languages by default.\n * Requires `\"video_quality\": \"plus\"`\n *\n * @see {@link https://docs.mux.com/guides/add-autogenerated-captions-and-use-transcripts}\n * @deprecated use `defaultAutogeneratedSubtitleLang` instead. Only a single autogenerated\n */\n defaultAutogeneratedSubtitleLangs?: SupportedMuxLanguage[]\n\n /**\n * Auto-generate captions for this language by default. Users can still\n * Requires `\"video_quality\": \"plus\"`\n *\n * @see {@link https://docs.mux.com/guides/add-autogenerated-captions-and-use-transcripts}\n */\n defaultAutogeneratedSubtitleLang?: SupportedMuxLanguage\n\n /**\n * Whether or not to allow content editors to override asset upload\n * configuration settings when uploading a video to Mux.\n *\n * @see {@link https://docs.mux.com/guides/secure-video-playback}\n * @defaultValue false\n */\n disableUploadConfig?: boolean\n\n /**\n * Whether or not to allow content editors to add text tracks alongside their\n * asset when uploading a video to Mux.\n *\n * @see {@link https://docs.mux.com/guides/secure-video-playback}\n * @defaultValue false\n */\n disableTextTrackConfig?: boolean\n\n /**\n * Whether or not to show the playback warning when trying to watch DRM content for the first time.\n *\n * @defaultValue false\n */\n disableDrmPlaybackWarning?: boolean\n\n /**\n * The mime types that are accepted by the input.\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/accept}\n * @defaultValue ['video/*','audio/*']\n\n */\n acceptedMimeTypes?: ('audio/*' | 'video/*')[]\n\n /**\n * Maximum file size allowed for video uploads in bytes.\n * If not specified, no file size validation will be performed.\n *\n * @example 1024 * 1024 * 1024 // 1 GB\n * @defaultValue undefined\n */\n maxAssetFileSize?: number\n\n /**\n * Maximum video duration allowed in seconds.\n * If not specified, no duration validation will be performed.\n *\n * @example 2 * 60 * 60 // 2 hours\n * @defaultValue undefined\n */\n maxAssetDuration?: number\n\n /**\n * HLS.js configuration options to be passed to the Mux Player.\n * These options allow you to customize the underlying HLS.js playback engine behavior.\n *\n * @see {@link https://github.com/video-dev/hls.js/blob/master/docs/API.md#fine-tuning}\n * @defaultValue undefined\n * @example\n * ```ts\n * {\n * maxBufferLength: 30,\n * lowLatencyMode: true,\n * capLevelToPlayerSize: true\n * }\n * ```\n */\n hlsConfig?: MuxPlayerElement['_hlsConfig']\n}\n\nexport interface PluginConfig extends MuxInputConfig {\n /**\n * How the videos browser should appear as a studio tool in Sanity's top navigation\n *\n * Pass `false` if you want to disable it.\n * @defaultValue {title: 'Videos', icon: VideoIcon}\n **/\n tool:\n | false\n | {\n title?: string\n icon?: React.ComponentType\n }\n\n /**\n * The roles that are allowed to configure the plugin.\n *\n * If not set, all roles will be allowed to configure the plugin.\n * @defaultValue []\n */\n allowedRolesForConfiguration: string[]\n\n /**\n * Send only Mux addon requests (`/v<apiVersion>/addons/mux/...`) to this host, for example a\n * local development server. Content Lake requests (queries, listeners, asset documents)\n * still use the Studio API host.\n *\n * The host is used as-is: the plugin does not prepend the project id to it. If your server needs\n * the project id in the hostname, include it in the host, like `http://<projectId>.example.test:8000`.\n *\n * Auth: the Studio token (if any) is sent as `Authorization: Bearer`. Session cookies for the\n * Studio API host are not sent to a different host.\n *\n * @example 'http://127.0.0.1:8080'\n * @defaultValue undefined\n */\n muxApiHost?: string\n}\n\nexport const SUPPORTED_MUX_LANGUAGES = [\n {label: 'English', code: 'en', state: 'Stable'},\n {label: 'Spanish', code: 'es', state: 'Stable'},\n {label: 'Italian', code: 'it', state: 'Stable'},\n {label: 'Portuguese', code: 'pt', state: 'Stable'},\n {label: 'German', code: 'de', state: 'Stable'},\n {label: 'French', code: 'fr', state: 'Stable'},\n {label: 'Polish', code: 'pl', state: 'Beta'},\n {label: 'Russian', code: 'ru', state: 'Beta'},\n {label: 'Dutch', code: 'nl', state: 'Beta'},\n {label: 'Catalan', code: 'ca', state: 'Beta'},\n {label: 'Turkish', code: 'tr', state: 'Beta'},\n {label: 'Swedish', code: 'sv', state: 'Beta'},\n {label: 'Ukrainian', code: 'uk', state: 'Beta'},\n {label: 'Norwegian', code: 'no', state: 'Beta'},\n {label: 'Finnish', code: 'fi', state: 'Beta'},\n {label: 'Slovak', code: 'sk', state: 'Beta'},\n {label: 'Greek', code: 'el', state: 'Beta'},\n {label: 'Czech', code: 'cs', state: 'Beta'},\n {label: 'Croatian', code: 'hr', state: 'Beta'},\n {label: 'Danish', code: 'da', state: 'Beta'},\n {label: 'Romanian', code: 'ro', state: 'Beta'},\n {label: 'Bulgarian', code: 'bg', state: 'Beta'},\n] as const\n\nexport const SUPPORTED_MUX_LANGUAGES_VALUES = SUPPORTED_MUX_LANGUAGES.map((l) => l.code)\n\nexport type SupportedMuxLanguage = (typeof SUPPORTED_MUX_LANGUAGES_VALUES)[number]\n\nexport interface TextTrack {\n _id: string\n name: string\n}\n\nexport interface AutogeneratedTextTrack extends TextTrack {\n type: 'autogenerated'\n language_code: SupportedMuxLanguage\n}\n\nexport interface CustomTextTrack extends TextTrack {\n type: 'subtitles' | 'captions'\n language_code: string\n file: {\n contents: string\n type: string\n name: string\n size: number\n }\n}\n\nexport function isCustomTextTrack(track: Partial<UploadTextTrack>): track is CustomTextTrack {\n return track.type !== 'autogenerated'\n}\n\nexport function isAutogeneratedTrack(\n track: Partial<UploadTextTrack>,\n): track is AutogeneratedTextTrack {\n return track.type === 'autogenerated'\n}\n\nexport type UploadTextTrack = AutogeneratedTextTrack | CustomTextTrack\n\n/**\n * Watermark configuration for UI (draggable position)\n */\nexport interface WatermarkConfig {\n enabled: boolean\n imageUrl?: string\n /**\n * Aspect ratio (width / height) of the watermark image.\n * Used to convert between our center-based UI coords and Mux overlay margins.\n */\n imageAspectRatio?: number\n /**\n * Optional explicit Mux `overlay_settings`.\n * When set, these values should be used as-is for the upload request and preview.\n * @see {@link https://www.mux.com/docs/guides/add-watermarks-to-your-videos}\n */\n overlay_settings?: MuxOverlaySettings\n position?: {\n x: number // percentage (0-100)\n y: number // percentage (0-100)\n }\n size?: number // percentage of video width (0-100)\n opacity?: number // 0-1 (converted to percentage string for Mux API)\n}\n\n/**\n * Mux overlay_settings format for watermark API\n * @see {@link https://www.mux.com/docs/guides/add-watermarks-to-your-videos}\n */\nexport interface MuxOverlaySettings {\n vertical_align: 'top' | 'middle' | 'bottom'\n vertical_margin: string // percentage (e.g., \"10%\") or pixels (e.g., \"40px\")\n horizontal_align: 'left' | 'center' | 'right'\n horizontal_margin: string // percentage (e.g., \"10%\") or pixels (e.g., \"40px\")\n width?: string // percentage (e.g., \"25%\") or pixels (e.g., \"80px\")\n height?: string // percentage or pixels\n opacity?: string // percentage string (e.g., \"90%\")\n}\n\nexport interface UploadConfig extends Pick<\n MuxInputConfig,\n 'max_resolution_tier' | 'normalize_audio' | 'video_quality'\n> {\n static_renditions: StaticRenditionResolution[]\n text_tracks: UploadTextTrack[]\n signed_policy: boolean\n public_policy: boolean\n watermark?: WatermarkConfig\n drm_policy: boolean\n}\n\n/**\n * Data sent to Mux to create a new asset.\n * @docs {@link https://docs.mux.com/api-reference#video/operation/create-direct-upload}\n */\nexport interface MuxNewAssetSettings extends Pick<\n MuxInputConfig,\n 'max_resolution_tier' | 'normalize_audio' | 'video_quality'\n> {\n /** Static renditions configuration for downloadable files */\n static_renditions?: {resolution: StaticRenditionResolution}[]\n /** An array of objects that each describe an input file to be used to create the asset.*/\n input?: {\n /** The URL of the file that Mux should download and use. */\n url?: string\n /** Generate subtitle tracks using automatic speech recognition with this configuration. This may only be provided for the first input object (the main input file). */\n generated_subtitles?: {\n /** A name for this subtitle track. */\n name: string\n /** Arbitrary metadata set for the subtitle track. Max 255 characters. */\n passthrough?: string\n /** The language to generate subtitles in. */\n language_code: SupportedMuxLanguage\n }[]\n /** The time offset in seconds from the beginning of the video indicating the clip's starting marker. */\n start_time?: number\n /** The time offset in seconds from the beginning of the video indicating the clip's ending marker. */\n end_time?: number\n /** This parameter is required for text type tracks. */\n type?: 'video' | 'audio' | 'text'\n /** Type of text track. This parameter only supports subtitles value. */\n text_type?: 'subtitles'\n /** The language code value must be a valid BCP 47 specification compliant value. */\n language_code?: string\n /** The name of the track containing a human-readable description. This value must be unique within each group of text or audio track types. */\n name?: string\n /** Indicates the track provides Subtitles for the Deaf or Hard-of-hearing (SDH). */\n closed_captions?: boolean\n /** This optional parameter should be used tracks with type of text and text_type set to subtitles. */\n passthrough?: string\n /** Overlay settings for watermarks. Used when adding a watermark image as a second input. */\n overlay_settings?: MuxOverlaySettings\n }[]\n\n /** An array of playback policy names that you want applied to this asset and available through playback_ids. */\n playback_policy?: PlaybackPolicy[]\n\n /** An array of playback policy objects that you want applied to this asset and available through playback_ids. advanced_playback_policies must be used instead of playback_policies when creating a DRM playback ID. */\n advanced_playback_policies: AdvancedPlaybackPolicy[]\n\n /** Arbitrary user-supplied metadata that will be included in the asset details and related webhooks. */\n passthrough?: string\n}\n\n/** Used by advanced_playback_policies, allows to define DRM config. */\nexport type AdvancedPlaybackPolicy = {\n policy: PlaybackPolicy\n drm_configuration_id?: string\n}\n\nexport interface Secrets {\n token: string | null\n secretKey: string | null\n enableSignedUrls: boolean\n signingKeyId: string | null\n signingKeyPrivate: string | null\n drmConfigId: string | null\n}\n\nexport type MuxImageOrigin = `https://image.mux.com`\nexport type MuxThumbnailUrl = `${MuxImageOrigin}/${string}/thumbnail.png?${string}`\nexport type MuxAnimatedThumbnailUrl = `${MuxImageOrigin}/${string}/animated.gif?${string}`\nexport type MuxVideoOrigin = `https://stream.mux.com`\nexport type MuxVideoUrl = `${MuxVideoOrigin}/${string}.m3u8?${string}`\n\n// 'preserve' by default\n// @url: https://docs.mux.com/guides/video/get-images-from-a-video#thumbnail-query-string-parameters\nexport type FitMode = 'preserve' | 'crop' | 'smartcrop' | 'pad'\n\nexport interface ThumbnailOptions {\n fit_mode?: FitMode\n height?: number\n time?: number\n width?: number\n}\n\nexport interface AnimatedThumbnailOptions {\n // Starting time code for the animation, if no end is set it'll have a 5s duration\n // The start and end timecodes uses `asset.thumbTime` to create an iOS `Live Photo` effect by showing you the 5 secodnds before, and after, the thumb time`\n start?: number\n // End code, can't be longer than 10s after the start code\n end?: number\n // Max 640px, 320px by default\n width?: number\n // Preserves aspect ratio, like width, you can't set both the height and width, max 640\n height?: number\n // The fps is 15 by default, but can go up to 30\n fps?: number\n}\n\nexport interface AssetThumbnailOptions {\n asset: Pick<VideoAssetDocument, 'playbackId' | 'data' | 'thumbTime' | 'filename' | 'assetId'>\n}\n\nexport type PlaybackPolicy = 'signed' | 'public' | 'drm'\n\nexport interface MuxErrors {\n type: string\n messages: string[]\n}\n\nexport interface MuxPlaybackId {\n id: string\n policy: PlaybackPolicy\n}\n\nexport interface MuxVideoTrack {\n type: 'video'\n id: string\n max_width: number\n max_height: number\n // if the fps can't be reliably determined, this will be -1\n max_frame_rate: -1 | number\n // top-level duration is always set, while track level duration is not\n duration?: number\n}\nexport interface MuxAudioTrack {\n type: 'audio'\n id: string\n duration?: number\n max_channels: number\n max_channel_layout: 'stereo' | string\n}\nexport interface MuxTextTrack {\n type: 'text'\n id: string\n text_type?: 'subtitles'\n // https://docs.mux.com/api-reference/video#operation/list-assets:~:text=text%20type%20tracks.-,tracks%5B%5D.,text_source,-string\n text_source?:\n | 'uploaded'\n | 'embedded'\n | 'generated_live'\n | 'generated_live_final'\n | 'generated_vod'\n // BCP 47 language code\n language_code?: 'en' | 'en-US' | string\n // The name of the track containing a human-readable description. The hls manifest will associate a subtitle text track with this value\n name?: 'English' | string\n closed_captions?: boolean\n // Max 255 characters\n passthrough?: string\n status: 'preparing' | 'ready' | 'errored'\n error?: {\n type: string\n messages?: string[]\n }\n}\nexport type MuxTrack = MuxVideoTrack | MuxAudioTrack | MuxTextTrack\n// Typings lifted from https://docs.mux.com/api-reference/video#tag/assets\nexport interface MuxAsset {\n id: string\n /** In seconds (instead of JS's default milliseconds) */\n created_at: string\n status: 'preparing' | 'ready' | 'errored'\n duration: number\n max_stored_resolution: 'Audio only' | 'SD' | 'HD' | 'FHD' | 'UHD'\n max_resolution_tier?: '2160p' | '1440p' | '1080p'\n // if the fps can't be reliably determined, this will be -1\n max_stored_frame_rate: -1 | number\n // The aspect ratio of the asset in the form of width:height, for example 16:9\n aspect_ratio: `${number}:${number}`\n playback_ids: MuxPlaybackId[]\n tracks: MuxTrack[]\n errors?: MuxErrors\n upload_id: string\n is_live?: boolean\n // We use passthrough to set the mux.videoAsset._id of the asset that originally uploaded the video\n passthrough: string\n live_stream_id?: string\n master?: {\n status: 'ready' | 'preparing' | 'errored'\n // Temporary URL to master MP4, expires after 24 hours.\n // Only present once `status` is 'ready'.\n url?: string\n }\n master_access: 'temporary' | 'none'\n mp4_support: 'standard' | 'none'\n // Asset Identifier of the video used as the source for creating the clip.\n source_asset_id?: string\n // Normalize the audio track loudness level. This parameter is only applicable to on-demand (not live) assets., default false\n normalize_audio?: boolean\n // The object does not exist if no static renditions have been requested\n static_renditions?: {\n status: 'ready' | 'preparing' | 'disabled' | 'errored'\n files: {\n name: string\n ext: 'mp4' | 'm4a'\n height: number\n width: number\n bitrate: number\n filesize: string\n type: 'standard' | 'advanced'\n status: 'ready' | 'preparing' | 'skipped' | 'errored'\n resolution_tier?: string\n resolution?: string\n id: string\n passthrough?: string\n }[]\n }\n recording_times?: {\n started_at: string\n duration: number\n type: 'content' | 'slate'\n }[]\n // https://docs.mux.com/guides/video/minimize-processing-time\n non_standard_input_reasons?: {\n video_codec?: string\n audio_codec?: string\n video_gop_size?: 'high'\n video_frame_rate?: string\n video_resolution?: string\n video_bitrate?: 'high'\n pixel_aspect_ratio?: string\n video_edit_list?: 'non-standard'\n audio_edit_list?: 'non-standard'\n unexpected_media_file_parameters?: 'non-standard'\n test?: boolean\n }\n meta?: {\n title?: string\n }\n}\n\nexport interface VideoAssetDocument {\n _id: string\n _type: 'mux.videoAsset'\n _createdAt: string\n _updatedAt?: string\n status?: string\n assetId?: string\n playbackId?: string\n filename?: string\n thumbTime?: number\n // Docs for what goes in `data` https://docs.mux.com/api-reference/video#tag/assets\n data?: PartialDeep<MuxAsset>\n}\n\nexport type Reference = {_type: 'reference'; _ref: string}\n\n// @TODO add Reference, and ReferenceSchemaType in the generic\nexport type MuxInputProps = ObjectInputProps<{\n asset?: Reference\n}>\n","import {TranslateIcon} from '@sanity/icons/Translate'\nimport {UploadIcon} from '@sanity/icons/Upload'\nimport {\n Button,\n Card,\n Checkbox,\n Dialog,\n Flex,\n Label,\n Spinner,\n Stack,\n Text,\n TextInput,\n} from '@sanity/ui'\nimport {Autocomplete} from '@sanity/ui/autocomplete'\nimport {useToast} from '@sanity/ui/toast'\nimport LanguagesList from 'iso-639-1'\nimport {useId, useRef, useState} from 'react'\n\nimport {addTextTrackFromUrl, generateSubtitles, getAsset} from '../actions/assets'\nimport {useClient} from '../hooks/useClient'\nimport {addKeysToMuxData} from '../util/addKeysToMuxData'\nimport {extractErrorMessage, pollTrackStatus} from '../util/textTracks'\nimport {type MuxTextTrack, SUPPORTED_MUX_LANGUAGES, type VideoAssetDocument} from '../util/types'\n\nconst LANGUAGE_OPTIONS = LanguagesList.getAllCodes().map((code) => ({\n value: code,\n label: LanguagesList.getNativeName(code),\n}))\n\nconst MUX_LANGUAGE_OPTIONS = SUPPORTED_MUX_LANGUAGES.map((lang) => ({\n value: lang.code,\n label: lang.label,\n}))\n\nexport interface Props {\n asset: VideoAssetDocument\n onAdd: (track: MuxTextTrack) => void\n onClose: () => void\n}\n\nexport default function AddCaptionDialog({asset, onAdd, onClose}: Props) {\n const client = useClient()\n const toast = useToast()\n const dialogId = `AddCaptionDialog${useId()}`\n\n const [isAutogenerated, setIsAutogenerated] = useState(false)\n const [vttUrl, setVttUrl] = useState('')\n const [languageCode, setLanguageCode] = useState('')\n const [selectedLanguage, setSelectedLanguage] = useState<{value: string; label: string} | null>(\n null,\n )\n const [name, setName] = useState('')\n const [isSubmitting, setIsSubmitting] = useState(false)\n const [selectedFile, setSelectedFile] = useState<File | null>(null)\n const fileInputRef = useRef<HTMLInputElement>(null)\n\n const uploadVttFile = async (file: File): Promise<string> => {\n const assetDocument = await client.assets.upload('file', file, {\n filename: file.name,\n })\n return assetDocument.url\n }\n\n const refreshAssetData = async () => {\n if (!asset._id || !asset.assetId) return\n try {\n const latestAssetData = await getAsset(client, asset.assetId)\n const dataWithKeys = addKeysToMuxData(latestAssetData.data)\n await client\n .patch(asset._id)\n .set({data: dataWithKeys, status: latestAssetData.data.status})\n .commit({returnDocuments: false})\n } catch (refreshError) {\n console.error('Failed to refresh asset data:', refreshError)\n }\n }\n\n const handleAddTrackFromUrl = async () => {\n if (!asset.assetId) {\n throw new Error('Asset ID is required')\n }\n\n const trimmedName = name.trim()\n const trimmedLanguageCode = languageCode.trim()\n\n let vttUrlToUse = vttUrl.trim()\n\n if (selectedFile) {\n try {\n vttUrlToUse = await uploadVttFile(selectedFile)\n } catch (uploadError) {\n toast.push({\n title: 'Failed to upload caption file',\n status: 'error',\n description: 'Could not upload the caption file to Sanity. Please try again.',\n })\n setIsSubmitting(false)\n throw uploadError\n }\n }\n\n await addTextTrackFromUrl(client, asset.assetId, vttUrlToUse, {\n language_code: trimmedLanguageCode,\n name: trimmedName,\n text_type: 'subtitles',\n })\n\n const result = await pollTrackStatus({\n client,\n assetId: asset.assetId,\n trackName: trimmedName,\n trackLanguageCode: trimmedLanguageCode,\n onTrackErrored: async (track) => {\n const errorMessage =\n track.error?.messages?.[0] ||\n track.error?.type ||\n 'The track failed to download from the provided URL'\n toast.push({\n title: 'Caption track failed',\n status: 'error',\n description: errorMessage,\n })\n await refreshAssetData()\n onAdd(track)\n onClose()\n },\n })\n\n if (!result.found || !result.track) {\n toast.push({\n title: 'Caption track may have been added',\n status: 'warning',\n description:\n 'The track was created but its status could not be determined. It may still be processing. Please refresh the page to see if it appears.',\n })\n onClose()\n return\n }\n\n if (result.status === 'errored') {\n return\n }\n\n if (result.status === 'preparing') {\n toast.push({\n title: 'Caption track is processing',\n status: 'info',\n description:\n 'The track was created and is being processed. It will appear in the list shortly.',\n })\n await refreshAssetData()\n onAdd(result.track)\n onClose()\n return\n }\n\n await refreshAssetData()\n toast.push({\n title: 'Caption track added',\n status: 'success',\n description: 'Caption track added successfully',\n })\n\n onAdd(result.track)\n onClose()\n }\n\n const handleGenerateSubtitles = async () => {\n if (!asset.assetId) {\n throw new Error('Asset ID is required')\n }\n\n const assetData = await getAsset(client, asset.assetId)\n const audioTrack = assetData.data.tracks?.find((track) => track.type === 'audio')\n\n if (!audioTrack || !audioTrack.id) {\n toast.push({\n title: 'No audio track found',\n status: 'error',\n description:\n 'The asset does not have an audio track. Auto-generated subtitles require an audio track.',\n })\n throw new Error('No audio track found')\n }\n\n await generateSubtitles(client, asset.assetId, audioTrack.id, {\n language_code: languageCode.trim(),\n name: name.trim(),\n })\n\n const mockTrackId = `generating-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`\n const mockTrack: MuxTextTrack = {\n type: 'text',\n id: mockTrackId,\n text_type: 'subtitles',\n text_source: 'generated_live',\n language_code: languageCode.trim(),\n name: name.trim(),\n status: 'preparing',\n }\n\n toast.push({\n title: 'Generating subtitles',\n status: 'success',\n description: 'This may take a few minutes',\n })\n\n onAdd(mockTrack)\n onClose()\n }\n\n const handleSubmit = async () => {\n if (!isAutogenerated) {\n if (!selectedFile && !vttUrl.trim()) {\n toast.push({\n title: 'Caption file or URL required',\n status: 'error',\n description: 'Please select a VTT or SRT file or enter a caption file URL',\n })\n return\n }\n\n if (vttUrl.trim() && !selectedFile) {\n try {\n void new URL(vttUrl.trim())\n } catch {\n toast.push({\n title: 'Invalid URL',\n status: 'error',\n description:\n 'Please enter a valid URL (e.g., https://example.com/subtitles.vtt or subtitles.srt)',\n })\n return\n }\n }\n }\n\n if (!name.trim()) {\n toast.push({\n title: 'Audio name required',\n status: 'error',\n description: 'Please enter an audio name for this caption track',\n })\n return\n }\n\n if (!languageCode.trim()) {\n toast.push({\n title: 'Language code required',\n status: 'error',\n description: 'Please enter a language code (e.g., en, es, fr)',\n })\n return\n }\n\n setIsSubmitting(true)\n\n try {\n if (isAutogenerated) {\n await handleGenerateSubtitles()\n } else {\n await handleAddTrackFromUrl()\n }\n } catch (error) {\n toast.push({\n title: 'Failed to add caption track',\n status: 'error',\n description: extractErrorMessage(error, 'Failed to add caption track'),\n })\n // oxlint-disable-next-line react/todo\n } finally {\n setIsSubmitting(false)\n }\n }\n\n return (\n <Dialog\n id={dialogId}\n header=\"Add Caption Track\"\n onClose={onClose}\n width={1}\n onClickOutside={onClose}\n >\n <Stack padding={4} gap={4}>\n <Stack gap={2}>\n <Flex align=\"center\" marginBottom={3}>\n <Checkbox\n id=\"autogenerated-checkbox\"\n style={{display: 'block'}}\n checked={isAutogenerated}\n onChange={(e) => {\n setIsAutogenerated(e.currentTarget.checked)\n if (e.currentTarget.checked) {\n setVttUrl('')\n }\n }}\n disabled={isSubmitting}\n />\n <Flex flex={1} paddingLeft={2}>\n <Text>\n <label htmlFor=\"autogenerated-checkbox\">Generate captions</label>\n </Text>\n </Flex>\n </Flex>\n {!isAutogenerated && (\n <Stack gap={2}>\n <Card padding={3} marginBottom={2} tone=\"transparent\" border radius={2}>\n <Flex align=\"center\" justify=\"space-between\">\n <Text size={1} muted>\n {selectedFile ? `Selected: ${selectedFile.name}` : 'No file selected'}\n </Text>\n <Button\n icon={UploadIcon}\n text=\"Select File\"\n mode=\"ghost\"\n tone=\"primary\"\n fontSize={1}\n padding={2}\n onClick={() => fileInputRef.current?.click()}\n disabled={isSubmitting}\n />\n </Flex>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\".vtt,text/vtt,.srt,application/x-subrip\"\n style={{display: 'none'}}\n onChange={(e) => {\n if (e.target.files && e.target.files.length > 0 && !isSubmitting) {\n setSelectedFile(e.target.files[0]!)\n setVttUrl('')\n }\n }}\n />\n </Card>\n <Text size={1} muted style={{textAlign: 'center'}}>\n Or enter the caption file URL\n </Text>\n <Stack gap={2}>\n <Label as=\"label\" htmlFor=\"vtt-url\">\n Caption File URL (.vtt or .srt)\n </Label>\n <TextInput\n id=\"vtt-url\"\n placeholder=\"https://example.com/subtitles.vtt\"\n value={vttUrl}\n onChange={(e) => {\n setVttUrl(e.currentTarget.value)\n setSelectedFile(null)\n }}\n disabled={isSubmitting}\n />\n </Stack>\n </Stack>\n )}\n </Stack>\n\n <Stack gap={2}>\n <Label as=\"label\" htmlFor=\"caption-name\">\n Audio name\n </Label>\n <Autocomplete\n id=\"caption-name\"\n value={selectedLanguage?.value || ''}\n onChange={(newValue) => {\n const options = isAutogenerated ? MUX_LANGUAGE_OPTIONS : LANGUAGE_OPTIONS\n const selected = options.find((opt) => opt.value === newValue)\n if (selected) {\n setSelectedLanguage(selected)\n setLanguageCode(selected.value)\n setName(selected.label)\n }\n }}\n options={isAutogenerated ? MUX_LANGUAGE_OPTIONS : LANGUAGE_OPTIONS}\n icon={TranslateIcon}\n placeholder=\"Select language\"\n filterOption={(query, option) =>\n option.label.toLowerCase().indexOf(query.toLowerCase()) > -1 ||\n option.value.toLowerCase().indexOf(query.toLowerCase()) > -1\n }\n openButton\n renderValue={(value) =>\n (isAutogenerated ? MUX_LANGUAGE_OPTIONS : LANGUAGE_OPTIONS).find(\n (l) => l.value === value,\n )?.label || value\n }\n renderOption={(option) => (\n <Card data-as=\"button\" padding={3} radius={2} tone=\"inherit\">\n <Text size={2} textOverflow=\"ellipsis\">\n {option.label} ({option.value})\n </Text>\n </Card>\n )}\n disabled={isSubmitting}\n />\n </Stack>\n\n <Stack gap={2}>\n <Label as=\"label\" htmlFor=\"caption-language\">\n Language Code\n </Label>\n <TextInput\n id=\"caption-language\"\n placeholder=\"en-US\"\n value={languageCode}\n onChange={(e) => {\n setLanguageCode(e.currentTarget.value)\n if (selectedLanguage && selectedLanguage.value !== e.currentTarget.value) {\n setSelectedLanguage(null)\n if (!name || name === selectedLanguage.label) {\n setName('')\n }\n }\n }}\n disabled={isSubmitting}\n />\n </Stack>\n\n <Flex gap={2} justify=\"flex-end\" marginTop={2}>\n <Button text=\"Cancel\" mode=\"ghost\" onClick={onClose} disabled={isSubmitting} />\n <Button\n text=\"Add Caption Track\"\n tone=\"primary\"\n icon={\n isSubmitting ? (\n <Spinner\n style={{\n verticalAlign: 'middle',\n display: 'inline-block',\n marginBottom: '-3px',\n width: '1em',\n height: '1em',\n marginRight: '-6px',\n }}\n />\n ) : (\n <UploadIcon />\n )\n }\n onClick={handleSubmit}\n disabled={isSubmitting}\n />\n </Flex>\n </Stack>\n </Dialog>\n )\n}\n","import {DownloadIcon} from '@sanity/icons/Download'\nimport {TranslateIcon} from '@sanity/icons/Translate'\nimport {UploadIcon} from '@sanity/icons/Upload'\nimport {Button, Card, Dialog, Flex, Label, Spinner, Stack, Text, TextInput} from '@sanity/ui'\nimport {Autocomplete} from '@sanity/ui/autocomplete'\nimport {useToast} from '@sanity/ui/toast'\nimport LanguagesList from 'iso-639-1'\nimport {useEffect, useId, useRef, useState} from 'react'\n\nimport {addTextTrackFromUrl, deleteTextTrack, getAsset} from '../actions/assets'\nimport {useClient} from '../hooks/useClient'\nimport {addKeysToMuxData} from '../util/addKeysToMuxData'\nimport {generateJwt} from '../util/generateJwt'\nimport {getPlaybackId} from '../util/getPlaybackPolicy'\nimport {getPlaybackPolicy} from '../util/getPlaybackPolicy'\nimport {downloadVttFile, extractErrorMessage, pollTrackStatus} from '../util/textTracks'\nimport type {MuxTextTrack, VideoAssetDocument} from '../util/types'\n\nconst LANGUAGE_OPTIONS = LanguagesList.getAllCodes().map((code) => ({\n value: code,\n label: LanguagesList.getNativeName(code),\n}))\n\nexport interface Props {\n asset: VideoAssetDocument\n track: MuxTextTrack\n onUpdate: (track: MuxTextTrack, oldTrackId?: string) => void\n onClose: () => void\n}\n\nexport default function EditCaptionDialog({asset, track, onUpdate, onClose}: Props) {\n const client = useClient()\n const toast = useToast()\n const dialogId = `EditCaptionDialog${useId()}`\n\n const isAutogenerated =\n track.text_source === 'generated_live' ||\n track.text_source === 'generated_live_final' ||\n track.text_source === 'generated_vod'\n\n const [vttUrl, setVttUrl] = useState('')\n const [languageCode, setLanguageCode] = useState(track.language_code || '')\n const [selectedLanguage, setSelectedLanguage] = useState<{value: string; label: string} | null>(\n () => {\n const baseCode = track.language_code?.split('-')[0]\n const found = LANGUAGE_OPTIONS.find(\n (opt) => opt.value === track.language_code || opt.value === baseCode,\n )\n if (found) return found\n if (track.name) {\n const foundByName = LANGUAGE_OPTIONS.find((opt) => opt.label === track.name)\n if (foundByName) return foundByName\n }\n return null\n },\n )\n const [name, setName] = useState(track.name || '')\n const [isSubmitting, setIsSubmitting] = useState(false)\n const [downloading, setDownloading] = useState(false)\n const [selectedFile, setSelectedFile] = useState<File | null>(null)\n const fileInputRef = useRef<HTMLInputElement>(null)\n\n useEffect(() => {\n // oxlint-disable-next-line react/set-state-in-effect\n setLanguageCode(track.language_code || '')\n setName(track.name || '')\n setVttUrl('')\n const baseCode = track.language_code?.split('-')[0]\n const foundByCode = LANGUAGE_OPTIONS.find(\n (opt) => opt.value === track.language_code || opt.value === baseCode,\n )\n const foundByName = track.name ? LANGUAGE_OPTIONS.find((opt) => opt.label === track.name) : null\n setSelectedLanguage(foundByCode || foundByName || null)\n // oxlint-disable-next-line react/exhaustive-effect-dependencies\n }, [track, asset, client])\n\n const handleDownloadCurrentFile = async () => {\n setDownloading(true)\n try {\n await downloadVttFile(client, asset, track)\n } catch (error) {\n let errorMessage = 'Please try again'\n let title = 'Failed to download VTT file'\n\n if (error instanceof Error) {\n errorMessage = error.message\n if (error.message.includes('Track')) {\n title = 'Cannot download'\n }\n } else if (error === 'Track ID is missing' || error === 'Track is not ready yet') {\n errorMessage = error\n title = 'Cannot download'\n }\n\n toast.push({\n title,\n status: 'error',\n description: errorMessage,\n })\n // oxlint-disable-next-line react/todo\n } finally {\n setDownloading(false)\n }\n }\n\n const getCurrentFileName = () => {\n if (track.id && asset.filename) {\n return `${asset.filename}-${track.language_code || 'en'}.vtt`\n }\n return `captions-${track.language_code || 'en'}.vtt`\n }\n\n const uploadVttFile = async (file: File): Promise<string> => {\n const assetDocument = await client.assets.upload('file', file, {\n filename: file.name,\n })\n return assetDocument.url\n }\n\n const refreshAssetData = async () => {\n if (!asset._id || !asset.assetId) return\n try {\n const latestAssetData = await getAsset(client, asset.assetId)\n const dataWithKeys = addKeysToMuxData(latestAssetData.data)\n await client\n .patch(asset._id)\n .set({data: dataWithKeys, status: latestAssetData.data.status})\n .commit({returnDocuments: false})\n } catch (refreshError) {\n console.error('Failed to refresh asset data:', refreshError)\n }\n }\n\n const handleUpdateTrackWithNewUrl = async () => {\n if (!asset.assetId) {\n throw new Error('Asset ID is required')\n }\n\n const trimmedName = name.trim()\n const trimmedLanguageCode = languageCode.trim()\n\n const oldTrackId = track.id\n\n try {\n await deleteTextTrack(client, asset.assetId, oldTrackId)\n } catch (deleteError) {\n toast.push({\n title: 'Failed to delete old track',\n status: 'error',\n description: 'Could not delete the old track. Please try again or delete it manually.',\n })\n setIsSubmitting(false)\n throw deleteError\n }\n\n let vttUrlToUse = vttUrl.trim()\n\n if (selectedFile) {\n try {\n vttUrlToUse = await uploadVttFile(selectedFile)\n } catch (uploadError) {\n toast.push({\n title: 'Failed to upload VTT file',\n status: 'error',\n description: 'Could not upload the VTT file to Sanity. Please try again.',\n })\n setIsSubmitting(false)\n throw uploadError\n }\n }\n\n try {\n await addTextTrackFromUrl(client, asset.assetId, vttUrlToUse, {\n language_code: trimmedLanguageCode,\n name: trimmedName,\n text_type: 'subtitles',\n })\n } catch (error: unknown) {\n toast.push({\n title: 'Failed to update caption track',\n status: 'error',\n description: extractErrorMessage(error, 'Failed to update caption track'),\n })\n setIsSubmitting(false)\n throw error\n }\n\n const result = await pollTrackStatus({\n client,\n assetId: asset.assetId,\n trackName: trimmedName,\n trackLanguageCode: trimmedLanguageCode,\n onTrackErrored: async (erroredTrack) => {\n const errorMessage =\n erroredTrack.error?.messages?.[0] ||\n erroredTrack.error?.type ||\n 'The track failed to download from the provided URL'\n toast.push({\n title: 'Caption track failed',\n status: 'error',\n description: errorMessage,\n })\n await refreshAssetData()\n onUpdate(erroredTrack, oldTrackId)\n setIsSubmitting(false)\n },\n })\n\n if (!result.found || !result.track) {\n toast.push({\n title: 'Caption track may have been updated',\n status: 'warning',\n description:\n 'The track was updated but its status could not be determined. It may still be processing. Please refresh the page to see if it appears.',\n })\n setIsSubmitting(false)\n return\n }\n\n if (result.status === 'errored') {\n return\n }\n\n await refreshAssetData()\n\n if (result.status === 'preparing') {\n toast.push({\n title: 'Caption track is processing',\n status: 'info',\n description:\n 'The track was updated and is being processed. It will appear in the list shortly.',\n })\n } else {\n toast.push({\n title: 'Caption track updated',\n status: 'success',\n description: 'Caption track updated successfully',\n })\n }\n\n onUpdate(result.track, oldTrackId)\n setIsSubmitting(false)\n }\n\n const handleSubmit = async () => {\n if (!name.trim()) {\n toast.push({\n title: 'Audio name required',\n status: 'error',\n description: 'Please enter an audio name for this caption track',\n })\n return\n }\n\n if (!languageCode.trim()) {\n toast.push({\n title: 'Language code required',\n status: 'error',\n description: 'Please enter a language code (e.g., en, es, fr)',\n })\n return\n }\n\n setIsSubmitting(true)\n\n try {\n if (!asset.assetId) {\n // oxlint-disable-next-line react/todo\n throw new Error('Asset ID is required')\n }\n\n const originalVttUrl = (() => {\n if (isAutogenerated || !track.id) return ''\n const playbackId = getPlaybackId(asset)\n if (!playbackId) return ''\n let url = `https://stream.mux.com/${playbackId}/text/${track.id}.vtt`\n if (getPlaybackPolicy(asset)?.policy === 'signed') {\n const token = generateJwt(client, playbackId, 'v')\n url += `?token=${token}`\n }\n return url\n })()\n\n const urlChanged =\n selectedFile !== null || (vttUrl.trim() && vttUrl.trim() !== originalVttUrl)\n\n if (!urlChanged) {\n toast.push({\n title: 'No changes',\n status: 'info',\n description:\n 'Please provide a new VTT file or URL using the \"Replace\" button or URL field to update the track.',\n })\n setIsSubmitting(false)\n return\n }\n\n if (urlChanged) {\n if (!selectedFile && vttUrl.trim()) {\n try {\n void new URL(vttUrl.trim())\n } catch {\n toast.push({\n title: 'Invalid URL',\n status: 'error',\n description: 'Please enter a valid URL (e.g., https://example.com/subtitles.vtt)',\n })\n setIsSubmitting(false)\n return\n }\n }\n\n if (!selectedFile && !vttUrl.trim()) {\n toast.push({\n title: 'VTT file or URL required',\n status: 'error',\n description: 'Please select a VTT file or enter a VTT file URL',\n })\n setIsSubmitting(false)\n return\n }\n\n await handleUpdateTrackWithNewUrl()\n }\n\n onClose()\n } catch (error) {\n toast.push({\n title: 'Failed to update caption track',\n status: 'error',\n description: error instanceof Error ? error.message : 'Please try again',\n })\n // oxlint-disable-next-line react/todo\n } finally {\n setIsSubmitting(false)\n }\n }\n\n return (\n <Dialog\n id={dialogId}\n header=\"Edit Caption Track\"\n onClose={onClose}\n width={1}\n onClickOutside={onClose}\n >\n <Stack padding={4} gap={4}>\n <Stack gap={2}>\n <Card padding={3} marginBottom={2} tone=\"transparent\" border radius={2}>\n <Flex align=\"center\" justify=\"space-between\">\n <Text>{getCurrentFileName()}</Text>\n <Flex gap={2}>\n {track.status !== 'errored' && (\n <Button\n icon={\n downloading ? (\n <Spinner\n style={{\n verticalAlign: 'middle',\n display: 'inline-block',\n marginTop: '-2px',\n width: '0.5em',\n height: '0.5em',\n }}\n />\n ) : (\n <DownloadIcon />\n )\n }\n text=\"Download\"\n mode=\"ghost\"\n tone=\"primary\"\n fontSize={1}\n padding={2}\n onClick={handleDownloadCurrentFile}\n disabled={downloading || isSubmitting}\n />\n )}\n <Button\n icon={UploadIcon}\n text=\"Replace\"\n mode=\"ghost\"\n tone=\"primary\"\n fontSize={1}\n padding={2}\n onClick={() => fileInputRef.current?.click()}\n disabled={isSubmitting}\n />\n </Flex>\n </Flex>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\".vtt,text/vtt\"\n style={{display: 'none'}}\n onChange={(e) => {\n if (e.target.files && e.target.files.length > 0 && !isSubmitting) {\n setSelectedFile(e.target.files[0]!)\n setVttUrl('')\n }\n }}\n />\n {selectedFile && (\n <Text size={1} muted style={{marginTop: 8}}>\n Selected: {selectedFile.name}\n </Text>\n )}\n </Card>\n <Stack gap={2}>\n <Label as=\"label\" htmlFor=\"vtt-url\">\n VTT File URL\n </Label>\n <TextInput\n id=\"vtt-url\"\n placeholder=\"https://example.com/subtitles.vtt\"\n value={vttUrl}\n onChange={(e) => {\n setVttUrl(e.currentTarget.value)\n setSelectedFile(null)\n }}\n disabled={isSubmitting}\n />\n <Text size={1} muted>\n Add a URL to replace the existing VTT file with a new one\n </Text>\n </Stack>\n </Stack>\n\n <Stack gap={2}>\n <Label as=\"label\" htmlFor=\"caption-name\">\n Audio name\n </Label>\n <Autocomplete\n id=\"caption-name\"\n value={selectedLanguage?.value || ''}\n onChange={(newValue) => {\n const selected = LANGUAGE_OPTIONS.find((opt) => opt.value === newValue)\n if (selected) {\n setSelectedLanguage(selected)\n setLanguageCode(selected.value)\n setName(selected.label)\n }\n }}\n options={LANGUAGE_OPTIONS}\n icon={TranslateIcon}\n placeholder=\"Select language\"\n filterOption={(query, option) =>\n option.label.toLowerCase().indexOf(query.toLowerCase()) > -1 ||\n option.value.toLowerCase().indexOf(query.toLowerCase()) > -1\n }\n openButton\n renderValue={(value) => LANGUAGE_OPTIONS.find((l) => l.value === value)?.label || value}\n renderOption={(option) => (\n <Card data-as=\"button\" padding={3} radius={2} tone=\"inherit\">\n <Text size={2} textOverflow=\"ellipsis\">\n {option.label} ({option.value})\n </Text>\n </Card>\n )}\n disabled={isSubmitting}\n />\n </Stack>\n\n <Stack gap={2}>\n <Label as=\"label\" htmlFor=\"caption-language\">\n Language Code\n </Label>\n <TextInput\n id=\"caption-language\"\n placeholder=\"en-US\"\n value={languageCode}\n onChange={(e) => {\n setLanguageCode(e.currentTarget.value)\n if (selectedLanguage && selectedLanguage.value !== e.currentTarget.value) {\n setSelectedLanguage(null)\n if (!name || name === selectedLanguage.label) {\n setName('')\n }\n }\n }}\n disabled={isSubmitting}\n />\n </Stack>\n\n <Flex gap={2} justify=\"flex-end\" marginTop={2}>\n <Button text=\"Cancel\" mode=\"ghost\" onClick={onClose} disabled={isSubmitting} />\n <Button\n text=\"Update Caption Track\"\n tone=\"primary\"\n icon={\n isSubmitting ? (\n <Spinner\n style={{\n verticalAlign: 'middle',\n display: 'inline-block',\n marginBottom: '-3px',\n width: '1em',\n height: '1em',\n marginRight: '-6px',\n }}\n />\n ) : (\n UploadIcon\n )\n }\n onClick={handleSubmit}\n disabled={isSubmitting}\n />\n </Flex>\n </Stack>\n </Dialog>\n )\n}\n","import {AddIcon} from '@sanity/icons/Add'\nimport {ChevronDownIcon} from '@sanity/icons/ChevronDown'\nimport {ChevronUpIcon} from '@sanity/icons/ChevronUp'\nimport {DownloadIcon} from '@sanity/icons/Download'\nimport {EditIcon} from '@sanity/icons/Edit'\nimport {ErrorOutlineIcon} from '@sanity/icons/ErrorOutline'\nimport {TrashIcon} from '@sanity/icons/Trash'\nimport {Box, Button, Card, Dialog, Flex, Heading, Spinner, Stack, Text} from '@sanity/ui'\nimport {useToast} from '@sanity/ui/toast'\nimport {useEffect, useId, useMemo, useState} from 'react'\n\nimport {deleteTextTrack} from '../actions/assets'\nimport {useClient} from '../hooks/useClient'\nimport {useResyncAsset} from '../hooks/useResyncAsset'\nimport {downloadVttFile} from '../util/textTracks'\nimport type {MuxTextTrack, VideoAssetDocument} from '../util/types'\nimport AddCaptionDialog from './AddCaptionDialog'\nimport EditCaptionDialog from './EditCaptionDialog'\n\ninterface TrackCardProps {\n track: MuxTextTrack\n iconOnly: boolean\n downloadingTrackId: string | null\n deletingTrackId: string | null\n trackToEdit: MuxTextTrack | null\n getTrackSourceLabel: (track: MuxTextTrack) => string\n handleDownload: (track: MuxTextTrack) => void\n setTrackToEdit: (track: MuxTextTrack) => void\n setTrackToDelete: (track: MuxTextTrack) => void\n}\n\nfunction TrackCard({\n track,\n iconOnly,\n downloadingTrackId,\n deletingTrackId,\n trackToEdit,\n getTrackSourceLabel,\n handleDownload,\n setTrackToEdit,\n setTrackToDelete,\n}: TrackCardProps) {\n const isDisabled = (action: 'download' | 'edit' | 'delete') => {\n if (action === 'download') {\n return (\n downloadingTrackId !== null || deletingTrackId === track.id || trackToEdit?.id === track.id\n )\n }\n if (action === 'edit') {\n return (\n downloadingTrackId === track.id ||\n deletingTrackId === track.id ||\n trackToEdit?.id === track.id\n )\n }\n return (\n downloadingTrackId === track.id || deletingTrackId !== null || trackToEdit?.id === track.id\n )\n }\n\n const renderActionButtons = () => {\n if (track.status === 'preparing') {\n return (\n <Flex align=\"center\" gap={2}>\n <Spinner\n muted\n style={{\n width: '0.75em',\n height: '0.75em',\n verticalAlign: 'middle',\n display: 'inline-block',\n marginBottom: '-2px',\n }}\n />\n <Text size={1} muted>\n Processing...\n </Text>\n </Flex>\n )\n }\n\n return (\n <Flex gap={2}>\n {track.status !== 'errored' && (\n <Button\n icon={\n downloadingTrackId === track.id ? (\n <Spinner\n style={{\n verticalAlign: 'middle',\n display: 'inline-block',\n marginTop: '-2px',\n width: '0.5em',\n height: '0.5em',\n }}\n />\n ) : (\n <DownloadIcon />\n )\n }\n text={iconOnly ? undefined : 'Download'}\n mode=\"ghost\"\n tone=\"primary\"\n fontSize={1}\n padding={2}\n onClick={() => handleDownload(track)}\n disabled={isDisabled('download')}\n title=\"Download\"\n />\n )}\n <Button\n icon={<EditIcon />}\n text={iconOnly ? undefined : 'Edit'}\n mode=\"ghost\"\n tone=\"primary\"\n fontSize={1}\n padding={2}\n disabled={isDisabled('edit')}\n onClick={() => setTrackToEdit(track)}\n title=\"Edit\"\n />\n <Button\n icon={\n deletingTrackId === track.id ? (\n <Spinner\n style={{\n verticalAlign: 'middle',\n display: 'inline-block',\n marginTop: '-2px',\n width: '0.5em',\n height: '0.5em',\n }}\n />\n ) : (\n <TrashIcon />\n )\n }\n text={iconOnly ? undefined : 'Delete'}\n mode=\"ghost\"\n tone=\"critical\"\n fontSize={1}\n padding={2}\n disabled={isDisabled('delete')}\n onClick={() => setTrackToDelete(track)}\n title=\"Delete\"\n />\n </Flex>\n )\n }\n\n return (\n <Card\n padding={3}\n radius={2}\n tone={track.status === 'errored' ? 'caution' : 'transparent'}\n border\n >\n <Flex align=\"center\" justify=\"space-between\" gap={3}>\n <Stack gap={2} flex={1}>\n <Flex align=\"center\" gap={2}>\n <Text weight=\"semibold\">{track.name || 'Untitled'}</Text>\n <Text size={1} muted>\n ({getTrackSourceLabel(track)})\n </Text>\n {track.status === 'errored' && (\n <ErrorOutlineIcon\n style={{color: 'var(--card-critical-color)'}}\n aria-label=\"Error\"\n fontSize={20}\n />\n )}\n </Flex>\n {track.language_code && (\n <Text size={1} muted>\n Language: {track.language_code}\n </Text>\n )}\n {track.status === 'errored' && track.error && (\n <Text size={1} style={{color: 'var(--card-critical-color)'}}>\n {track.error.messages?.[0] || track.error.type || 'Failed to process track'}\n </Text>\n )}\n </Stack>\n {renderActionButtons()}\n </Flex>\n </Card>\n )\n}\n\ninterface TextTracksManagerProps {\n asset: VideoAssetDocument\n iconOnly?: boolean\n tracks?: MuxTextTrack[]\n collapseTracks?: boolean\n}\n\nexport default function TextTracksManager({\n asset,\n iconOnly = false,\n tracks: propTracks,\n collapseTracks = false,\n}: TextTracksManagerProps) {\n const client = useClient()\n const toast = useToast()\n const dialogId = `DeleteCaptionDialog${useId()}`\n const {resyncAsset} = useResyncAsset()\n const [downloadingTrackId, setDownloadingTrackId] = useState<string | null>(null)\n const [deletingTrackId, setDeletingTrackId] = useState<string | null>(null)\n const [addedTracks, setAddedTracks] = useState<MuxTextTrack[]>([])\n const [updatedTracks, setUpdatedTracks] = useState<Map<string, MuxTextTrack>>(new Map())\n const [trackActivityOrder, setTrackActivityOrder] = useState<Map<string, number>>(new Map())\n const [autogeneratedTrackIds, setAutogeneratedTrackIds] = useState<Set<string>>(new Set())\n const [trackToDelete, setTrackToDelete] = useState<MuxTextTrack | null>(null)\n const [trackToEdit, setTrackToEdit] = useState<MuxTextTrack | null>(null)\n const [showAddDialog, setShowAddDialog] = useState(false)\n const [isExpanded, setIsExpanded] = useState(false)\n\n const MAX_VISIBLE_TRACKS = 4\n\n const realTracks: MuxTextTrack[] = propTracks\n ? propTracks\n : asset.data?.tracks?.filter((track): track is MuxTextTrack => track.type === 'text') || []\n\n const activeTracks = realTracks.filter(\n (track) =>\n track.id &&\n (track.status === 'ready' || track.status === 'preparing' || track.status === 'errored'),\n )\n\n const allTracks = useMemo(() => {\n const tracksWithUpdates = activeTracks.map((track) => {\n const updated = updatedTracks.get(track.id)\n return updated || track\n })\n\n const isMockTrackReplaced = (mockTrack: MuxTextTrack, realTracksList: MuxTextTrack[]) => {\n if (!mockTrack.id || !mockTrack.id.startsWith('generating-')) {\n return false\n }\n return realTracksList.some((realTrack) => {\n const nameMatches = realTrack.name === mockTrack.name\n const languageMatches = realTrack.language_code === mockTrack.language_code\n if (!nameMatches || !languageMatches) {\n return false\n }\n if (realTrack.status === 'ready') {\n const isGenerated =\n realTrack.text_source === 'generated_live' ||\n realTrack.text_source === 'generated_live_final' ||\n realTrack.text_source === 'generated_vod'\n return isGenerated\n }\n if (realTrack.status === 'preparing') {\n return true\n }\n return false\n })\n }\n\n const isTrackAlreadyInRealTracks = (\n addedTrack: MuxTextTrack,\n realTracksList: MuxTextTrack[],\n ) => {\n if (!addedTrack.id) return false\n if (addedTrack.id.startsWith('generating-')) {\n return isMockTrackReplaced(addedTrack, realTracksList)\n }\n return realTracksList.some((realTrack) => realTrack.id === addedTrack.id)\n }\n\n const tracksToKeep = addedTracks.filter((addedTrack) => {\n if (addedTrack.id && addedTrack.id.startsWith('generating-')) {\n return !isMockTrackReplaced(addedTrack, tracksWithUpdates)\n }\n return !isTrackAlreadyInRealTracks(addedTrack, tracksWithUpdates)\n })\n\n return [...tracksWithUpdates, ...tracksToKeep]\n }, [activeTracks, addedTracks, updatedTracks])\n\n useEffect(() => {\n const newAutogeneratedIds = new Set<string>()\n\n activeTracks.forEach((track) => {\n if (\n track.id &&\n (track.text_source === 'generated_live' ||\n track.text_source === 'generated_live_final' ||\n track.text_source === 'generated_vod')\n ) {\n newAutogeneratedIds.add(track.id)\n }\n })\n\n addedTracks.forEach((mockTrack) => {\n if (mockTrack.id && mockTrack.id.startsWith('generating-')) {\n const realTrack = activeTracks.find((rt) => {\n const nameMatches = rt.name === mockTrack.name\n const languageMatches = rt.language_code === mockTrack.language_code\n return nameMatches && languageMatches\n })\n if (realTrack?.id) {\n newAutogeneratedIds.add(realTrack.id)\n }\n }\n })\n\n // oxlint-disable-next-line react/set-state-in-effect\n setAutogeneratedTrackIds((prev) => {\n let hasNew = false\n const updated = new Set(prev)\n newAutogeneratedIds.forEach((id) => {\n if (!prev.has(id)) {\n updated.add(id)\n hasNew = true\n }\n })\n return hasNew ? updated : prev\n })\n }, [activeTracks, addedTracks])\n\n useEffect(() => {\n const preparingTracks = allTracks.filter((track) => track.status === 'preparing')\n if (preparingTracks.length === 0 || !asset.assetId || !asset._id) {\n return undefined\n }\n\n const interval = setInterval(async () => {\n try {\n const muxData = await resyncAsset(asset)\n if (!muxData) return\n\n const fetchedTracks =\n muxData.tracks?.filter((track): track is MuxTextTrack => track.type === 'text') || []\n\n const isMockTrackReplaced = (\n mockTrack: MuxTextTrack,\n fetchedTracksList: MuxTextTrack[],\n ) => {\n if (!mockTrack.id || !mockTrack.id.startsWith('generating-')) {\n return false\n }\n return fetchedTracksList.some((realTrack) => {\n const nameMatches = realTrack.name === mockTrack.name\n const languageMatches = realTrack.language_code === mockTrack.language_code\n if (!nameMatches || !languageMatches) {\n return false\n }\n if (realTrack.status === 'ready') {\n const isGenerated =\n realTrack.text_source === 'generated_live' ||\n realTrack.text_source === 'generated_live_final' ||\n realTrack.text_source === 'generated_vod'\n return isGenerated\n }\n if (realTrack.status === 'preparing') {\n return true\n }\n return false\n })\n }\n\n const newAutogeneratedIds = new Set<string>()\n fetchedTracks.forEach((track) => {\n if (\n track.id &&\n (track.text_source === 'generated_live' ||\n track.text_source === 'generated_live_final' ||\n track.text_source === 'generated_vod')\n ) {\n newAutogeneratedIds.add(track.id)\n }\n })\n\n const findMatchingRealTrack = (mockTrack: MuxTextTrack, tracksList: MuxTextTrack[]) => {\n return tracksList.find((rt) => {\n const nameMatches = rt.name === mockTrack.name\n const languageMatches = rt.language_code === mockTrack.language_code\n return nameMatches && languageMatches\n })\n }\n\n setAddedTracks((prev) => {\n return prev.filter((mockTrack) => {\n if (mockTrack.id && mockTrack.id.startsWith('generating-')) {\n const replaced = isMockTrackReplaced(mockTrack, fetchedTracks)\n if (replaced) {\n const realTrack = findMatchingRealTrack(mockTrack, fetchedTracks)\n if (realTrack?.id) {\n newAutogeneratedIds.add(realTrack.id)\n setTrackActivityOrder((prevOrder) => {\n const mockOrder = prevOrder.get(mockTrack.id)\n if (mockOrder) {\n const newMap = new Map(prevOrder)\n newMap.set(realTrack.id, mockOrder)\n return newMap\n }\n return prevOrder\n })\n }\n }\n return !replaced\n }\n return true\n })\n })\n\n if (newAutogeneratedIds.size > 0) {\n setAutogeneratedTrackIds((prevIds) => {\n const updated = new Set(prevIds)\n newAutogeneratedIds.forEach((id) => updated.add(id))\n return updated\n })\n }\n } catch (error) {\n console.error('Failed to refresh asset data:', error)\n }\n }, 3000) // Poll every 3 seconds\n\n return () => clearInterval(interval)\n }, [allTracks, asset, resyncAsset])\n\n const visibleTracks = allTracks\n .filter(\n (track) =>\n track.status === 'ready' || track.status === 'preparing' || track.status === 'errored',\n )\n .sort((a, b) => {\n const orderA = trackActivityOrder.get(a.id) || 0\n const orderB = trackActivityOrder.get(b.id) || 0\n\n if (orderA > 0 && orderB > 0) {\n return orderB - orderA\n }\n\n if (orderA > 0) return -1\n if (orderB > 0) return 1\n\n const aIsPreparing = a.status === 'preparing'\n const bIsPreparing = b.status === 'preparing'\n if (aIsPreparing && !bIsPreparing) return -1\n if (!aIsPreparing && bIsPreparing) return 1\n\n const aIsAutogenerated =\n (a.id && a.id.startsWith('generating-')) || (a.id && autogeneratedTrackIds.has(a.id))\n const bIsAutogenerated =\n (b.id && b.id.startsWith('generating-')) || (b.id && autogeneratedTrackIds.has(b.id))\n if (aIsAutogenerated && !bIsAutogenerated) return -1\n if (!aIsAutogenerated && bIsAutogenerated) return 1\n\n return 0\n })\n\n const handleDownload = async (track: MuxTextTrack) => {\n if (!track.id) return\n\n setDownloadingTrackId(track.id)\n try {\n await downloadVttFile(client, asset, track)\n } catch (error) {\n toast.push({\n title: 'Failed to download VTT file',\n status: 'error',\n description: error instanceof Error ? error.message : 'Please try again',\n })\n // oxlint-disable-next-line react/todo\n } finally {\n setDownloadingTrackId(null)\n }\n }\n\n const confirmDelete = async () => {\n if (!trackToDelete || !trackToDelete.id) return\n\n const track = trackToDelete\n setTrackToDelete(null)\n setDeletingTrackId(track.id)\n try {\n if (!asset.assetId) {\n // oxlint-disable-next-line react/todo\n throw new Error('Asset ID is required')\n }\n await deleteTextTrack(client, asset.assetId, track.id)\n\n // Refresh asset data after deletion\n await resyncAsset(asset)\n\n toast.push({\n title: 'Successfully deleted caption track',\n status: 'success',\n })\n\n setAddedTracks((prev) => prev.filter((t) => t.id !== track.id))\n setUpdatedTracks((prev) => {\n const newMap = new Map(prev)\n newMap.delete(track.id)\n return newMap\n })\n setTrackActivityOrder((prev) => {\n const newMap = new Map(prev)\n newMap.delete(track.id)\n return newMap\n })\n setAutogeneratedTrackIds((prev) => {\n const updated = new Set(prev)\n updated.delete(track.id)\n return updated\n })\n } catch (error) {\n toast.push({\n title: 'Failed to delete caption track',\n status: 'error',\n description: error instanceof Error ? error.message : 'Please try again',\n })\n // oxlint-disable-next-line react/todo\n } finally {\n setDeletingTrackId(null)\n }\n }\n\n const handleAddTrack = (track: MuxTextTrack) => {\n setAddedTracks((prev) => [...prev, track])\n setTrackActivityOrder((prev) => {\n const newMap = new Map(prev)\n newMap.set(track.id, prev.size + 1)\n return newMap\n })\n setShowAddDialog(false)\n }\n\n const handleUpdateTrack = async (updatedTrack: MuxTextTrack, oldTrackId?: string) => {\n if (oldTrackId) {\n setAddedTracks((prev) => prev.filter((t) => t.id !== oldTrackId))\n setUpdatedTracks((prev) => {\n const newMap = new Map(prev)\n newMap.delete(oldTrackId)\n return newMap\n })\n setTrackActivityOrder((prev) => {\n const newMap = new Map(prev)\n newMap.delete(oldTrackId)\n return newMap\n })\n setAutogeneratedTrackIds((prev) => {\n const updated = new Set(prev)\n updated.delete(oldTrackId)\n return updated\n })\n }\n\n const isAddedTrack = addedTracks.some((t) => t.id === updatedTrack.id)\n\n if (isAddedTrack) {\n setAddedTracks((prev) => prev.map((t) => (t.id === updatedTrack.id ? updatedTrack : t)))\n } else {\n setUpdatedTracks((prev) => {\n const newMap = new Map(prev)\n newMap.set(updatedTrack.id, updatedTrack)\n return newMap\n })\n }\n\n setTrackActivityOrder((prev) => {\n const newMap = new Map(prev)\n newMap.set(updatedTrack.id, prev.size + 1)\n return newMap\n })\n\n setTrackToEdit(null)\n\n // Refresh asset data after update\n await resyncAsset(asset)\n }\n\n const getTrackSourceLabel = (track: MuxTextTrack) => {\n if (track.id && track.id.startsWith('generating-')) {\n return 'Auto-generated'\n }\n if (track.id && autogeneratedTrackIds.has(track.id)) {\n return 'Auto-generated'\n }\n if (\n track.text_source === 'generated_live_final' ||\n track.text_source === 'generated_live' ||\n track.text_source === 'generated_vod'\n ) {\n return 'Auto-generated'\n }\n if (track.text_source === 'uploaded') {\n return 'Uploaded'\n }\n return 'Custom'\n }\n\n if (visibleTracks.length === 0 && !showAddDialog) {\n return (\n <Stack gap={3}>\n <Flex justify=\"flex-end\">\n <Button\n icon={AddIcon}\n text=\"Add Caption\"\n tone=\"primary\"\n onClick={() => setShowAddDialog(true)}\n />\n </Flex>\n <Card padding={4} radius={2} tone=\"transparent\" border>\n <Text size={1} muted>\n No captions available. Add captions when uploading a video or add them manually.\n </Text>\n </Card>\n {showAddDialog && (\n <AddCaptionDialog\n asset={asset}\n onAdd={handleAddTrack}\n onClose={() => setShowAddDialog(false)}\n />\n )}\n </Stack>\n )\n }\n\n const displayedTracks =\n collapseTracks && !isExpanded ? visibleTracks.slice(0, MAX_VISIBLE_TRACKS) : visibleTracks\n const hasMoreTracks = collapseTracks && visibleTracks.length > MAX_VISIBLE_TRACKS\n\n return (\n <Stack gap={3}>\n <Flex justify=\"flex-end\">\n <Button\n icon={AddIcon}\n text=\"Add Caption\"\n tone=\"primary\"\n onClick={() => setShowAddDialog(true)}\n />\n </Flex>\n\n {displayedTracks.map((track) => (\n <TrackCard\n key={track.id}\n track={track}\n iconOnly={iconOnly}\n downloadingTrackId={downloadingTrackId}\n deletingTrackId={deletingTrackId}\n trackToEdit={trackToEdit}\n getTrackSourceLabel={getTrackSourceLabel}\n handleDownload={handleDownload}\n setTrackToEdit={setTrackToEdit}\n setTrackToDelete={setTrackToDelete}\n />\n ))}\n\n {hasMoreTracks && (\n <Flex justify=\"center\">\n <Button\n icon={isExpanded ? ChevronUpIcon : ChevronDownIcon}\n text={\n isExpanded ? 'Show less' : `Show ${visibleTracks.length - MAX_VISIBLE_TRACKS} more`\n }\n mode=\"ghost\"\n tone=\"primary\"\n onClick={() => setIsExpanded(!isExpanded)}\n />\n </Flex>\n )}\n\n {trackToDelete && (\n <Dialog\n animate\n id={dialogId}\n header=\"Delete track\"\n onClose={() => setTrackToDelete(null)}\n onClickOutside={() => setTrackToDelete(null)}\n width={1}\n >\n <Card\n padding={3}\n style={{\n minHeight: '150px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <Stack gap={3}>\n <Heading size={2}>\n Are you sure you want to delete "\n {trackToDelete.name || trackToDelete.language_code || 'Untitled'}"?\n </Heading>\n <Text size={2}>This action is irreversible</Text>\n <Stack gap={4} marginY={4}>\n <Box>\n <Button\n icon={\n deletingTrackId === trackToDelete.id ? (\n <Spinner\n style={{\n verticalAlign: 'middle',\n display: 'inline-block',\n marginTop: '-2px',\n width: '0.5em',\n height: '0.5em',\n }}\n />\n ) : (\n <TrashIcon />\n )\n }\n fontSize={2}\n padding={3}\n text=\"Delete track\"\n tone=\"critical\"\n onClick={confirmDelete}\n disabled={deletingTrackId !== null}\n />\n </Box>\n </Stack>\n </Stack>\n </Card>\n </Dialog>\n )}\n\n {showAddDialog && (\n <AddCaptionDialog\n asset={asset}\n onAdd={handleAddTrack}\n onClose={() => setShowAddDialog(false)}\n />\n )}\n\n {trackToEdit && (\n <EditCaptionDialog\n asset={asset}\n track={trackToEdit}\n onUpdate={handleUpdateTrack}\n onClose={() => setTrackToEdit(null)}\n />\n )}\n </Stack>\n )\n}\n","import {createContext, useContext, useMemo} from 'react'\n\nimport {type DialogState, type SetDialogState} from '../hooks/useDialogState'\n\ntype DialogStateContextProps = {\n dialogState: DialogState\n setDialogState: SetDialogState\n}\n\nconst DialogStateContext = createContext<DialogStateContextProps>({\n dialogState: false,\n setDialogState: () => {\n return null\n },\n})\n\ninterface DialogStateProviderProps extends DialogStateContextProps {\n children: React.ReactNode\n}\n\nexport const DialogStateProvider = ({\n dialogState,\n setDialogState,\n children,\n}: DialogStateProviderProps) => {\n const value = useMemo(() => ({dialogState, setDialogState}), [dialogState, setDialogState])\n return <DialogStateContext.Provider value={value}>{children}</DialogStateContext.Provider>\n}\n\nexport const useDialogStateContext = () => {\n const context = useContext(DialogStateContext)\n return context\n}\n","import type {SanityClient} from 'sanity'\n\nimport {generateJwt} from './generateJwt'\nimport type {MuxPlaybackId, MuxVideoUrl} from './types'\n\ninterface VideoSrcOptions {\n muxPlaybackId: MuxPlaybackId\n client: SanityClient\n}\n\n/**\n * May throw a Promise. Call this with {@link tryWithSuspend} or rethrow the Promise\n */\nexport function getVideoSrc({client, muxPlaybackId}: VideoSrcOptions): MuxVideoUrl {\n const searchParams = new URLSearchParams()\n\n if (muxPlaybackId.policy === 'signed' || muxPlaybackId.policy === 'drm') {\n const token = generateJwt(client, muxPlaybackId.id, 'v')\n searchParams.set('token', token)\n }\n\n return `https://stream.mux.com/${muxPlaybackId.id}.m3u8?${searchParams}`\n}\n","import {Dialog, Stack} from '@sanity/ui'\nimport {useId} from 'react'\n\nimport {useDialogStateContext} from '../context/DialogStateContext'\nimport type {VideoAssetDocument} from '../util/types'\nimport TextTracksManager from './TextTracksManager'\n\nexport interface Props {\n asset: VideoAssetDocument\n}\n\nexport default function CaptionsDialog({asset}: Props) {\n const {setDialogState} = useDialogStateContext()\n const dialogId = `CaptionsDialog${useId()}`\n\n return (\n <Dialog id={dialogId} header=\"Edit Captions\" onClose={() => setDialogState(false)} width={1}>\n <Stack padding={4}>\n <TextTracksManager asset={asset} />\n </Stack>\n </Dialog>\n )\n}\n","// From: https://stackoverflow.com/a/11486026/10433647\nexport function formatSeconds(seconds: number): string {\n if (typeof seconds !== 'number' || Number.isNaN(seconds)) {\n return ''\n }\n // Hours, minutes and seconds\n const hrs = ~~(seconds / 3600)\n const mins = ~~((seconds % 3600) / 60)\n const secs = ~~seconds % 60\n\n // Output like \"1:01\" or \"4:03:59\" or \"123:03:59\"\n let ret = ''\n\n if (hrs > 0) {\n ret += '' + hrs + ':' + (mins < 10 ? '0' : '')\n }\n\n ret += '' + mins + ':' + (secs < 10 ? '0' : '')\n ret += '' + secs\n return ret\n}\n\n// Output like \"05:14:01\"\nexport function formatSecondsToHHMMSS(seconds: number): string {\n const hrs = Math.floor(seconds / 3600)\n .toString()\n .padStart(2, '0')\n const mins = Math.floor((seconds % 3600) / 60)\n .toString()\n .padStart(2, '0')\n const secs = Math.floor(seconds % 60)\n .toString()\n .padStart(2, '0')\n\n return `${hrs}:${mins}:${secs}`\n}\n\n// Checks if time has a HH:MM:SS format like \"05:14:01\"\nexport function isValidTimeFormat(time: string) {\n const regex = /^([0-1]?[0-9]|2[0-3]):([0-5]?[0-9]):([0-5]?[0-9])$/\n return regex.test(time) || time === ''\n}\n\n// Converts a time like \"05:14:01\" to seconds\nexport function getSecondsFromTimeFormat(time: string): number {\n const [hh = 0, mm = 0, ss = 0] = time.split(':').map(Number)\n return hh * 3600 + mm * 60 + ss\n}\n","import {Button, Dialog, Flex, Stack, Text, TextInput} from '@sanity/ui'\nimport {type ChangeEvent, useId, useMemo, useState} from 'react'\nimport {getDevicePixelRatio} from 'use-device-pixel-ratio'\n\nimport {useDialogStateContext} from '../context/DialogStateContext'\nimport {useClient} from '../hooks/useClient'\nimport {\n formatSecondsToHHMMSS,\n getSecondsFromTimeFormat,\n isValidTimeFormat,\n} from '../util/formatSeconds'\nimport type {VideoAssetDocument} from '../util/types'\nimport VideoThumbnail from './VideoThumbnail'\n\nexport interface Props {\n asset: VideoAssetDocument\n currentTime?: number\n}\n\nexport default function EditThumbnailDialog({asset, currentTime = 0}: Props) {\n const client = useClient()\n\n const {setDialogState} = useDialogStateContext()\n const dialogId = `EditThumbnailDialog${useId()}`\n\n const [timeFormatted, setTimeFormatted] = useState<string>(() =>\n formatSecondsToHHMMSS(currentTime),\n )\n const [nextTime, setNextTime] = useState<number>(currentTime)\n const [inputError, setInputError] = useState<string>('')\n\n const assetWithNewThumbnail = useMemo(() => ({...asset, thumbTime: nextTime}), [asset, nextTime])\n const [saving, setSaving] = useState(false)\n const [saveThumbnailError, setSaveThumbnailError] = useState<Error | null>(null)\n const handleSave = () => {\n setSaving(true)\n client\n .patch(asset._id)\n .set({thumbTime: nextTime})\n .commit({returnDocuments: false})\n .then(() => setDialogState(false))\n .catch(setSaveThumbnailError)\n .finally(() => setSaving(false))\n }\n const width = 300 * getDevicePixelRatio({maxDpr: 2})\n\n if (saveThumbnailError) {\n // @TODO handle errors more gracefully\n throw saveThumbnailError\n }\n\n const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {\n const value = event.currentTarget.value\n setTimeFormatted(value)\n\n if (isValidTimeFormat(value)) {\n setInputError('')\n const totalSeconds = getSecondsFromTimeFormat(value)\n setNextTime(totalSeconds)\n } else {\n setInputError('Invalid time format')\n }\n }\n\n return (\n <Dialog\n id={dialogId}\n header=\"Edit thumbnail\"\n onClose={() => setDialogState(false)}\n footer={\n <Stack padding={3}>\n <Button\n key=\"thumbnail\"\n disabled={inputError !== ''}\n mode=\"ghost\"\n tone=\"primary\"\n loading={saving}\n onClick={handleSave}\n text=\"Set new thumbnail\"\n />\n </Stack>\n }\n >\n <Stack gap={3} padding={3}>\n <Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n Current:\n </Text>\n <VideoThumbnail asset={asset} width={width} staticImage />\n </Stack>\n <Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n New:\n </Text>\n <VideoThumbnail asset={assetWithNewThumbnail} width={width} staticImage />\n </Stack>\n\n <Stack gap={2}>\n <Flex align={'center'} justify={'center'}>\n <Text size={5} weight=\"semibold\">\n Or\n </Text>\n </Flex>\n </Stack>\n\n <Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n Selected time for thumbnail (hh:mm:ss):\n </Text>\n <TextInput\n size={1}\n value={timeFormatted}\n placeholder=\"hh:mm:ss\"\n onChange={handleInputChange}\n customValidity={inputError}\n />\n </Stack>\n </Stack>\n </Dialog>\n )\n}\n","import type {SVGProps} from 'react'\n\nexport function AudioIcon(props: SVGProps<SVGSVGElement>) {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\" {...props}>\n <path\n fill=\"currentColor\"\n style={{opacity: '0.65'}}\n 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\"\n />\n </svg>\n )\n}\n","import {Box, Dialog, Stack} from '@sanity/ui'\nimport {useId} from 'react'\n\nimport {useDialogStateContext} from '../context/DialogStateContext'\nimport {getMezzanineStatus} from '../hooks/useMezzanine'\nimport {DIALOGS_Z_INDEX} from '../util/constants'\nimport type {VideoAssetDocument} from '../util/types'\nimport Mezzanine from './Mezzanine'\nimport MezzanineExplanation from './MezzanineExplanation'\n\nexport interface Props {\n asset: VideoAssetDocument\n onClose?: () => void\n}\n\n/**\n * Player actions menu entry point: the explanation in the dialog body (until the\n * file is enabled) with the {@link Mezzanine} card below for the action/status.\n */\nexport default function MezzanineDialog({asset, onClose}: Props) {\n const {setDialogState} = useDialogStateContext()\n const dialogId = `MezzanineDialog${useId()}`\n\n const closing = () => {\n onClose?.()\n setDialogState(false)\n }\n\n const status = getMezzanineStatus(asset)\n const showExplanation = status !== 'preparing' && status !== 'ready'\n\n return (\n <Dialog\n id={dialogId}\n header=\"Mezzanine file\"\n onClose={closing}\n zOffset={DIALOGS_Z_INDEX}\n width={1}\n >\n <Box padding={4}>\n <Stack gap={4}>\n {showExplanation && <MezzanineExplanation />}\n <Mezzanine asset={asset} withExplanation={false} />\n </Stack>\n </Box>\n </Dialog>\n )\n}\n","import {type MuxPlayerProps, type MuxPlayerRefAttributes} from '@mux/mux-player-react'\nimport MuxPlayer from '@mux/mux-player-react/lazy'\nimport {ErrorOutlineIcon} from '@sanity/icons/ErrorOutline'\nimport {Card, Text} from '@sanity/ui'\nimport {type PropsWithChildren, Suspense, useMemo, useRef, useState} from 'react'\n\nimport {PLUGIN_VERSION} from '../constants'\nimport {useDialogStateContext} from '../context/DialogStateContext'\nimport {useClient} from '../hooks/useClient'\nimport {AUDIO_ASPECT_RATIO, MIN_ASPECT_RATIO} from '../util/constants'\nimport {generateJwt} from '../util/generateJwt'\nimport {getPlaybackId} from '../util/getPlaybackPolicy'\nimport {getPlaybackPolicyById} from '../util/getPlaybackPolicy'\nimport {getPosterSrc} from '../util/getPosterSrc'\nimport {getVideoSrc} from '../util/getVideoSrc'\nimport {tryWithSuspend} from '../util/tryWithSuspend'\nimport type {VideoAssetDocument} from '../util/types'\nimport CaptionsDialog from './CaptionsDialog'\nimport EditThumbnailDialog from './EditThumbnailDialog'\nimport {AudioIcon} from './icons/Audio'\nimport MezzanineDialog from './MezzanineDialog'\n\nexport default function VideoPlayer({\n asset,\n thumbnailWidth = 250,\n children,\n hlsConfig,\n ...props\n}: PropsWithChildren<\n {\n asset: VideoAssetDocument\n thumbnailWidth?: number\n forceAspectRatio?: number\n hlsConfig?: MuxPlayerProps['_hlsConfig']\n } & Partial<Pick<MuxPlayerProps, 'autoPlay'>>\n>) {\n const client = useClient()\n const {dialogState} = useDialogStateContext()\n\n const isAudio = assetIsAudio(asset)\n const muxPlayer = useRef<MuxPlayerRefAttributes>(null)\n const playerContainerRef = useRef<HTMLDivElement>(null)\n const [error, setError] = useState<Error>()\n\n /* Playback ID that will be used to play the video */\n const playbackId = useMemo(() => {\n try {\n return getPlaybackId(asset, ['public', 'signed', 'drm'])\n } catch (e) {\n // oxlint-disable-next-line react/set-state-in-render\n setError(new TypeError('Asset has no playback ID', {cause: e}))\n return undefined\n }\n }, [asset])\n\n const muxPlaybackId = useMemo(() => {\n if (!playbackId) return undefined\n return getPlaybackPolicyById(asset, playbackId)\n }, [asset, playbackId])\n\n const src = useMemo(() => {\n if (!playbackId) return undefined\n if (!muxPlaybackId) return undefined\n return tryWithSuspend(\n () => getVideoSrc({muxPlaybackId, client}),\n (e: Error) => {\n setError(e)\n return undefined\n },\n )\n }, [muxPlaybackId, playbackId, client])\n\n const poster = useMemo(() => {\n return tryWithSuspend(\n () => getPosterSrc({asset, client, width: thumbnailWidth}),\n (e: Error) => {\n setError(e)\n return undefined\n },\n )\n }, [asset, client, thumbnailWidth])\n\n const signedToken = useMemo(() => {\n try {\n const url = new URL(src!)\n return url.searchParams.get('token')\n } catch {\n return undefined\n }\n }, [src])\n const drmToken = useMemo(() => {\n if (!playbackId) return undefined\n if (muxPlaybackId?.policy !== 'drm') return undefined\n\n return tryWithSuspend(\n () => generateJwt(client, playbackId, 'd'),\n (e: Error) => {\n setError(e)\n return undefined\n },\n )\n }, [client, muxPlaybackId?.policy, playbackId])\n const tokens:\n | Partial<{\n playback?: string\n thumbnail?: string\n storyboard?: string\n drm?: string\n }>\n | undefined = useMemo(() => {\n try {\n const partialTokens: {\n playback?: string\n thumbnail?: string\n storyboard?: string\n drm?: string\n } = {\n playback: undefined,\n thumbnail: undefined,\n storyboard: undefined,\n drm: undefined,\n }\n\n if (signedToken) {\n partialTokens.playback = signedToken\n partialTokens.thumbnail = signedToken\n partialTokens.storyboard = signedToken\n }\n\n if (drmToken) {\n partialTokens.drm = drmToken\n }\n\n return {...partialTokens}\n } catch {\n return undefined\n }\n }, [signedToken, drmToken])\n\n const [width, height] = (asset?.data?.aspect_ratio ?? '16:9').split(':').map(Number)\n const targetAspectRatio =\n props.forceAspectRatio || (Number.isNaN(width) ? 16 / 9 : width! / height!)\n let aspectRatio = Math.max(MIN_ASPECT_RATIO, targetAspectRatio)\n if (isAudio) {\n aspectRatio = props.forceAspectRatio\n ? // Make it wider when forcing aspect ratio to balance with videos' rendering height (audio players overflow a bit)\n props.forceAspectRatio * 1.2\n : AUDIO_ASPECT_RATIO\n }\n\n /* We use Suspense here because `generateJwt` and related functions use suspend()\n under the hood */\n return (\n <>\n <Card\n ref={playerContainerRef}\n tone=\"transparent\"\n style={{\n aspectRatio: aspectRatio,\n position: 'relative',\n ...(isAudio && {display: 'flex', alignItems: 'flex-end'}),\n }}\n >\n {src && poster && (\n <>\n {isAudio && (\n <AudioIcon\n style={{\n padding: '0.5em',\n width: '2.2em',\n height: '2.2em',\n position: 'absolute',\n top: 0,\n left: 0,\n zIndex: 1,\n }}\n />\n )}\n <Suspense fallback={null}>\n <MuxPlayer\n poster={isAudio ? undefined : poster}\n ref={muxPlayer}\n {...props}\n playsInline\n playbackId={playbackId}\n tokens={tokens}\n preload=\"metadata\"\n crossOrigin=\"anonymous\"\n metadata={{\n player_name: 'Sanity Admin Dashboard',\n player_version: PLUGIN_VERSION,\n page_type: 'Preview Player',\n }}\n audio={isAudio}\n _hlsConfig={hlsConfig}\n style={{\n ...(!isAudio && {height: '100%'}),\n width: '100%',\n display: 'block',\n objectFit: 'contain',\n ...(isAudio && {alignSelf: 'end'}),\n }}\n />\n {children}\n </Suspense>\n </>\n )}\n {error ? (\n <div\n style={{\n position: 'absolute',\n top: '50%',\n left: '50%',\n transform: 'translate(-50%, -50%)',\n }}\n >\n <Text muted>\n <ErrorOutlineIcon style={{marginRight: '0.15em'}} />\n {typeof error === 'object' && 'message' in error && typeof error.message === 'string'\n ? error.message\n : 'Error loading video'}\n </Text>\n </div>\n ) : null}\n {children}\n </Card>\n\n {dialogState === 'edit-thumbnail' && (\n <EditThumbnailDialog\n asset={asset}\n // oxlint-disable-next-line react/refs\n currentTime={muxPlayer?.current?.currentTime}\n />\n )}\n {dialogState === 'edit-captions' && <CaptionsDialog asset={asset} />}\n {dialogState === 'mezzanine' && <MezzanineDialog asset={asset} />}\n </>\n )\n}\n\nexport function assetIsAudio(asset: VideoAssetDocument) {\n return asset.data?.max_stored_resolution === 'Audio only'\n}\n","// Adapted from https://github.com/sanity-io/sanity/blob/next/packages/sanity/src/desk/components/MissingSchemaType.tsx\nimport {WarningOutlineIcon} from '@sanity/icons/WarningOutline'\nimport type {SanityDocument} from 'sanity'\nimport type {GeneralPreviewLayoutKey} from 'sanity'\nimport {SanityDefaultPreview} from 'sanity'\n\nexport interface MissingSchemaTypeProps {\n layout?: GeneralPreviewLayoutKey\n value: SanityDocument\n}\n\nconst getUnknownTypeFallback = (id: string, typeName: string) => ({\n title: (\n <em>\n No schema found for type <code>{typeName}</code>\n </em>\n ),\n subtitle: (\n <em>\n Document: <code>{id}</code>\n </em>\n ),\n media: () => <WarningOutlineIcon />,\n})\n\nexport function MissingSchemaType(props: MissingSchemaTypeProps) {\n const {layout, value} = props\n\n return (\n <SanityDefaultPreview {...getUnknownTypeFallback(value._id, value._type)} layout={layout} />\n )\n}\n","// Adapted from https://github.com/sanity-io/sanity/blob/next/packages/sanity/src/desk/components/TimeAgo.tsx\nimport {useRelativeTime} from 'sanity'\n\nexport interface TimeAgoProps {\n time: string | Date\n}\n\nexport function TimeAgo({time}: TimeAgoProps) {\n const timeAgo = useRelativeTime(time, {useTemporalPhrase: true})\n\n return <span title={timeAgo}>{timeAgo}</span>\n}\n","// Adapted from https://github.com/sanity-io/sanity/blob/next/packages/sanity/src/desk/components/DraftStatus.tsx\nimport {EditIcon} from '@sanity/icons/Edit'\nimport {Box, Text} from '@sanity/ui'\nimport {Tooltip} from '@sanity/ui/tooltip'\nimport type {PreviewValue, SanityDocument} from 'sanity'\nimport {TextWithTone} from 'sanity'\n\nimport {TimeAgo} from './TimeAgo'\n\nexport function DraftStatus(props: {document?: PreviewValue | Partial<SanityDocument> | null}) {\n const {document} = props\n const updatedAt = document && '_updatedAt' in document && document._updatedAt\n\n return (\n <Tooltip\n animate\n portal\n content={\n <Box padding={2}>\n <Text size={1}>\n {document ? (\n <>Edited {updatedAt && <TimeAgo time={updatedAt} />}</>\n ) : (\n <>No unpublished edits</>\n )}\n </Text>\n </Box>\n }\n >\n <TextWithTone tone=\"caution\" dimmed={!document} muted={!document} size={1}>\n <EditIcon />\n </TextWithTone>\n </Tooltip>\n )\n}\n","// Adapted from https://github.com/sanity-io/sanity/blob/next/packages/sanity/src/desk/components/PublishedStatus.tsx\n\nimport {PublishIcon} from '@sanity/icons/Publish'\nimport {Box, Text} from '@sanity/ui'\nimport {Tooltip} from '@sanity/ui/tooltip'\nimport type {PreviewValue, SanityDocument} from 'sanity'\nimport {TextWithTone} from 'sanity'\n\nimport {TimeAgo} from './TimeAgo'\n\nexport function PublishedStatus(props: {document?: PreviewValue | Partial<SanityDocument> | null}) {\n const {document} = props\n const updatedAt = document && '_updatedAt' in document && document._updatedAt\n\n return (\n <Tooltip\n animate\n portal\n content={\n <Box padding={2}>\n <Text size={1}>\n {document ? (\n <>Published {updatedAt && <TimeAgo time={updatedAt} />}</>\n ) : (\n <>Not published</>\n )}\n </Text>\n </Box>\n }\n >\n <TextWithTone tone=\"positive\" dimmed={!document} muted={!document} size={1}>\n <PublishIcon />\n </TextWithTone>\n </Tooltip>\n )\n}\n","// Adapted from:\n// https://github.com/sanity-io/sanity/blob/next/packages/sanity/src/desk/components/paneItem/PaneItemPreview.tsx\nimport {Inline} from '@sanity/ui'\nimport {isNumber, isString} from 'lodash'\nimport {isValidElement, useMemo} from 'react'\nimport {useObservable} from 'react-rx'\nimport type {SanityDocument, SchemaType} from 'sanity'\nimport {\n type DocumentPresence,\n DocumentPreviewPresence,\n type DocumentPreviewStore,\n type GeneralPreviewLayoutKey,\n getPreviewStateObservable,\n getPreviewValueWithFallback,\n isRecord,\n SanityDefaultPreview,\n} from 'sanity'\n\nimport {DraftStatus} from './DraftStatus'\nimport {PublishedStatus} from './PublishedStatus'\n\nexport interface PaneItemPreviewProps {\n documentPreviewStore: DocumentPreviewStore\n icon: React.ComponentType | false\n layout: GeneralPreviewLayoutKey\n presence?: DocumentPresence[]\n schemaType: SchemaType\n value: SanityDocument\n}\n\nexport function PaneItemPreview(props: PaneItemPreviewProps) {\n const {icon, layout, presence, schemaType, value} = props\n const title =\n (isRecord(value['title']) && isValidElement(value['title'])) ||\n isString(value['title']) ||\n isNumber(value['title'])\n ? value['title']\n : null\n\n const observable = useMemo(\n () => getPreviewStateObservable(props.documentPreviewStore, schemaType, value._id),\n [props.documentPreviewStore, schemaType, value._id],\n )\n const {snapshot, original, isLoading} = useObservable(observable, {\n isLoading: true,\n snapshot: null,\n original: null,\n })\n\n const status = isLoading ? null : (\n <Inline gap={4}>\n {presence && presence.length > 0 && <DocumentPreviewPresence presence={presence} />}\n <PublishedStatus document={original} />\n <DraftStatus document={snapshot} />\n </Inline>\n )\n\n return (\n <SanityDefaultPreview\n {...(getPreviewValueWithFallback({snapshot, original, fallback: {title}}) as any)}\n isPlaceholder={isLoading}\n icon={icon}\n layout={layout}\n status={status}\n />\n )\n}\n","// Adapted from https://github.com/sanity-io/sanity/blob/next/packages/sanity/src/desk/components/paneItem/PaneItem.tsx\n\nimport {DocumentIcon} from '@sanity/icons/Document'\nimport {useMemo} from 'react'\nimport type {CollatedHit, SanityDocument, SchemaType} from 'sanity'\nimport {PreviewCard, useDocumentPresence, useDocumentPreviewStore, useSchema} from 'sanity'\nimport {IntentLink} from 'sanity/router'\n\nimport {MissingSchemaType} from './MissingSchemaType'\nimport {PaneItemPreview} from './PaneItemPreview'\n\ninterface DocumentPreviewProps {\n schemaType?: SchemaType\n documentPair: CollatedHit<SanityDocument>\n}\n\n/**\n * Return `false` if we explicitly disable the icon.\n * Otherwise return the passed icon or the schema type icon as a backup.\n */\nfunction getIconWithFallback(\n icon: React.ComponentType<any> | false | undefined,\n schemaType: SchemaType | undefined,\n defaultIcon: React.ComponentType<any>,\n): React.ComponentType<any> | false {\n if (icon === false) {\n return false\n }\n\n return icon || ((schemaType && schemaType.icon) as any) || defaultIcon || false\n}\n\nexport function DocumentPreview(props: DocumentPreviewProps) {\n const {schemaType, documentPair} = props\n const doc = documentPair?.draft || documentPair?.published\n const id = documentPair.id || ''\n const documentPreviewStore = useDocumentPreviewStore()\n const schema = useSchema()\n const documentPresence = useDocumentPresence(id)\n const hasSchemaType = Boolean(schemaType && schemaType.name && schema.get(schemaType.name))\n\n const children = useMemo(() => {\n if (!doc) return null\n\n if (!schemaType || !hasSchemaType) {\n return <MissingSchemaType value={doc} />\n }\n\n return (\n <PaneItemPreview\n documentPreviewStore={documentPreviewStore}\n icon={getIconWithFallback(undefined, schemaType, DocumentIcon)}\n schemaType={schemaType}\n layout=\"default\"\n value={doc}\n presence={documentPresence}\n />\n )\n }, [hasSchemaType, schemaType, documentPresence, doc, documentPreviewStore])\n\n return (\n <PreviewCard\n __unstable_focusRing\n as={IntentLink}\n intent=\"edit\"\n params={{id: props.documentPair.id}}\n data-as=\"a\"\n data-ui=\"PaneItem\"\n padding={2}\n radius={2}\n tone=\"inherit\"\n >\n {children}\n </PreviewCard>\n )\n}\n","import type {SanityDocument} from '@sanity/client'\nimport {Box, Card, Text} from '@sanity/ui'\nimport {collate, useSchema} from 'sanity'\nimport {styled} from 'styled-components'\n\nimport {DocumentPreview} from '../documentPreview/DocumentPreview'\nimport SpinnerBox from '../SpinnerBox'\n\nconst Container = styled(Box)`\n * {\n color: ${(props: any) => props.theme.sanity.color.base.fg};\n }\n a {\n text-decoration: none;\n }\n h2 {\n font-size: ${(props: any) => props.theme.sanity.fonts.text.sizes[1]};\n }\n`\n\nconst VideoReferences: React.FC<{\n references?: SanityDocument[]\n isLoaded: boolean\n}> = (props) => {\n const schema = useSchema()\n if (!props.isLoaded) {\n return <SpinnerBox />\n }\n\n if (!props.references?.length) {\n return (\n <Card border radius={3} padding={3}>\n <Text size={2}>No documents are using this video</Text>\n </Card>\n )\n }\n\n const documentPairs = collate(props.references || [])\n return (\n <Container>\n {documentPairs?.map((documentPair) => {\n const schemaType = schema.get(documentPair.type)\n\n return (\n <Card\n key={documentPair.id}\n marginBottom={2}\n padding={2}\n radius={2}\n shadow={1}\n style={{overflow: 'hidden'}}\n >\n <Box>\n <DocumentPreview documentPair={documentPair} schemaType={schemaType} />\n </Box>\n </Card>\n )\n })}\n </Container>\n )\n}\n\nexport default VideoReferences\n","import {TrashIcon} from '@sanity/icons/Trash'\nimport {Box, Button, Card, Checkbox, Dialog, Flex, Heading, Stack, Text} from '@sanity/ui'\nimport {useToast} from '@sanity/ui/toast'\nimport {useEffect, useState} from 'react'\nimport type {SanityDocument} from 'sanity'\n\nimport {deleteAsset} from '../../actions/assets'\nimport {useClient} from '../../hooks/useClient'\nimport {DIALOGS_Z_INDEX} from '../../util/constants'\nimport type {VideoAssetDocument} from '../../util/types'\nimport SpinnerBox from '../SpinnerBox'\nimport VideoReferences from './VideoReferences'\n\nexport default function DeleteDialog({\n asset,\n references,\n referencesLoading,\n cancelDelete,\n succeededDeleting,\n}: {\n asset: VideoAssetDocument\n references?: SanityDocument[]\n referencesLoading: boolean\n cancelDelete: () => void\n succeededDeleting: () => void\n}) {\n const client = useClient()\n const [state, setState] = useState<\n 'processing_deletion' | 'checkingReferences' | 'error_deleting' | 'cantDelete' | 'confirm'\n >('checkingReferences')\n const [deleteOnMux, setDeleteOnMux] = useState(true)\n const toast = useToast()\n\n useEffect(() => {\n if (state !== 'checkingReferences' || referencesLoading) return\n\n // oxlint-disable-next-line react/set-state-in-effect\n setState(references?.length ? 'cantDelete' : 'confirm')\n }, [state, references, referencesLoading])\n\n async function confirmDelete() {\n if (state !== 'confirm') return\n\n setState('processing_deletion')\n const worked = await deleteAsset({client, asset, deleteOnMux})\n if (worked === true) {\n toast.push({title: 'Successfully deleted video', status: 'success'})\n succeededDeleting()\n } else if (worked === 'failed-mux') {\n toast.push({\n title: 'Deleted video in Sanity',\n description: \"But it wasn't deleted in Mux\",\n status: 'warning',\n })\n succeededDeleting()\n } else {\n toast.push({title: 'Failed deleting video', status: 'error'})\n\n setState('error_deleting')\n }\n }\n\n return (\n <Dialog\n animate\n header={'Delete video'}\n zOffset={DIALOGS_Z_INDEX}\n id=\"deleting-video-details-dialog\"\n onClose={cancelDelete}\n onClickOutside={cancelDelete}\n width={1}\n position=\"fixed\"\n >\n <Card\n padding={3}\n style={{\n minHeight: '150px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <Stack gap={3}>\n {state === 'checkingReferences' && (\n <>\n <Heading size={2}>Checking if video can be deleted</Heading>\n <SpinnerBox />\n </>\n )}\n {state === 'cantDelete' && (\n <>\n <Heading size={2}>Video can't be deleted</Heading>\n <Text size={2} style={{marginBottom: '2rem'}}>\n There are {references?.length} document{references && references.length > 0 && 's'}{' '}\n pointing to this video. Remove their references to this file or delete them before\n proceeding.\n </Text>\n <VideoReferences references={references} isLoaded={!referencesLoading} />\n </>\n )}\n {state === 'confirm' && (\n <>\n <Heading size={2}>Are you sure you want to delete this video?</Heading>\n <Text size={2}>This action is irreversible</Text>\n <Stack gap={4} marginY={4}>\n <Flex align=\"center\" as=\"label\">\n <Checkbox\n checked={deleteOnMux}\n onChange={() => setDeleteOnMux((prev) => !prev)}\n />\n <Text style={{margin: '0 10px'}}>Delete asset on Mux</Text>\n </Flex>\n <Flex align=\"center\" as=\"label\">\n <Checkbox disabled checked />\n <Text style={{margin: '0 10px'}}>Delete video from dataset</Text>\n </Flex>\n <Box>\n <Button\n icon={TrashIcon}\n fontSize={2}\n padding={3}\n text=\"Delete video\"\n tone=\"critical\"\n onClick={confirmDelete}\n disabled={['processing_deletion', 'checkingReferences', 'cantDelete'].some(\n (s) => s === state,\n )}\n />\n </Box>\n </Stack>\n </>\n )}\n {state === 'processing_deletion' && (\n <>\n <Heading size={2}>Deleting video...</Heading>\n <SpinnerBox />\n </>\n )}\n {state === 'error_deleting' && (\n <>\n <Heading size={2}>Something went wrong!</Heading>\n <Text size={2}>Try deleting the video again by clicking the button below</Text>\n </>\n )}\n </Stack>\n </Card>\n </Dialog>\n )\n}\n","import {createHookFromObservableFactory, type DocumentStore, type SanityDocument} from 'sanity'\n\nimport {SANITY_API_VERSION} from './useClient'\n\nconst useDocReferences = createHookFromObservableFactory<\n SanityDocument[],\n {\n documentStore: DocumentStore\n id: string\n }\n>(({documentStore, id}) => {\n return documentStore.listenQuery(\n /* groq */ '*[references($id)]{_id, _type, _rev, _updatedAt, _createdAt}',\n {id},\n {\n apiVersion: SANITY_API_VERSION,\n },\n )\n})\n\nexport default useDocReferences\n","import {formatSeconds} from './formatSeconds'\nimport type {MuxTextTrack, VideoAssetDocument} from './types'\n\nexport default function getVideoMetadata(doc: VideoAssetDocument) {\n const id = doc.assetId || doc._id || ''\n const date = doc.data?.created_at\n ? new Date(Number(doc.data.created_at) * 1000)\n : new Date(doc._createdAt || doc._updatedAt || Date.now())\n\n return {\n title: doc.filename || id.slice(0, 12),\n id: id,\n playbackId: doc.playbackId,\n createdAt: date,\n duration: doc.data?.duration ? formatSeconds(doc.data?.duration) : undefined,\n playback_ids: doc.data?.playback_ids,\n aspect_ratio: doc.data?.aspect_ratio,\n max_stored_resolution: doc.data?.max_stored_resolution,\n max_stored_frame_rate: doc.data?.max_stored_frame_rate,\n text_tracks:\n doc.data?.tracks?.filter((track): track is MuxTextTrack => track.type === 'text') || [],\n }\n}\n","import {useToast} from '@sanity/ui/toast'\nimport {useMemo, useState} from 'react'\nimport {useDocumentStore} from 'sanity'\n\nimport {useClient} from '../../hooks/useClient'\nimport useDocReferences from '../../hooks/useDocReferences'\nimport {useResyncAsset} from '../../hooks/useResyncAsset'\nimport getVideoMetadata from '../../util/getVideoMetadata'\nimport {type VideoAssetDocument} from '../../util/types'\n\ntype VideoDetailsState = 'idle' | 'saving' | 'deleting' | 'closing' | 'resyncing'\n\nexport interface VideoDetailsProps {\n closeDialog: () => void\n asset: VideoAssetDocument & {autoPlay?: boolean}\n}\n\nexport default function useVideoDetails(props: VideoDetailsProps) {\n const documentStore = useDocumentStore()\n const toast = useToast()\n const client = useClient()\n\n const [references, referencesLoading] = useDocReferences(\n useMemo(() => ({documentStore, id: props.asset._id}), [documentStore, props.asset._id]),\n )\n\n const [originalAsset, setOriginalAsset] = useState(() => props.asset)\n const [filename, setFilename] = useState(props.asset.filename)\n const modified = filename !== originalAsset.filename\n\n const displayInfo = getVideoMetadata({...props.asset, filename})\n\n const [state, setState] = useState<VideoDetailsState>('idle')\n\n const {resyncAsset, isResyncing} = useResyncAsset({showToast: true})\n\n async function handleResync() {\n if (state !== 'idle') return\n setState('resyncing')\n await resyncAsset(props.asset)\n setState('idle')\n }\n\n function handleClose() {\n if (state !== 'idle') return\n\n if (modified) {\n setState('closing')\n return\n }\n\n props.closeDialog()\n }\n\n function confirmClose(shouldClose: boolean) {\n if (state !== 'closing') return\n\n if (shouldClose) props.closeDialog()\n\n setState('idle')\n }\n\n async function saveChanges() {\n if (state !== 'idle') return\n setState('saving')\n\n try {\n await client.patch(props.asset._id).set({filename}).commit()\n setOriginalAsset((prev) => ({...prev, filename}))\n toast.push({\n title: 'Video title updated',\n description: `New title: ${filename}`,\n status: 'success',\n })\n props.closeDialog()\n } catch (error) {\n toast.push({\n title: 'Failed updating file name',\n status: 'error',\n description: typeof error === 'string' ? error : 'Please try again',\n })\n setFilename(originalAsset.filename)\n }\n\n setState('idle')\n }\n\n return {\n references,\n referencesLoading,\n modified,\n filename,\n setFilename,\n displayInfo,\n state,\n setState,\n handleClose,\n confirmClose,\n saveChanges,\n handleResync,\n isResyncing,\n }\n}\n","import {CalendarIcon} from '@sanity/icons/Calendar'\nimport {CheckmarkIcon} from '@sanity/icons/Checkmark'\nimport {ClockIcon} from '@sanity/icons/Clock'\nimport {CropIcon} from '@sanity/icons/Crop'\nimport {EditIcon} from '@sanity/icons/Edit'\nimport {ErrorOutlineIcon} from '@sanity/icons/ErrorOutline'\nimport {RevertIcon} from '@sanity/icons/Revert'\nimport {SearchIcon} from '@sanity/icons/Search'\nimport {SyncIcon} from '@sanity/icons/Sync'\nimport {TagIcon} from '@sanity/icons/Tag'\nimport {TrashIcon} from '@sanity/icons/Trash'\nimport {\n Button,\n Card,\n Dialog,\n Flex,\n Heading,\n Spinner,\n Stack,\n Tab,\n TabList,\n TabPanel,\n Text,\n TextInput,\n} from '@sanity/ui'\nimport {type InputEvent, useEffect, useRef, useState} from 'react'\n\nimport {DIALOGS_Z_INDEX} from '../../util/constants'\nimport type {MuxPlaybackId, MuxTextTrack, PlaybackPolicy} from '../../util/types'\nimport FormField from '../FormField'\nimport IconInfo from '../IconInfo'\nimport {ResolutionIcon} from '../icons/Resolution'\nimport {StopWatchIcon} from '../icons/StopWatch'\nimport Mezzanine from '../Mezzanine'\nimport TextTracksManager from '../TextTracksManager'\nimport VideoPlayer from '../VideoPlayer'\nimport DeleteDialog from './DeleteDialog'\nimport useVideoDetails, {type VideoDetailsProps} from './useVideoDetails'\nimport VideoReferences from './VideoReferences'\n\nconst AssetInput: React.FC<{\n label: string\n description?: string\n placeholder?: string\n value: string\n onInput: (e: InputEvent<HTMLInputElement>) => void\n disabled?: boolean\n}> = (props) => (\n <FormField title={props.label} description={props.description} inputId={props.label}>\n <TextInput\n id={props.label}\n value={props.value}\n placeholder={props.placeholder}\n onInput={props.onInput}\n disabled={props.disabled}\n />\n </FormField>\n)\n\nconst VideoDetails: React.FC<VideoDetailsProps> = (props) => {\n const [tab, setTab] = useState<'details' | 'references'>('details')\n const {\n displayInfo,\n filename,\n modified,\n references,\n referencesLoading,\n setFilename,\n state,\n setState,\n handleClose,\n confirmClose,\n saveChanges,\n handleResync,\n isResyncing,\n } = useVideoDetails(props)\n\n const isSaving = state === 'saving'\n\n // Avoid layout shifts in large screens' 2-column dialog by setting their `minHeight` to the container's\n const [containerHeight, setContainerHeight] = useState<number | null>(null)\n const contentsRef = useRef<HTMLDivElement>(null)\n useEffect(() => {\n if (!contentsRef.current || !('getBoundingClientRect' in contentsRef.current)) return\n\n setContainerHeight(contentsRef.current.getBoundingClientRect().height)\n }, [])\n\n return (\n <Dialog\n animate\n header={displayInfo.title}\n zOffset={DIALOGS_Z_INDEX}\n id=\"video-details-dialog\"\n onClose={handleClose}\n onClickOutside={handleClose}\n width={2}\n position=\"fixed\"\n footer={\n <Card padding={3}>\n <Flex justify=\"space-between\" align=\"center\">\n <Flex gap={2}>\n <Button\n icon={TrashIcon}\n fontSize={2}\n padding={3}\n mode=\"bleed\"\n text=\"Delete\"\n tone=\"critical\"\n onClick={() => setState('deleting')}\n disabled={isSaving || isResyncing}\n />\n <Button\n icon={SyncIcon}\n fontSize={2}\n padding={3}\n mode=\"bleed\"\n text=\"Resync\"\n tone=\"primary\"\n onClick={handleResync}\n disabled={isSaving || isResyncing}\n iconRight={isResyncing && Spinner}\n />\n </Flex>\n {modified && (\n <Button\n icon={CheckmarkIcon}\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Save and close\"\n tone=\"positive\"\n onClick={saveChanges}\n iconRight={isSaving && Spinner}\n disabled={isSaving || isResyncing}\n />\n )}\n </Flex>\n </Card>\n }\n >\n {/* DELETION DIALOG */}\n {state === 'deleting' && (\n <DeleteDialog\n asset={props.asset}\n cancelDelete={() => setState('idle')}\n referencesLoading={referencesLoading}\n references={references}\n succeededDeleting={() => {\n props.closeDialog()\n }}\n />\n )}\n\n {/* CONFIRM CLOSING DIALOG */}\n {state === 'closing' && (\n <Dialog\n animate\n header={'You have unsaved changes'}\n zOffset={DIALOGS_Z_INDEX}\n id=\"closing-video-details-dialog\"\n onClose={() => confirmClose(false)}\n onClickOutside={() => confirmClose(false)}\n width={1}\n position=\"fixed\"\n footer={\n <Card padding={3}>\n <Flex justify=\"space-between\" align=\"center\">\n <Button\n icon={ErrorOutlineIcon}\n fontSize={2}\n padding={3}\n text=\"Discard changes\"\n tone=\"critical\"\n onClick={() => confirmClose(true)}\n />\n {modified && (\n <Button\n icon={RevertIcon}\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Keep editing\"\n tone=\"primary\"\n onClick={() => confirmClose(false)}\n />\n )}\n </Flex>\n </Card>\n }\n >\n <Card padding={5}>\n <Stack style={{textAlign: 'center'}} gap={3}>\n <Heading size={2}>Unsaved changes will be lost</Heading>\n <Text size={2}>Are you sure you want to discard them?</Text>\n </Stack>\n </Card>\n </Dialog>\n )}\n <Card\n padding={4}\n sizing=\"border\"\n style={{\n containerType: 'inline-size',\n }}\n >\n <Flex\n sizing=\"border\"\n gap={4}\n direction={['column', 'column', 'row']}\n align=\"flex-start\"\n ref={contentsRef}\n style={\n typeof containerHeight === 'number'\n ? {\n minHeight: containerHeight,\n }\n : undefined\n }\n >\n <Stack gap={4} flex={1} sizing=\"border\">\n <VideoPlayer asset={props.asset} autoPlay={props.asset.autoPlay || false} />\n {tab === 'details' && (\n <>\n <TextTracksManager\n asset={props.asset}\n iconOnly\n collapseTracks\n tracks={\n displayInfo?.text_tracks ||\n props.asset.data?.tracks?.filter(\n (track): track is MuxTextTrack => track.type === 'text',\n ) ||\n []\n }\n />\n <Mezzanine asset={props.asset} />\n </>\n )}\n </Stack>\n <Stack gap={4} flex={1} sizing=\"border\">\n <TabList gap={2}>\n <Tab\n aria-controls=\"details-panel\"\n icon={EditIcon}\n id=\"details-tab\"\n label=\"Details\"\n onClick={() => setTab('details')}\n selected={tab === 'details'}\n />\n <Tab\n aria-controls=\"references-panel\"\n icon={SearchIcon}\n id=\"references-tab\"\n label={`Used by ${references ? `(${references.length})` : ''}`}\n onClick={() => setTab('references')}\n selected={tab === 'references'}\n />\n </TabList>\n <TabPanel\n aria-labelledby=\"details-tab\"\n id=\"details-panel\"\n hidden={tab !== 'details'}\n style={{wordBreak: 'break-word'}}\n >\n <Stack gap={4}>\n <AssetInput\n label=\"Video title or file name\"\n description=\"Not visible to users. Useful for finding videos later.\"\n value={filename || ''}\n onInput={(e) => setFilename(e.currentTarget.value)}\n disabled={state !== 'idle'}\n />\n <Stack gap={3}>\n {displayInfo?.duration && (\n <IconInfo\n text={`Duration: ${displayInfo.duration}`}\n icon={ClockIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_resolution && (\n <IconInfo\n text={`Max Resolution: ${displayInfo.max_stored_resolution}`}\n icon={ResolutionIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_frame_rate && (\n <IconInfo\n text={`Frame rate: ${displayInfo.max_stored_frame_rate}`}\n icon={StopWatchIcon}\n size={2}\n />\n )}\n {displayInfo?.aspect_ratio && (\n <IconInfo\n text={`Aspect Ratio: ${displayInfo.aspect_ratio}`}\n icon={CropIcon}\n size={2}\n />\n )}\n <IconInfo\n text={`Uploaded on: ${displayInfo.createdAt.toLocaleDateString('en', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })}`}\n icon={CalendarIcon}\n size={2}\n />\n <IconInfo text={`Mux ID: \\n${displayInfo.id}`} icon={TagIcon} size={2} />\n <PlaybackIds playback_ids={displayInfo.playback_ids} />\n </Stack>\n </Stack>\n </TabPanel>\n <TabPanel\n aria-labelledby=\"references-tab\"\n id=\"references-panel\"\n hidden={tab !== 'references'}\n >\n <VideoReferences references={references} isLoaded={!referencesLoading} />\n </TabPanel>\n </Stack>\n </Flex>\n </Card>\n </Dialog>\n )\n}\n\nconst PlaybackIds = ({playback_ids}: {playback_ids?: MuxPlaybackId[]}) => {\n if (playback_ids) {\n return playback_ids.map((entry) => (\n <IconInfo\n key={entry.id}\n text={`Playback ID [${policyToText(entry.policy)}]: ${entry.id}`}\n icon={TagIcon}\n size={2}\n />\n ))\n }\n return <IconInfo text={'No Playback ID'} icon={TagIcon} size={2} />\n}\n\nconst policyToText = (policy: PlaybackPolicy) => {\n switch (policy) {\n case 'drm':\n return 'DRM'\n case 'signed':\n return 'Signed'\n case 'public':\n return 'Public'\n default:\n return policy\n }\n}\nexport default VideoDetails\n","import {CalendarIcon} from '@sanity/icons/Calendar'\nimport {ClockIcon} from '@sanity/icons/Clock'\nimport {TagIcon} from '@sanity/icons/Tag'\nimport {Inline, Stack, Text} from '@sanity/ui'\n\nimport getVideoMetadata from '../util/getVideoMetadata'\nimport type {VideoAssetDocument} from '../util/types'\nimport IconInfo from './IconInfo'\n\nconst VideoMetadata = (props: {asset: VideoAssetDocument}) => {\n if (!props.asset) {\n return null\n }\n\n const displayInfo = getVideoMetadata(props.asset)\n return (\n <Stack gap={2}>\n {displayInfo.title && (\n <Text\n size={1}\n weight=\"semibold\"\n style={{\n wordWrap: 'break-word',\n }}\n >\n {displayInfo.title}\n </Text>\n )}\n <Inline gap={3}>\n {displayInfo?.duration && (\n <IconInfo text={displayInfo.duration} icon={ClockIcon} size={1} muted />\n )}\n <IconInfo\n text={displayInfo.createdAt.toISOString().split('T')[0]!}\n icon={CalendarIcon}\n size={1}\n muted\n />\n {displayInfo.title != displayInfo.id.slice(0, 12) && (\n <IconInfo text={displayInfo.id.slice(0, 12)} icon={TagIcon} size={1} muted />\n )}\n </Inline>\n </Stack>\n )\n}\n\nexport default VideoMetadata\n","import {CheckmarkIcon} from '@sanity/icons/Checkmark'\nimport {EditIcon} from '@sanity/icons/Edit'\nimport {LockIcon} from '@sanity/icons/Lock'\nimport {PlayIcon} from '@sanity/icons/Play'\nimport {Button, Card, Stack, Text} from '@sanity/ui'\nimport {Tooltip} from '@sanity/ui/tooltip'\nimport {useCallback, useState} from 'react'\nimport {styled} from 'styled-components'\n\nimport {DRMWarningDialog, useDrmPlaybackWarningContext} from '../context/DrmPlaybackWarningContext'\nimport {THUMBNAIL_ASPECT_RATIO} from '../util/constants'\nimport {getPlaybackPolicy} from '../util/getPlaybackPolicy'\nimport {type VideoAssetDocument} from '../util/types'\nimport IconInfo from './IconInfo'\nimport {AudioIcon} from './icons/Audio'\nimport VideoMetadata from './VideoMetadata'\nimport VideoPlayer, {assetIsAudio} from './VideoPlayer'\nimport VideoThumbnail from './VideoThumbnail'\n\nconst PlayButton = styled.button`\n display: block;\n padding: 0;\n margin: 0;\n border: none;\n border-radius: 0.1875rem;\n position: relative;\n cursor: pointer;\n\n &::after {\n content: '';\n background: var(--card-fg-color);\n opacity: 0;\n display: block;\n position: absolute;\n inset: 0;\n z-index: 10;\n transition: 0.15s ease-out;\n border-radius: inherit;\n }\n\n > div[data-play] {\n z-index: 11;\n opacity: 0;\n transition: 0.15s 0.05s ease-out;\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n color: var(--card-fg-color);\n background: var(--card-bg-color);\n width: auto;\n height: 30%;\n aspect-ratio: 1;\n border-radius: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n box-sizing: border-box;\n > svg {\n display: block;\n width: 70%;\n height: auto;\n // Visual balance to center-align the icon\n transform: translateX(5%);\n }\n }\n\n &:hover,\n &:focus {\n &::after {\n opacity: 0.3;\n }\n > div[data-play] {\n opacity: 1;\n }\n }\n`\n\ntype RenderState = 'render-video' | 'pre-render-warn' | false\n\nexport default function VideoInBrowser({\n onSelect,\n onEdit,\n asset,\n}: {\n onSelect?: (asset: VideoAssetDocument) => void\n onEdit?: (asset: VideoAssetDocument) => void\n asset: VideoAssetDocument\n}) {\n const [renderVideo, setRenderVideo] = useState<RenderState>(false)\n const select = useCallback(() => onSelect?.(asset), [onSelect, asset])\n const edit = useCallback(() => onEdit?.(asset), [onEdit, asset])\n const {hasShownWarning} = useDrmPlaybackWarningContext()\n\n if (!asset) {\n return null\n }\n\n const playbackPolicy = getPlaybackPolicy(asset)\n const onClickPlay = () => {\n if (playbackPolicy?.policy === 'drm' && !hasShownWarning) {\n setRenderVideo('pre-render-warn')\n } else {\n setRenderVideo('render-video')\n }\n }\n return (\n <Card\n border\n padding={2}\n sizing=\"border\"\n radius={2}\n style={{\n position: 'relative',\n }}\n >\n {playbackPolicy?.policy === 'signed' && (\n <Tooltip\n animate\n content={\n <Card padding={2} radius={2}>\n <IconInfo icon={LockIcon} text=\"Signed playback policy\" size={2} />\n </Card>\n }\n placement=\"right\"\n fallbackPlacements={['top', 'bottom']}\n portal\n >\n <Card\n tone=\"caution\"\n style={{\n borderRadius: '100%',\n position: 'absolute',\n left: '1em',\n top: '1em',\n zIndex: 11,\n }}\n padding={2}\n border\n >\n <Text muted size={1}>\n <LockIcon />\n </Text>\n </Card>\n </Tooltip>\n )}\n {playbackPolicy?.policy === 'drm' && (\n <Tooltip\n animate\n content={\n <Card padding={2} radius={2}>\n <IconInfo icon={LockIcon} text=\"DRM playback policy\" size={2} />\n </Card>\n }\n placement=\"right\"\n fallbackPlacements={['top', 'bottom']}\n portal\n >\n <Card\n tone=\"caution\"\n style={{\n borderRadius: '0.25rem',\n position: 'absolute',\n left: '1em',\n top: '1em',\n zIndex: 11,\n }}\n padding={2}\n border\n >\n <Text muted size={1} weight=\"semibold\" style={{color: 'var(--card-icon-color)'}}>\n DRM\n </Text>\n </Card>\n </Tooltip>\n )}\n <Stack\n gap={3}\n height=\"fill\"\n style={{\n gridTemplateRows: 'min-content min-content 1fr',\n }}\n >\n {renderVideo === 'pre-render-warn' && (\n <DRMWarningDialog\n onClose={() => {\n setRenderVideo('render-video')\n }}\n />\n )}\n {renderVideo === 'render-video' ? (\n <VideoPlayer asset={asset} autoPlay forceAspectRatio={THUMBNAIL_ASPECT_RATIO} />\n ) : (\n <PlayButton onClick={onClickPlay}>\n <div data-play>\n <PlayIcon />\n </div>\n {assetIsAudio(asset) ? (\n <div\n style={{\n aspectRatio: THUMBNAIL_ASPECT_RATIO,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <AudioIcon width=\"3em\" height=\"3em\" />\n </div>\n ) : (\n <VideoThumbnail asset={asset} />\n )}\n </PlayButton>\n )}\n <VideoMetadata asset={asset} />\n <div\n style={{\n display: 'flex',\n width: '100%',\n alignItems: 'flex-end',\n justifyContent: 'flex-start',\n gap: '.35rem',\n }}\n >\n {onSelect && (\n <Button\n icon={CheckmarkIcon}\n fontSize={2}\n padding={2}\n mode=\"ghost\"\n text=\"Select\"\n style={{flex: 1}}\n tone=\"positive\"\n onClick={select}\n />\n )}\n <Button\n icon={EditIcon}\n fontSize={2}\n padding={2}\n mode=\"ghost\"\n text=\"Details\"\n style={{flex: 1}}\n onClick={edit}\n />\n </div>\n </Stack>\n </Card>\n )\n}\n","import {SearchIcon} from '@sanity/icons/Search'\nimport {Card, Flex, Grid, Inline, Label, Stack, Text, TextInput} from '@sanity/ui'\nimport {type InputEvent, useMemo, useState} from 'react'\n\nimport {DrmPlaybackWarningContextProvider} from '../context/DrmPlaybackWarningContext'\nimport useAssets from '../hooks/useAssets'\nimport type {PluginConfig, VideoAssetDocument} from '../util/types'\nimport ConfigureApi from './ConfigureApi'\nimport ImportVideosFromMux from './ImportVideosFromMux'\nimport PageSelector from './PageSelector'\nimport ResyncMetadata from './ResyncMetadata'\nimport {SelectSortOptions} from './SelectSortOptions'\nimport SpinnerBox from './SpinnerBox'\nimport type {VideoDetailsProps} from './VideoDetails/useVideoDetails'\nimport VideoDetails from './VideoDetails/VideoDetails'\nimport VideoInBrowser from './VideoInBrowser'\n\nexport interface VideosBrowserProps {\n config: PluginConfig\n onSelect?: (asset: VideoAssetDocument) => void\n}\n\nexport default function VideosBrowser({onSelect, config}: VideosBrowserProps) {\n const {assets, isLoading, searchQuery, setSearchQuery, setSort, sort} = useAssets()\n const [page, setPage] = useState<number>(0)\n const pageLimit = 20\n const pageTotal = Math.floor(assets.length / pageLimit) + 1\n const [editedAsset, setEditedAsset] = useState<VideoDetailsProps['asset'] | null>(null)\n const freshEditedAsset = useMemo(\n () => assets.find((a) => a._id === editedAsset?._id) || editedAsset,\n [editedAsset, assets],\n )\n\n const pageStart = page * pageLimit\n const pageEnd = pageStart + pageLimit\n\n const placement = onSelect ? 'input' : 'tool'\n return (\n <DrmPlaybackWarningContextProvider config={config}>\n <Stack padding={4} gap={4} style={{minHeight: '50vh'}}>\n <Flex justify=\"space-between\" align=\"center\">\n <Flex align=\"center\" gap={3}>\n <TextInput\n value={searchQuery}\n icon={SearchIcon}\n onInput={(e: InputEvent<HTMLInputElement>) => setSearchQuery(e.currentTarget.value)}\n placeholder=\"Search videos\"\n />\n <SelectSortOptions setSort={setSort} sort={sort} />\n <PageSelector page={page} setPage={setPage} total={pageTotal} />\n </Flex>\n {placement === 'tool' && (\n <Inline gap={2}>\n <ImportVideosFromMux />\n <ResyncMetadata />\n <ConfigureApi />\n </Inline>\n )}\n </Flex>\n <Stack gap={3}>\n {assets?.length > 0 && (\n <Label muted>\n {assets.length} video{assets.length > 1 ? 's' : null}{' '}\n {searchQuery ? `matching \"${searchQuery}\"` : 'found'}\n </Label>\n )}\n <Grid\n gap={2}\n style={{\n gridTemplateColumns: 'repeat(auto-fill, minmax(250px, 1fr))',\n }}\n >\n {assets.slice(pageStart, pageEnd).map((asset) => (\n <VideoInBrowser\n key={asset._id}\n asset={asset}\n onEdit={setEditedAsset}\n onSelect={onSelect}\n />\n ))}\n </Grid>\n </Stack>\n {isLoading && <SpinnerBox />}\n\n {!isLoading && assets.length === 0 && (\n <Card marginY={4} paddingX={4} paddingY={6} border radius={2} tone=\"transparent\">\n <Text align=\"center\" muted size={3}>\n {searchQuery ? `No videos found for \"${searchQuery}\"` : 'No videos in this dataset'}\n </Text>\n </Card>\n )}\n </Stack>\n {freshEditedAsset && (\n <VideoDetails closeDialog={() => setEditedAsset(null)} asset={freshEditedAsset} />\n )}\n </DrmPlaybackWarningContextProvider>\n )\n}\n","import type {Tool} from 'sanity'\n\nimport {MuxApiHostProvider} from '../context/MuxApiHostContext'\nimport type {PluginConfig} from '../util/types'\nimport ToolIcon from './icons/ToolIcon'\nimport VideosBrowser from './VideosBrowser'\n\nconst StudioTool: React.FC<PluginConfig> = (config) => {\n return (\n <MuxApiHostProvider muxApiHost={config.muxApiHost}>\n <VideosBrowser config={config} />\n </MuxApiHostProvider>\n )\n}\n\nexport const DEFAULT_TOOL_CONFIG = {\n icon: ToolIcon,\n title: 'Videos',\n}\n\nexport default function createStudioTool(config: PluginConfig): Tool {\n const toolConfig = typeof config.tool === 'object' ? config.tool : DEFAULT_TOOL_CONFIG\n return {\n name: 'mux',\n icon: toolConfig.icon || DEFAULT_TOOL_CONFIG.icon,\n title: toolConfig.title || DEFAULT_TOOL_CONFIG.title,\n component: (props: any) => <StudioTool {...config} {...props} />,\n }\n}\n","import {useCurrentUser} from 'sanity'\n\nimport {type PluginConfig} from '../util/types'\n\nexport const useAccessControl = (config: PluginConfig) => {\n const user = useCurrentUser()\n\n const hasConfigAccess =\n !config?.allowedRolesForConfiguration?.length ||\n user?.roles?.some((role) => config.allowedRolesForConfiguration.includes(role.name))\n\n return {hasConfigAccess}\n}\n","import {isReference} from 'sanity'\nimport {useDocumentValues} from 'sanity'\n\nimport type {Reference, VideoAssetDocument} from '../util/types'\n\nconst path = ['assetId', 'data', 'playbackId', 'status', 'thumbTime', 'filename']\nexport const useAssetDocumentValues = (asset: Reference | null | undefined) =>\n useDocumentValues<VideoAssetDocument | null | undefined>(\n isReference(asset) ? asset._ref : '',\n path,\n )\n","import {useMemo, useRef} from 'react'\nimport {useDataset, useProjectId} from 'sanity'\nimport useSWR from 'swr'\n\nimport {useClient} from '../hooks/useClient'\nimport {addKeysToMuxData} from '../util/addKeysToMuxData'\nimport {getMuxAddonClient} from '../util/muxAddonClient'\nimport {PLUGIN_VERSION_QUERY} from '../util/pluginVersion'\nimport type {MuxAsset, VideoAssetDocument} from '../util/types'\n\n// Poll MUX if it's preparing the main document or its own static renditions\nexport const useMuxPolling = (asset?: VideoAssetDocument) => {\n const client = useClient()\n const projectId = useProjectId()\n const dataset = useDataset()\n const isPreparingStaticRenditions = useMemo(() => {\n // Legacy: If static_renditions has a status field, it was created with mp4_support (deprecated)\n // We don't process this old format, just return false\n // Note: 'disabled' status is valid in the new format when no renditions were requested\n if (\n asset?.data?.static_renditions?.status &&\n asset?.data?.static_renditions?.status !== 'disabled'\n ) {\n return false\n }\n\n const files = asset?.data?.static_renditions?.files\n if (!files || files.length === 0) {\n return false\n }\n return files.some((file) => file.status === 'preparing')\n }, [asset?.data?.static_renditions?.status, asset?.data?.static_renditions?.files])\n\n const shouldFetch = useMemo(\n () => !!asset?.assetId && (asset?.status === 'preparing' || isPreparingStaticRenditions),\n [asset?.assetId, asset?.status, isPreparingStaticRenditions],\n )\n // Only log the first failure of a streak so a persistent error doesn't flood\n // the console on every interval.\n const errorLoggedRef = useRef(false)\n return useSWR(\n shouldFetch ? `/${projectId}/addons/mux/assets/${dataset}/data/${asset?.assetId}` : null,\n async () => {\n try {\n const {data} = await getMuxAddonClient(client).request<{data: MuxAsset}>({\n url: `/addons/mux/assets/${dataset}/data/${asset!.assetId}`,\n withCredentials: true,\n method: 'GET',\n query: PLUGIN_VERSION_QUERY,\n })\n if (!asset?._id || !data) return\n await client\n .patch(asset._id)\n .set({status: data.status, data: addKeysToMuxData(data)})\n .commit({returnDocuments: false})\n errorLoggedRef.current = false\n } catch (error) {\n // Input re-throws `poll.error`, so a background polling failure would\n // crash the whole field. Swallow it instead.\n if (!errorLoggedRef.current) {\n errorLoggedRef.current = true\n console.error('[sanity-plugin-mux-input] Mux polling failed', {\n assetId: asset?.assetId,\n documentId: asset?._id,\n error,\n })\n }\n }\n },\n {refreshInterval: 2000, refreshWhenHidden: true, dedupingInterval: 1000},\n )\n}\n","/* eslint-disable no-console */\nimport {Button, Card, Flex, Grid, Heading, Inline, Text} from '@sanity/ui'\nimport {useToast} from '@sanity/ui/toast'\nimport {memo, useCallback, useRef} from 'react'\nimport scrollIntoView from 'scroll-into-view-if-needed'\nimport {clear} from 'suspend-react'\nimport {useErrorBoundary} from 'use-error-boundary'\n\nimport {name} from '../util/constants'\nimport {type MuxInputProps} from '../util/types'\n\nexport interface Props extends Pick<MuxInputProps, 'schemaType'> {\n children: React.ReactNode\n}\nfunction ErrorBoundaryCard(props: Props) {\n const {children, schemaType} = props\n const {push: pushToast} = useToast()\n const errorRef = useRef(null)\n const {ErrorBoundary, didCatch, error, reset} = useErrorBoundary({\n // oxlint-disable-next-line no-unstable-nested-components\n onDidCatch: (err, errorInfo) => {\n console.group(err.toString())\n console.groupCollapsed('console.error')\n console.error(err)\n console.groupEnd()\n if (err.stack) {\n console.groupCollapsed('error.stack')\n console.log(err.stack)\n console.groupEnd()\n }\n if (errorInfo?.componentStack) {\n console.groupCollapsed('errorInfo.componentStack')\n console.log(errorInfo.componentStack)\n console.groupEnd()\n }\n console.groupEnd()\n pushToast({\n status: 'error',\n title: 'Plugin crashed',\n description: (\n <Flex align=\"center\">\n <Inline gap={1}>\n An error happened while rendering\n <Button\n padding={1}\n fontSize={1}\n style={{transform: 'translateY(1px)'}}\n mode=\"ghost\"\n text={schemaType.title}\n onClick={() => {\n if (errorRef.current) {\n scrollIntoView(errorRef.current, {\n behavior: 'smooth',\n scrollMode: 'if-needed',\n block: 'center',\n })\n }\n }}\n />\n </Inline>\n </Flex>\n ),\n })\n },\n })\n const handleRetry = useCallback(() => {\n // Purge request cache before retrying, otherwise the cached errors will rethrow\n clear([name])\n\n reset()\n }, [reset])\n\n if (didCatch) {\n return (\n <Card ref={errorRef} paddingX={[2, 3, 4, 4]} height=\"fill\" shadow={1} overflow=\"auto\">\n <Flex justify=\"flex-start\" align=\"center\" height=\"fill\">\n <Grid gridTemplateColumns={1} gap={[2, 3, 4, 4]}>\n <Heading as=\"h1\">\n The <code>{name}</code> plugin crashed\n </Heading>\n {error?.message && (\n <Card padding={3} tone=\"critical\" shadow={1} radius={2}>\n <Text>{error.message}</Text>\n </Card>\n )}\n <Inline>\n <Button onClick={handleRetry} text=\"Retry\" />\n </Inline>\n </Grid>\n </Flex>\n </Card>\n )\n }\n\n return <ErrorBoundary>{children}</ErrorBoundary>\n}\n\nexport default memo(ErrorBoundaryCard)\n","import {Box, Card, Flex, Spinner, Text} from '@sanity/ui'\n\nexport const InputFallback = () => {\n return (\n <div style={{padding: 1}}>\n <Card\n shadow={1}\n sizing=\"border\"\n style={{aspectRatio: '16/9', width: '100%', borderRadius: '1px'}}\n >\n <Flex align=\"center\" direction=\"column\" height=\"fill\" justify=\"center\">\n <Spinner muted />\n <Box marginTop={3}>\n <Text align=\"center\" muted size={1}>\n Loading…\n </Text>\n </Box>\n </Flex>\n </Card>\n </div>\n )\n}\n","import {PlugIcon} from '@sanity/icons/Plug'\nimport {Button, Card, Flex, Grid, Heading, Inline, Text} from '@sanity/ui'\nimport {useCallback} from 'react'\n\nimport {useAccessControl} from '../hooks/useAccessControl'\nimport type {SetDialogState} from '../hooks/useDialogState'\nimport {type PluginConfig} from '../util/types'\nimport MuxLogo from './MuxLogo'\n\ninterface OnboardProps {\n setDialogState: SetDialogState\n config: PluginConfig\n}\n\nexport default function Onboard(props: OnboardProps) {\n const {setDialogState} = props\n const handleOpen = useCallback(() => setDialogState('secrets'), [setDialogState])\n const {hasConfigAccess} = useAccessControl(props.config)\n\n return (\n <>\n <div style={{padding: 2}}>\n <Card\n display=\"flex\"\n sizing=\"border\"\n style={{\n aspectRatio: '16/9',\n width: '100%',\n boxShadow: 'var(--card-bg-color) 0 0 0 2px',\n }}\n paddingX={[2, 3, 4, 4]}\n radius={1}\n tone=\"transparent\"\n >\n <Flex justify=\"flex-start\" align=\"center\">\n <Grid gridTemplateColumns={1} gap={[2, 3, 4, 4]}>\n <Inline paddingY={1}>\n <div style={{height: '32px'}}>\n <MuxLogo />\n </div>\n </Inline>\n <Inline paddingY={1}>\n <Heading size={[0, 1, 2, 2]}>\n Upload and preview videos directly from your studio.\n </Heading>\n </Inline>\n <Inline paddingY={1}>\n {hasConfigAccess ? (\n <Button mode=\"ghost\" icon={PlugIcon} text=\"Configure API\" onClick={handleOpen} />\n ) : (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"critical\">\n <Text>\n You do not have access to configure the Mux API. Please contact your\n administrator.\n </Text>\n </Card>\n )}\n </Inline>\n </Grid>\n </Flex>\n </Card>\n </div>\n </>\n )\n}\n","import {UpChunk} from '@mux/upchunk'\nimport {Observable} from 'rxjs'\n\nexport function createUpChunkObservable(uuid: string, uploadUrl: string, source: File) {\n return new Observable<\n | {type: 'pause' | 'resume'; id: string}\n | {type: 'success'; id: string}\n | {type: 'progress'; percent: number}\n >((subscriber) => {\n const upchunk = UpChunk.createUpload({\n endpoint: uploadUrl,\n file: source,\n dynamicChunkSize: true, // changes the chunk size based on network speeds\n })\n\n const successHandler = () => {\n subscriber.next({\n type: 'success',\n id: uuid,\n })\n subscriber.complete()\n }\n\n const errorHandler = (data: CustomEvent) => subscriber.error(new Error(data.detail.message))\n\n const progressHandler = (data: CustomEvent) => {\n return subscriber.next({type: 'progress', percent: data.detail})\n }\n\n const offlineHandler = () => {\n upchunk.pause()\n subscriber.next({\n type: 'pause',\n id: uuid,\n })\n }\n\n const onlineHandler = () => {\n upchunk.resume()\n subscriber.next({\n type: 'resume',\n id: uuid,\n })\n }\n\n upchunk.on('success', successHandler)\n upchunk.on('error', errorHandler)\n upchunk.on('progress', progressHandler)\n upchunk.on('offline', offlineHandler)\n upchunk.on('online', onlineHandler)\n\n return () => upchunk.abort()\n })\n}\n","/**\n * Format Google Drive share links as Google Drive export links.\n * Supported formats:\n * - https://drive.google.com/uc?id=<ID>...\n * - https://drive.google.com/open?id=<ID>...\n * - https://drive.google.com/file/d/<ID>...\n * - https://drive.google.com/folder/<ID>...\n *\n * @param url Google Drive share link to format.\n * @returns Google Drive export link (URL passthrough if not share link).\n */\nexport function formatDriveShareLink(url: string): string {\n // Export link formatter.\n const formatExportLink = (id: string) => {\n return `https://drive.google.com/uc?export=download&id=${id}`\n }\n\n // URL formatting.\n try {\n // Parse URL.\n const trimmed = url.trim()\n const parsed = new URL(trimmed)\n\n // Enforce strict host name.\n if (parsed.hostname !== 'drive.google.com') {\n throw new Error('URL is not from Google Drive.')\n }\n\n // Look for ID in search parameters.\n const id = parsed.searchParams.get('id') || ''\n if (id.length) {\n return formatExportLink(id)\n }\n\n // Look for ID in path name.\n const path = parsed.pathname.split('/') || []\n\n // Path is /file/d/<ID>...\n if (path.includes('file') && path.includes('d')) {\n const index =\n path.findIndex((value: string) => {\n return value === 'd'\n }) + 1\n const fileId = path.at(index) || ''\n return formatExportLink(fileId)\n }\n\n // Path is /folder/<ID>...\n if (path.includes('folders')) {\n const index =\n path.findIndex((value: string) => {\n return value === 'folders'\n }) + 1\n const folderId = path.at(index) || ''\n return formatExportLink(folderId)\n }\n\n // URL not recognized.\n throw new Error('URL was not recognized.')\n } catch {\n // URL passthrough by default.\n return url\n }\n}\n","/**\n * Rounds the numeric part of a px string to the nearest integer.\n * Returns undefined if the value is not a valid px string or not a finite number.\n * Avoids sending 0px (and JS -0); snaps to ±1 instead.\n */\nexport function roundPxString(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n if (!trimmed.endsWith('px')) return undefined\n const n = Number(trimmed.slice(0, -2))\n if (!Number.isFinite(n)) return undefined\n let rounded = Math.round(n)\n // Avoid sending 0px (and JS -0); keep sign when negative.\n if (rounded === 0) rounded = n < 0 ? -1 : 1\n return `${rounded}px`\n}\n","import {uuid as generateUuid} from '@sanity/uuid'\nimport {concat, defer, from, type Observable, of, throwError} from 'rxjs'\nimport {catchError, mergeMap, switchMap} from 'rxjs/operators'\nimport type {SanityClient} from 'sanity'\n\nimport {createUpChunkObservable} from '../clients/upChunkObservable'\nimport {formatDriveShareLink} from '../util/formatDriveShareLink'\nimport {getMuxAddonClient} from '../util/muxAddonClient'\nimport {PLUGIN_VERSION_QUERY} from '../util/pluginVersion'\nimport {roundPxString} from '../util/roundPxString'\nimport type {MuxAsset, MuxNewAssetSettings, WatermarkConfig} from '../util/types'\nimport {getAsset} from './assets'\nimport {testSecretsObservable} from './secrets'\n\nfunction sanitizeOverlaySettingsInPlace(settings: MuxNewAssetSettings) {\n const inputs = settings.input\n if (!inputs) return\n for (const input of inputs) {\n const overlay = (input as {overlay_settings?: Record<string, unknown>}).overlay_settings\n if (!overlay) continue\n\n const hm = roundPxString(overlay['horizontal_margin'])\n const vm = roundPxString(overlay['vertical_margin'])\n const w = roundPxString(overlay['width'])\n\n if (hm) overlay['horizontal_margin'] = hm\n if (vm) overlay['vertical_margin'] = vm\n if (w) overlay['width'] = w\n }\n}\n\nfunction sanitizePxStringsInJson(json: string): string {\n return json.replace(/\"(-?\\d+(?:\\.\\d+)?)px\"/g, (_match, num) => {\n const n = Number(num)\n if (!Number.isFinite(n)) return _match\n let rounded = Math.round(n)\n if (rounded === 0) rounded = n < 0 ? -1 : 1\n return `\"${rounded}px\"`\n })\n}\n\nfunction cancelUpload(client: SanityClient, uuid: string) {\n return getMuxAddonClient(client).observable.request({\n url: `/addons/mux/uploads/${client.config().dataset}/${uuid}`,\n withCredentials: true,\n method: 'DELETE',\n query: PLUGIN_VERSION_QUERY,\n })\n}\n\nexport function uploadUrl({\n url,\n settings,\n client,\n}: {\n url: string\n settings: MuxNewAssetSettings\n client: SanityClient\n watermark?: WatermarkConfig\n}) {\n return testUrl(url).pipe(\n switchMap((validUrl) => {\n return concat(\n of({type: 'url' as const, url: validUrl}),\n testSecretsObservable(client).pipe(\n switchMap((json) => {\n if (!json || !json.status) {\n return throwError(() => new Error('Invalid credentials'))\n }\n const uuid = generateUuid()\n const muxBody = settings\n if (!muxBody.input) muxBody.input = [{type: 'video'}]\n muxBody.input[0]!.url = validUrl\n sanitizeOverlaySettingsInPlace(muxBody)\n\n const query: Record<string, string> = {\n muxBody: sanitizePxStringsInJson(JSON.stringify(muxBody)),\n }\n const filename = validUrl.split('/').slice(-1)[0]\n if (filename) {\n query['filename'] = filename\n }\n\n const dataset = client.config().dataset\n return defer(() =>\n getMuxAddonClient(client).observable.request({\n url: `/addons/mux/assets/${dataset}`,\n withCredentials: true,\n method: 'POST',\n headers: {\n 'MUX-Proxy-UUID': uuid,\n 'Content-Type': 'application/json',\n },\n query: {...query, ...PLUGIN_VERSION_QUERY},\n }),\n ).pipe(\n mergeMap((result) => {\n const asset =\n (result && result.results && result.results[0] && result.results[0].document) ||\n null\n\n if (!asset) {\n return throwError(() => new Error('No asset document returned'))\n }\n return of({type: 'success' as const, id: uuid, asset})\n }),\n )\n }),\n ),\n )\n }),\n )\n}\n\nexport function uploadFile({\n settings,\n client,\n file,\n watermark,\n}: {\n settings: MuxNewAssetSettings\n client: SanityClient\n file: File\n watermark?: WatermarkConfig\n}) {\n return testFile(file).pipe(\n switchMap((fileOptions) => {\n return concat(\n of({type: 'file' as const, file: fileOptions}),\n testSecretsObservable(client).pipe(\n switchMap((json) => {\n if (!json || !json.status) {\n return throwError(() => new Error('Invalid credentials'))\n }\n const uuid = generateUuid()\n const body = settings\n sanitizeOverlaySettingsInPlace(body)\n\n return concat(\n of({type: 'uuid' as const, uuid}),\n defer(() =>\n getMuxAddonClient(client).observable.request<{\n sanityAssetId: string\n upload: {\n cors_origin: string\n id: string\n new_asset_settings: MuxNewAssetSettings\n status: 'waiting'\n timeout: number\n url: string\n }\n }>({\n url: `/addons/mux/uploads/${client.config().dataset}`,\n withCredentials: true,\n method: 'POST',\n headers: {\n 'MUX-Proxy-UUID': uuid,\n 'Content-Type': 'application/json',\n },\n body,\n query: PLUGIN_VERSION_QUERY,\n }),\n ).pipe(\n mergeMap((result) => {\n return createUpChunkObservable(uuid, result.upload.url, file).pipe(\n // @TODO type the observable events\n mergeMap((event) => {\n if (event.type !== 'success') {\n return of(event)\n }\n return from(updateAssetDocumentFromUpload(client, uuid, watermark)).pipe(\n mergeMap((doc) => of({...event, asset: doc})),\n )\n }),\n catchError((err) => {\n // Delete asset document\n return cancelUpload(client, uuid).pipe(mergeMap(() => throwError(() => err)))\n }),\n )\n }),\n ),\n )\n }),\n ),\n )\n }),\n )\n}\n\ntype UploadResponse = {\n data: {\n asset_id: string\n cors_origin: string\n id: string\n new_asset_settings: {\n static_renditions?: {resolution: string}[]\n passthrough: string\n playback_policies: ['public' | 'signed' | 'drm']\n }\n status: string\n timeout: number\n }\n}\nfunction getUpload(client: SanityClient, assetId: string) {\n const {dataset} = client.config()\n return getMuxAddonClient(client).request<UploadResponse>({\n url: `/addons/mux/uploads/${dataset}/${assetId}`,\n withCredentials: true,\n method: 'GET',\n query: PLUGIN_VERSION_QUERY,\n })\n}\n\nfunction pollUpload(client: SanityClient, uuid: string): Promise<UploadResponse> {\n const maxTries = 10\n let pollInterval: number\n let tries = 0\n let assetId: string\n let upload: UploadResponse\n return new Promise((resolve, reject) => {\n pollInterval = (setInterval as typeof window.setInterval)(async () => {\n try {\n upload = await getUpload(client, uuid)\n } catch (err) {\n reject(err)\n return\n }\n assetId = upload && upload.data && upload.data.asset_id\n if (assetId) {\n clearInterval(pollInterval)\n resolve(upload)\n }\n if (tries > maxTries) {\n clearInterval(pollInterval)\n reject(new Error('Upload did not finish'))\n }\n tries++\n }, 2000)\n })\n}\n\nasync function updateAssetDocumentFromUpload(\n client: SanityClient,\n uuid: string,\n _watermark?: WatermarkConfig,\n) {\n let upload: UploadResponse\n let asset: {data: MuxAsset}\n try {\n upload = await pollUpload(client, uuid)\n } catch (err) {\n return Promise.reject(err)\n }\n try {\n asset = await getAsset(client, upload.data.asset_id)\n } catch (err) {\n return Promise.reject(err)\n }\n\n const doc = {\n _id: uuid,\n _type: 'mux.videoAsset',\n status: asset.data.status,\n data: asset.data,\n assetId: asset.data.id,\n playbackId: asset.data.playback_ids[0]?.id,\n uploadId: upload.data.id,\n }\n return client.createOrReplace(doc).then(() => {\n return doc\n })\n}\n\nfunction testFile(file: File) {\n if (typeof window !== 'undefined' && file instanceof window.File) {\n const fileOptions = optionsFromFile({}, file)\n return of(fileOptions)\n }\n return throwError(() => new Error('Invalid file'))\n}\n\nfunction testUrl(url: string): Observable<string> {\n const error = new Error('Invalid URL')\n if (typeof url !== 'string') {\n return throwError(() => error)\n }\n let formattedUrl = url.trim()\n formattedUrl = formatDriveShareLink(formattedUrl)\n let parsed\n try {\n parsed = new URL(formattedUrl)\n } catch {\n return throwError(() => error)\n }\n if (parsed && !parsed.protocol.match(/http:|https:/)) {\n return throwError(() => error)\n }\n return of(formattedUrl)\n}\n\nfunction optionsFromFile(opts: {preserveFilename?: boolean}, file: File) {\n if (typeof window === 'undefined' || !(file instanceof window.File)) {\n return undefined\n }\n return {\n name: opts.preserveFilename === false ? undefined : file.name,\n type: file.type,\n }\n}\n","import type {ServerError} from '@sanity/client'\n\nexport function isValidUrl(url: string): boolean {\n try {\n const parsed = new URL(url)\n return parsed && !!parsed.protocol.match(/http:|https:/)\n } catch {\n return false\n }\n}\n\n/**\n * We consider a server error one with status code 5XX.\n * Used mainly to handle unknown Proxy issues.\n */\nexport function isServerError(error: Error): error is ServerError {\n return (\n 'statusCode' in error &&\n typeof error.statusCode === 'number' &&\n 500 <= error.statusCode &&\n error.statusCode <= 600\n )\n}\n","/**\n * Utilities for extracting files from dataTransfer in a predictable cross-browser fashion.\n * Also recursively extracts files from a directory\n * Inspired by https://github.com/component/normalized-upload\n */\n\nexport function extractDroppedFiles(dataTransfer: DataTransfer) {\n const files = Array.from(dataTransfer.files || [])\n const items = Array.from(dataTransfer.items || [])\n if (files && files.length > 0) {\n return Promise.resolve(files)\n }\n return normalizeItems(items).then((arr) => arr.flat())\n}\n\nfunction normalizeItems(items: DataTransferItem[]) {\n return Promise.all(\n items.map((item) => {\n // directory\n if (item.kind === 'file' && item.webkitGetAsEntry) {\n let entry: FileSystemEntry | File[] | null\n // Edge throws\n try {\n entry = item.webkitGetAsEntry()\n } catch {\n return [item.getAsFile()]\n }\n if (!entry) {\n return []\n }\n return entry.isDirectory ? walk(entry) : [item.getAsFile()]\n }\n\n // file\n if (item.kind === 'file') {\n const file = item.getAsFile()\n return Promise.resolve(file ? [file] : [])\n }\n\n // others\n return new Promise((resolve) => item.getAsString(resolve)).then((str?: any) =>\n str ? [new File([str], 'unknown.txt', {type: item.type})] : [],\n )\n }),\n )\n}\n\nfunction isFile(entry: FileSystemEntry): entry is FileSystemFileEntry {\n return entry.isFile\n}\nfunction isDirectory(entry: FileSystemEntry): entry is FileSystemDirectoryEntry {\n return entry.isDirectory\n}\n\nfunction walk(entry: FileSystemEntry): any {\n if (isFile(entry)) {\n return new Promise((resolve) => entry.file(resolve)).then((file) => [file])\n }\n\n if (isDirectory(entry)) {\n const dir = entry.createReader()\n return new Promise<any>((resolve) => dir.readEntries(resolve))\n .then((entries: FileSystemEntry[]) => entries.filter((entr) => !entr.name.startsWith('.')))\n .then((entries) => Promise.all(entries.map(walk)).then((arr) => arr.flat()))\n }\n return Promise.resolve([])\n}\n","import {useCallback} from 'react'\nimport {PatchEvent, set, setIfMissing, unset} from 'sanity'\n\nimport type {SetDialogState} from '../hooks/useDialogState'\nimport type {MuxInputProps, PluginConfig, VideoAssetDocument} from '../util/types'\nimport VideosBrowser, {type VideosBrowserProps} from './VideosBrowser'\n\nexport interface Props extends Pick<MuxInputProps, 'onChange'> {\n asset?: VideoAssetDocument | null | undefined\n setDialogState: SetDialogState\n config: PluginConfig\n}\n\nexport default function SelectAssets({\n asset: selectedAsset,\n onChange,\n setDialogState,\n config,\n}: Props) {\n const handleSelect = useCallback<Required<VideosBrowserProps>['onSelect']>(\n (chosenAsset) => {\n if (!chosenAsset?._id) {\n onChange(PatchEvent.from([unset(['asset'])]))\n }\n if (chosenAsset._id !== selectedAsset?._id) {\n onChange(\n PatchEvent.from([\n setIfMissing({asset: {}, _type: 'mux.video'}),\n set({_type: 'reference', _weak: true, _ref: chosenAsset._id}, ['asset']),\n ]),\n )\n }\n setDialogState(false)\n },\n [onChange, setDialogState, selectedAsset],\n )\n\n return <VideosBrowser onSelect={handleSelect} config={config} />\n}\n","import {Dialog} from '@sanity/ui'\nimport {useCallback, useId} from 'react'\nimport {styled} from 'styled-components'\n\nimport type {SetDialogState} from '../hooks/useDialogState'\nimport SelectAsset, {type Props as SelectAssetProps} from './SelectAsset'\n\n/** To prevent Content Layout Shift (CLS), ensure that the dialog always occupies the entire available height. */\nconst StyledDialog = styled(Dialog)`\n > div[data-ui='DialogCard'] > div[data-ui='Card'] {\n height: 100%;\n }\n`\n\nexport default function InputBrowser({\n setDialogState,\n asset,\n onChange,\n config,\n}: Pick<SelectAssetProps, 'onChange' | 'asset' | 'config'> & {\n setDialogState: SetDialogState\n}) {\n const id = `InputBrowser${useId()}`\n const handleClose = useCallback(() => setDialogState(false), [setDialogState])\n return (\n <StyledDialog\n __unstable_autoFocus\n header=\"Select video\"\n id={id}\n onClose={handleClose}\n width={2}\n >\n <SelectAsset\n config={config}\n asset={asset}\n onChange={onChange}\n setDialogState={setDialogState}\n />\n </StyledDialog>\n )\n}\n","import {useCallback} from 'react'\nimport {PatchEvent, unset} from 'sanity'\n\nimport {deleteAssetOnMux} from '../actions/assets'\nimport {useClient} from '../hooks/useClient'\nimport type {MuxInputProps, VideoAssetDocument} from '../util/types'\n\nexport const useCancelUpload = (asset: VideoAssetDocument, onChange: MuxInputProps['onChange']) => {\n const client = useClient()\n return useCallback(() => {\n if (!asset) {\n return\n }\n onChange(PatchEvent.from(unset()))\n if (asset.assetId) {\n void deleteAssetOnMux(client, asset.assetId)\n }\n if (asset._id) {\n void client.delete(asset._id)\n }\n }, [asset, client, onChange])\n}\n","import {styled} from 'styled-components'\n\nexport const TopControls = styled.div`\n position: absolute;\n top: 0;\n right: 0;\n justify-content: flex-end;\n button {\n height: auto;\n }\n`\n","// Lifted from sanity/form/inputs/files/common/UploadProgress\n\nimport {Button, Card, Flex, Inline, Stack, Text} from '@sanity/ui'\nimport {Code} from '@sanity/ui/code'\nimport {LinearProgress} from 'sanity'\nimport {styled} from 'styled-components'\n\nconst CardWrapper = styled(Card)`\n min-height: 82px;\n box-sizing: border-box;\n`\n\nconst FlexWrapper = styled(Flex)`\n text-overflow: ellipsis;\n overflow: hidden;\n`\n\nconst LeftSection = styled(Stack)`\n position: relative;\n width: 60%;\n`\n\nconst CodeWrapper = styled(Code)`\n position: relative;\n width: 100%;\n\n code {\n overflow: hidden;\n text-overflow: ellipsis;\n position: relative;\n max-width: 200px;\n }\n`\n\nexport const UploadProgress = ({\n progress = 100,\n onCancel,\n filename,\n text = 'Uploading',\n}: {\n progress: number\n filename?: React.ReactNode\n onCancel?: React.MouseEventHandler<HTMLButtonElement>\n text?: React.ReactNode\n}) => {\n // Disable cancel button when upload is 90% or more complete\n // to prevent inconsistency between Mux and Sanity\n const isCancelDisabled = progress >= 90\n\n return (\n <CardWrapper tone=\"primary\" padding={4} border height=\"fill\">\n <FlexWrapper align=\"center\" justify=\"space-between\" height=\"fill\" direction=\"row\" gap={2}>\n <LeftSection>\n <Flex justify=\"center\" gap={[3, 3, 2, 2]} direction={['column', 'column', 'row']}>\n <Text size={1}>\n <Inline gap={2}>\n {text}\n <CodeWrapper size={1}>{filename ? filename : '...'}</CodeWrapper>\n </Inline>\n </Text>\n </Flex>\n\n <Card marginTop={3} radius={5} shadow={1}>\n <LinearProgress value={progress} />\n </Card>\n </LeftSection>\n\n {onCancel ? (\n <Button\n fontSize={2}\n text=\"Cancel upload\"\n mode=\"ghost\"\n tone=\"critical\"\n onClick={onCancel}\n disabled={isCancelDisabled}\n />\n ) : null}\n </FlexWrapper>\n </CardWrapper>\n )\n}\n","import {Card, Text} from '@sanity/ui'\nimport {useEffect, useMemo, useRef} from 'react'\n\nimport {useCancelUpload} from '../hooks/useCancelUpload'\nimport type {MuxInputProps, PluginConfig, VideoAssetDocument} from '../util/types'\nimport {TopControls} from './Player.styled'\nimport {UploadProgress} from './UploadProgress'\nimport VideoPlayer from './VideoPlayer'\n\ninterface Props extends Pick<MuxInputProps, 'onChange' | 'readOnly'> {\n buttons?: React.ReactNode\n asset: VideoAssetDocument\n config?: PluginConfig\n}\n\nconst Player = ({asset, buttons, readOnly, onChange, config}: Props) => {\n const isLoading = useMemo<boolean | string>(() => {\n if (asset?.status === 'preparing') {\n return 'Preparing the video'\n }\n if (asset?.status === 'waiting_for_upload') {\n return 'Waiting for upload to start'\n }\n if (asset?.status === 'waiting') {\n return 'Processing upload'\n }\n if (asset?.status === 'ready') {\n return false\n }\n if (typeof asset?.status === 'undefined') {\n return false\n }\n\n return true\n }, [asset])\n const isPreparingStaticRenditions = useMemo<boolean>(() => {\n // Legacy: If static_renditions has a status field, it was created with mp4_support (deprecated)\n // We don't process this old format, just return false\n // Note: 'disabled' status is valid in the new format when no renditions were requested\n if (\n asset?.data?.static_renditions?.status &&\n asset?.data?.static_renditions?.status !== 'disabled'\n ) {\n return false\n }\n\n // Check if any file in static_renditions is still preparing\n const files = asset?.data?.static_renditions?.files\n if (!files || files.length === 0) {\n return false\n }\n return files.some((file) => file.status === 'preparing')\n // oxlint-disable-next-line react/preserve-manual-memoization\n }, [asset?.data?.static_renditions?.status, asset?.data?.static_renditions?.files])\n const playRef = useRef<HTMLDivElement>(null)\n const muteRef = useRef<HTMLDivElement>(null)\n const handleCancelUpload = useCancelUpload(asset, onChange)\n\n useEffect(() => {\n const style = document.createElement('style')\n style.innerHTML = 'button svg { vertical-align: middle; }'\n\n if (playRef.current?.shadowRoot) {\n playRef.current.shadowRoot.appendChild(style)\n }\n if (muteRef?.current?.shadowRoot) {\n muteRef.current.shadowRoot.appendChild(style.cloneNode(true))\n }\n }, [])\n\n useEffect(() => {\n if (asset?.status === 'errored') {\n handleCancelUpload()\n // @TODO use better error handling\n throw new Error(asset.data?.errors?.messages?.join(' '))\n }\n }, [asset.data?.errors?.messages, asset?.status, handleCancelUpload])\n\n if (!asset || !asset.status) {\n return null\n }\n\n if (isLoading) {\n return (\n <UploadProgress\n progress={100}\n filename={asset?.filename}\n text={(isLoading !== true && isLoading) || 'Waiting for Mux to complete the upload'}\n onCancel={readOnly ? undefined : () => handleCancelUpload()}\n />\n )\n }\n\n return (\n <VideoPlayer asset={asset} hlsConfig={config?.hlsConfig}>\n {buttons && <TopControls slot=\"top-chrome\">{buttons}</TopControls>}\n {isPreparingStaticRenditions && (\n <Card\n padding={2}\n radius={1}\n style={{\n background: 'var(--card-fg-color)',\n position: 'absolute',\n top: '0.5em',\n left: '0.5em',\n }}\n >\n <Text size={1} style={{color: 'var(--card-bg-color)'}}>\n MUX is preparing static renditions, please stand by\n </Text>\n </Card>\n )}\n </VideoPlayer>\n )\n}\n\nexport default Player\n","// todo: get these utils from @sanity/ui instead\nexport function focusRingBorderStyle(border: {color: string; width: number}): string {\n return `inset 0 0 0 ${border.width}px ${border.color}`\n}\n\nexport function focusRingStyle(opts: {\n base?: {bg: string}\n border?: {color: string; width: number}\n focusRing: {offset: number; width: number}\n}): string {\n const {base, border, focusRing} = opts\n const focusRingOutsetWidth = focusRing.offset + focusRing.width\n const focusRingInsetWidth = 0 - focusRing.offset\n const bgColor = base ? base.bg : 'var(--card-bg-color)'\n\n return [\n focusRingInsetWidth > 0 && `inset 0 0 0 ${focusRingInsetWidth}px var(--card-focus-ring-color)`,\n border && focusRingBorderStyle(border),\n focusRingInsetWidth < 0 && `0 0 0 ${0 - focusRingInsetWidth}px ${bgColor}`,\n focusRingOutsetWidth > 0 && `0 0 0 ${focusRingOutsetWidth}px var(--card-focus-ring-color)`,\n ]\n .filter(Boolean)\n .join(',')\n}\n","import {MenuItem} from '@sanity/ui/menu'\nimport {css, styled} from 'styled-components'\n\nimport {focusRingStyle} from './withFocusRing/helpers'\n\nexport const FileButton = styled(MenuItem)(({theme}) => {\n // oxlint-disable-next-line no-deprecated -- deferred to a follow-up PR\n const {focusRing} = theme.sanity\n // oxlint-disable-next-line no-deprecated -- deferred to a follow-up PR\n const base = theme.sanity.color.base\n const border = {width: 1, color: 'var(--card-border-color)'}\n\n return css`\n position: relative;\n\n &:not([data-disabled='true']) {\n &:focus-within {\n box-shadow: ${focusRingStyle({base, border, focusRing})};\n }\n }\n\n & input {\n overflow: hidden;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n position: absolute;\n min-width: 0;\n display: block;\n appearance: none;\n padding: 0;\n margin: 0;\n border: 0;\n opacity: 0;\n }\n `\n})\n","import {Box, type ButtonProps, Flex, Text} from '@sanity/ui'\nimport {isValidElement, useId, useCallback} from 'react'\nimport {isValidElementType} from 'react-is'\n\nimport {FileButton} from './FileInputMenuItem.styled'\n\nexport interface FileInputMenuItemProps extends Omit<ButtonProps, 'onSelect'> {\n accept?: string\n capture?: 'user' | 'environment'\n multiple?: boolean\n onSelect?: (files: File[]) => void\n disabled?: boolean\n}\n\nexport function FileInputMenuItem(\n props: FileInputMenuItemProps &\n Omit<React.HTMLProps<HTMLButtonElement>, 'as' | 'ref' | 'type' | 'value' | 'onSelect'> & {\n ref?: React.Ref<HTMLInputElement>\n },\n) {\n const {\n icon: Icon,\n id: idProp,\n accept,\n capture,\n fontSize,\n multiple,\n onSelect,\n gap = 3,\n textAlign,\n text,\n disabled,\n ref,\n ...rest\n } = props\n const idHook = useId()\n const id = idProp || idHook\n\n const handleChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n if (onSelect && event.target.files) {\n onSelect(Array.from(event.target.files))\n }\n },\n [onSelect],\n )\n\n const content = (\n <Flex align=\"center\" justify=\"flex-start\">\n {/* Icon */}\n {Icon && (\n <Box marginRight={text ? gap : undefined}>\n <Text size={fontSize}>\n {isValidElement(Icon) && Icon}\n {isValidElementType(Icon) && <Icon />}\n </Text>\n </Box>\n )}\n\n {/* Text */}\n {text && (\n <Text align={textAlign} size={fontSize} textOverflow=\"ellipsis\">\n {text}\n </Text>\n )}\n </Flex>\n )\n\n return (\n <FileButton {...rest} htmlFor={id} disabled={disabled} ref={ref}>\n {content}\n\n {/* Visibly hidden input */}\n <input\n data-testid=\"file-button-input\"\n accept={accept}\n capture={capture}\n id={id}\n multiple={multiple}\n onChange={handleChange}\n type=\"file\"\n value=\"\"\n disabled={disabled}\n />\n </FileButton>\n )\n}\n","import {DownloadIcon} from '@sanity/icons/Download'\nimport {EllipsisHorizontalIcon} from '@sanity/icons/EllipsisHorizontal'\nimport {ImageIcon} from '@sanity/icons/Image'\nimport {LockIcon} from '@sanity/icons/Lock'\nimport {PlugIcon} from '@sanity/icons/Plug'\nimport {ResetIcon} from '@sanity/icons/Reset'\nimport {SearchIcon} from '@sanity/icons/Search'\nimport {SyncIcon} from '@sanity/icons/Sync'\nimport {TranslateIcon} from '@sanity/icons/Translate'\nimport {UploadIcon} from '@sanity/icons/Upload'\nimport {Box, Button, Card, Inline, Label, Text, useClickOutsideEvent} from '@sanity/ui'\nimport {Menu, MenuDivider, MenuItem} from '@sanity/ui/menu'\nimport {Popover} from '@sanity/ui/popover'\nimport {Tooltip} from '@sanity/ui/tooltip'\nimport {memo, useCallback, useEffect, useMemo, useState} from 'react'\nimport {PatchEvent, unset} from 'sanity'\nimport {styled} from 'styled-components'\n\nimport {useAccessControl} from '../hooks/useAccessControl'\nimport {type DialogState, type SetDialogState} from '../hooks/useDialogState'\nimport {useResyncAsset} from '../hooks/useResyncAsset'\nimport {getPlaybackPolicy} from '../util/getPlaybackPolicy'\nimport type {MuxInputProps, PluginConfig, VideoAssetDocument} from '../util/types'\nimport {FileInputMenuItem} from './FileInputMenuItem'\n\nconst LockCard = styled(Card)`\n position: absolute;\n top: 0;\n left: 0;\n opacity: 0.6;\n mix-blend-mode: screen;\n background: transparent;\n`\n\nconst LockButton = styled(Button)`\n background: transparent;\n color: white;\n`\n\n// @TODO: add support for audio type (asset._type) when uploading an audio file so we can hide the thumbnail option.\nconst isVideoAsset = (asset: VideoAssetDocument) => {\n return asset._type === 'mux.videoAsset'\n}\n\nfunction PlayerActionsMenu(\n props: Pick<MuxInputProps, 'onChange' | 'readOnly'> & {\n asset: VideoAssetDocument\n onSelect: (files: File[]) => void\n dialogState: DialogState\n setDialogState: SetDialogState\n config: PluginConfig\n accept: string\n },\n) {\n const {asset, readOnly, dialogState, setDialogState, onChange, onSelect, accept} = props\n const [open, setOpen] = useState(false)\n const [menuElement, setMenuRef] = useState<HTMLDivElement | null>(null)\n const isSigned = useMemo(() => getPlaybackPolicy(asset)?.policy === 'signed', [asset])\n const {hasConfigAccess} = useAccessControl(props.config)\n const {resyncAsset, isResyncing} = useResyncAsset({showToast: true})\n\n const onReset = useCallback(() => onChange(PatchEvent.from(unset([]))), [onChange])\n\n const handleResync = useCallback(async () => {\n setOpen(false)\n await resyncAsset(asset)\n }, [resyncAsset, asset])\n\n useEffect(() => {\n if (open && dialogState) {\n // oxlint-disable-next-line react/set-state-in-effect\n setOpen(false)\n }\n }, [dialogState, open])\n\n useClickOutsideEvent(\n () => setOpen(false),\n () => [menuElement],\n )\n\n return (\n <Inline gap={1} padding={2}>\n {isSigned && (\n <Tooltip\n animate\n content={\n <Box padding={2}>\n <Text muted size={1}>\n Signed playback policy\n </Text>\n </Box>\n }\n placement=\"right\"\n portal\n >\n <LockCard radius={2} margin={2} scheme=\"dark\" tone=\"positive\">\n <LockButton icon={LockIcon} mode=\"bleed\" tone=\"positive\" />\n </LockCard>\n </Tooltip>\n )}\n <Popover\n animate\n content={\n <Menu ref={setMenuRef}>\n <Box padding={2}>\n <Label muted size={1}>\n Replace\n </Label>\n </Box>\n <FileInputMenuItem\n accept={accept}\n icon={UploadIcon}\n onSelect={onSelect}\n text=\"Upload\"\n disabled={readOnly}\n fontSize={1}\n />\n <MenuItem\n icon={SearchIcon}\n text=\"Browse\"\n onClick={() => setDialogState('select-video')}\n />\n {isVideoAsset(asset) && (\n <>\n <MenuItem\n icon={ImageIcon}\n text=\"Thumbnail\"\n onClick={() => setDialogState('edit-thumbnail')}\n />\n <MenuItem\n icon={TranslateIcon}\n text=\"Captions\"\n onClick={() => setDialogState('edit-captions')}\n />\n <MenuItem\n icon={SyncIcon}\n text=\"Resync from Mux\"\n onClick={handleResync}\n disabled={readOnly || isResyncing}\n />\n </>\n )}\n <MenuDivider />\n <MenuItem\n icon={DownloadIcon}\n text=\"Mezzanine\"\n onClick={() => setDialogState('mezzanine')}\n />\n <MenuDivider />\n {hasConfigAccess && (\n <>\n <MenuItem\n icon={PlugIcon}\n text=\"Configure API\"\n onClick={() => setDialogState('secrets')}\n />\n <MenuDivider />\n </>\n )}\n <MenuItem\n tone=\"critical\"\n icon={ResetIcon}\n text=\"Clear field\"\n onClick={onReset}\n disabled={readOnly}\n />\n </Menu>\n }\n portal\n open={open}\n >\n <Button\n icon={EllipsisHorizontalIcon}\n mode=\"ghost\"\n fontSize={1}\n onClick={() => {\n setDialogState(false)\n setOpen(true)\n }}\n />\n </Popover>\n </Inline>\n )\n}\n\nexport default memo(PlayerActionsMenu)\n","import {useEffect, useState} from 'react'\n\nimport {type StagedUpload} from '../components/Uploader'\n\nexport function useFetchFileSize(stagedUpload: StagedUpload, maxFileSize?: number) {\n const [fileSize, setFileSize] = useState<number | null>(null)\n const [isLoadingFileSize, setIsLoadingFileSize] = useState(false)\n const [canSkipFileSizeValidation, setCanSkipFileSizeValidation] = useState(false)\n\n useEffect(() => {\n // Fetch URL Upload file size\n if (stagedUpload.type === 'url') {\n // oxlint-disable-next-line react/set-state-in-effect\n setIsLoadingFileSize(false)\n setCanSkipFileSizeValidation(false)\n setFileSize(null)\n const url = stagedUpload.url\n\n // Get file size from URL\n const fetchFileSize = async () => {\n setIsLoadingFileSize(true)\n try {\n const response = await fetch(url, {method: 'HEAD'})\n const contentLength = response.headers.get('content-length')\n const newFileSize = contentLength ? parseInt(contentLength, 10) : null\n\n setIsLoadingFileSize(false)\n if (newFileSize) {\n setFileSize(newFileSize)\n }\n if (newFileSize === null && maxFileSize !== undefined) {\n // Size unknown but size limit is configured - skip file size validation\n setCanSkipFileSizeValidation(true)\n }\n } catch {\n console.warn('Could not validate file size from URL')\n // Skip validation of file size, but still validate duration\n setCanSkipFileSizeValidation(true)\n setIsLoadingFileSize(false)\n }\n }\n\n void fetchFileSize()\n }\n if (stagedUpload.type === 'file') {\n setFileSize(stagedUpload.files[0]!.size)\n }\n }, [maxFileSize, stagedUpload, stagedUpload.type])\n\n return {\n fileSize,\n isLoadingFileSize,\n canSkipFileSizeValidation,\n }\n}\n","import {useEffect, useState} from 'react'\n\nimport {type StagedUpload} from '../components/Uploader'\n\nexport interface VideoAssetMetadata {\n width?: number\n height?: number\n isAudioOnly?: boolean\n duration?: number\n size?: number\n aspectRatio?: number\n}\n\nexport function useMediaMetadata(stagedUpload: StagedUpload) {\n const [videoAssetMetadata, setVideoAssetMetadata] = useState<VideoAssetMetadata | null>(null)\n const [isLoadingMetadata, setIsLoadingMetadata] = useState(false)\n useEffect(() => {\n let videoSrc = null\n // Validate file uploads\n if (stagedUpload.type === 'file') {\n const file = stagedUpload.files[0]\n videoSrc = URL.createObjectURL(file!)\n }\n\n // Validate URL uploads\n if (stagedUpload.type === 'url') {\n videoSrc = stagedUpload.url\n }\n\n // oxlint-disable-next-line react/set-state-in-effect\n setVideoAssetMetadata((old) => ({\n ...old,\n duration: undefined,\n width: undefined,\n height: undefined,\n }))\n\n if (!videoSrc) return () => null\n\n setIsLoadingMetadata(true)\n const videoElement = document.createElement('video')\n videoElement.preload = 'metadata'\n\n const metadataListeners = [\n () => {\n setIsLoadingMetadata(false)\n },\n () => {\n const duration = videoElement.duration\n const width = videoElement.videoWidth\n const height = videoElement.videoHeight\n const isAudioOnly = width <= 0 && height <= 0\n const aspectRatio = width / height\n setVideoAssetMetadata((old) => {\n return {\n ...old,\n duration: duration,\n width: width,\n height: height,\n isAudioOnly: isAudioOnly,\n aspectRatio: aspectRatio,\n }\n })\n },\n ]\n\n const cleanupVideo = (videoEl: HTMLVideoElement) => {\n const currentVideoSrc = videoEl?.src\n if (videoEl) {\n metadataListeners.forEach((listener) =>\n videoEl.removeEventListener('loadedmetadata', listener),\n )\n videoEl.onerror = null\n videoEl.src = ''\n videoEl.load()\n }\n if (currentVideoSrc?.startsWith('blob:')) {\n URL.revokeObjectURL(currentVideoSrc)\n }\n }\n metadataListeners.push(() => setTimeout(() => cleanupVideo(videoElement), 0))\n\n videoElement.onerror = () => {\n setIsLoadingMetadata(false)\n console.warn('Could not read video metadata for validation')\n cleanupVideo(videoElement)\n }\n\n metadataListeners.forEach((listener) =>\n videoElement.addEventListener('loadedmetadata', listener),\n )\n videoElement.src = videoSrc\n\n return () => {\n cleanupVideo(videoElement)\n }\n }, [stagedUpload.type, stagedUpload])\n\n return {\n videoAssetMetadata,\n setVideoAssetMetadata,\n isLoadingMetadata,\n }\n}\n","import {roundPxString} from './roundPxString'\nimport type {MuxOverlaySettings, WatermarkConfig} from './types'\n\n/**\n * Converts a draggable watermark position (x, y percentages) to Mux's overlay_settings format.\n *\n * @param watermark - The watermark configuration with position, size, and opacity\n * @returns Mux overlay_settings object\n * @see {@link https://www.mux.com/docs/guides/add-watermarks-to-your-videos}\n */\nexport function convertWatermarkToMuxOverlay(\n watermark: WatermarkConfig,\n options?: {\n /**\n * Video aspect ratio (width / height). Needed for correct vertical positioning,\n * especially on vertical videos.\n */\n videoAspectRatio?: number\n /**\n * Unit to emit for margins/width when generating overlay_settings from Canvas mode.\n * - 'px' will generate pixel strings according to Mux's scaling rules:\n * values are applied as if the video were scaled to 1920x1080 (horizontal)\n * or 1080x1920 (vertical).\n * - '%' preserves existing behavior.\n */\n units?: '%' | 'px'\n },\n): MuxOverlaySettings | null {\n if (!watermark.enabled || !watermark.imageUrl) {\n return null\n }\n\n const size = watermark.size || 20\n const opacity = watermark.opacity ?? 0.7\n\n /**\n * Convert a percentage to whole-pixel string, using Mux's base dimensions:\n * - Horizontal video: 1920x1080\n * - Vertical video: 1080x1920\n */\n const toPxString = (valuePercent: number, axis: 'x' | 'y') => {\n const videoAspectRatio = options?.videoAspectRatio ?? 16 / 9\n const isVertical = videoAspectRatio > 0 && videoAspectRatio < 1\n const baseW = isVertical ? 1080 : 1920\n const baseH = isVertical ? 1920 : 1080\n const base = axis === 'x' ? baseW : baseH\n const px = (valuePercent / 100) * base\n let rounded = Math.round(px)\n // Avoid sending 0px (and JS -0); keep sign for negative margins.\n if (rounded === 0) rounded = px < 0 ? -1 : 1\n return `${rounded}px`\n }\n\n const normalizeToPixels = (value: string | undefined, axis: 'x' | 'y'): string | undefined => {\n if (!value) return value\n const trimmed = value.trim()\n if (trimmed.endsWith('px')) {\n return roundPxString(trimmed)\n }\n if (trimmed.endsWith('%')) {\n const n = Number(trimmed.slice(0, -1))\n if (!Number.isFinite(n)) return value\n return toPxString(n, axis)\n }\n return value\n }\n\n // If user provided explicit overlay settings, use them (Mux-documented format).\n // When `options.units === 'px'`, we normalize both % and px to whole-pixel strings,\n // honoring vertical vs horizontal video bases.\n if (watermark.overlay_settings) {\n const widthValue = watermark.overlay_settings.width\n const widthNormalized =\n options?.units === 'px' ? normalizeToPixels(widthValue, 'x') : widthValue\n return {\n ...watermark.overlay_settings,\n horizontal_margin:\n options?.units === 'px'\n ? (normalizeToPixels(watermark.overlay_settings.horizontal_margin, 'x') ??\n watermark.overlay_settings.horizontal_margin)\n : watermark.overlay_settings.horizontal_margin,\n vertical_margin:\n options?.units === 'px'\n ? (normalizeToPixels(watermark.overlay_settings.vertical_margin, 'y') ??\n watermark.overlay_settings.vertical_margin)\n : watermark.overlay_settings.vertical_margin,\n width: widthNormalized ?? `${size}%`,\n opacity: watermark.overlay_settings.opacity ?? `${Math.round(opacity * 100)}%`,\n }\n }\n\n const position = watermark.position || {x: 50, y: 50}\n\n /**\n * Our UI stores watermark position as the *center point* in percentages.\n * Mux margins are interpreted relative to an *edge* (based on align).\n *\n * To make \"corner\" placements match what the user dragged, we convert from\n * center-position to top-left margins by subtracting half the watermark size.\n *\n * Note: `size` is a percentage of video width. Mux `width` is also expressed\n * as a percentage of the video width, so we can reuse it for horizontal math.\n * For vertical math, we approximate using the same percentage to keep behavior\n * consistent with the current draggable UI (which also uses `size` in both axes\n * for bounds).\n */\n // Allow negative margins to compensate for rounding / letterboxing edge-cases.\n // We still clamp to a sane range so values don't explode.\n const clampPercent = (value: number) => Math.max(-100, Math.min(100, value))\n\n // Mux accepts percentage strings; avoid sending an exact \"0%\" by nudging to 0.01%.\n // This also handles the JS -0 edge case and tiny floating point remnants.\n const toPercentString = (value: number) => {\n const epsilon = 1e-9\n const isZeroish = value === 0 || Object.is(value, -0) || Math.abs(value) < epsilon\n return `${isZeroish ? 0.01 : value}%`\n }\n\n const watermarkWidthPercentOfVideoWidth = size\n\n /**\n * Convert watermark height into % of video height.\n * height% = (watermarkWidthPx / imageAspectRatio) / videoHeightPx\n * = (size% * videoWidthPx / imageAspectRatio) / videoHeightPx\n * = size% * (videoWidthPx/videoHeightPx) / imageAspectRatio\n * = size% * videoAspectRatio / imageAspectRatio\n */\n const videoAspectRatio = options?.videoAspectRatio ?? 16 / 9\n const imageAspectRatio = watermark.imageAspectRatio ?? 1\n const watermarkHeightPercentOfVideoHeight = Math.max(\n 0,\n Math.min(100, (size * videoAspectRatio) / imageAspectRatio),\n )\n\n const halfWidth = watermarkWidthPercentOfVideoWidth / 2\n const halfHeight = watermarkHeightPercentOfVideoHeight / 2\n\n const leftMargin = clampPercent(\n Math.min(position.x - halfWidth, 100 - watermarkWidthPercentOfVideoWidth),\n )\n const topMargin = clampPercent(\n Math.min(position.y - halfHeight, 100 - watermarkHeightPercentOfVideoHeight),\n )\n\n const units = options?.units ?? '%'\n const marginX = units === 'px' ? toPxString(leftMargin, 'x') : toPercentString(leftMargin)\n const marginY = units === 'px' ? toPxString(topMargin, 'y') : toPercentString(topMargin)\n const width = units === 'px' ? toPxString(size, 'x') : `${size}%`\n\n const overlaySettings: MuxOverlaySettings = {\n vertical_align: 'top',\n vertical_margin: marginY,\n horizontal_align: 'left',\n horizontal_margin: marginX,\n width,\n opacity: `${Math.round(opacity * 100)}%`,\n }\n\n return overlaySettings\n}\n","// From: https://stackoverflow.com/questions/10420352/converting-file-size-in-bytes-to-human-readable-string\n/**\n * Format bytes as human-readable text.\n *\n * @param bytes Number of bytes.\n * @param si True to use metric (SI) units, aka powers of 1000. False to use\n * binary (IEC), aka powers of 1024.\n * @param dp Number of decimal places to display.\n *\n * @return Formatted string.\n */\nexport default function formatBytes(bytes: number, si = false, dp = 1) {\n const thresh = si ? 1000 : 1024\n\n if (Math.abs(bytes) < thresh) {\n return bytes + ' B'\n }\n\n const units = si\n ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']\n : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']\n let u = -1\n const r = 10 ** dp\n\n do {\n bytes /= thresh\n ++u\n } while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1)\n\n return bytes.toFixed(dp) + ' ' + units[u]\n}\n","import {CheckmarkCircleIcon} from '@sanity/icons/CheckmarkCircle'\nimport {ErrorOutlineIcon} from '@sanity/icons/ErrorOutline'\nimport {Box, Button, Card, Flex, Grid, Stack, Text, TextInput} from '@sanity/ui'\nimport {useCallback, useEffect, useRef, useState} from 'react'\nimport {styled} from 'styled-components'\n\nimport {convertWatermarkToMuxOverlay} from '../util/convertWatermarkToMux'\nimport type {MuxOverlaySettings, WatermarkConfig} from '../util/types'\n\nconst RangeInput = styled.input`\n width: 100%;\n height: 4px;\n border-radius: 2px;\n background: var(--card-border-color);\n outline: none;\n -webkit-appearance: none;\n appearance: none;\n\n &::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: var(--card-focus-ring-color, #2276fc);\n cursor: pointer;\n border: 2px solid white;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n }\n\n &::-moz-range-thumb {\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: var(--card-focus-ring-color, #2276fc);\n cursor: pointer;\n border: 2px solid white;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n }\n\n &:hover::-webkit-slider-thumb {\n background: var(--card-focus-ring-color, #1a5fc7);\n }\n\n &:hover::-moz-range-thumb {\n background: var(--card-focus-ring-color, #1a5fc7);\n }\n`\n\nconst WatermarkOverlay = styled.div<{$opacity: number}>`\n position: absolute;\n max-width: 200px;\n opacity: ${(props) => props.$opacity};\n cursor: move;\n user-select: none;\n z-index: 10;\n pointer-events: auto;\n\n img {\n width: 100%;\n height: auto;\n display: block;\n pointer-events: none;\n }\n\n &:hover {\n outline: 2px dashed rgba(255, 255, 255, 0.8);\n outline-offset: 4px;\n }\n`\n\ninterface DraggableWatermarkProps {\n watermark: WatermarkConfig\n onChange: (watermark: WatermarkConfig) => void\n containerRef?: React.RefObject<HTMLDivElement>\n videoElementRef?: React.RefObject<HTMLVideoElement>\n}\n\nexport default function DraggableWatermark({\n watermark,\n onChange,\n containerRef,\n videoElementRef,\n}: DraggableWatermarkProps) {\n const [isDragging, setIsDragging] = useState(false)\n const [dragStart, setDragStart] = useState({x: 0, y: 0})\n const [startPosition, setStartPosition] = useState({x: 0, y: 0})\n const watermarkRef = useRef<HTMLDivElement>(null)\n const debounceTimeoutRef = useRef<NodeJS.Timeout | null>(null)\n const [localPosition, setLocalPosition] = useState(watermark.position || {x: 50, y: 50})\n\n const position = localPosition\n const size = watermark.size || 20\n const opacity = watermark.opacity ?? 0.7\n\n const parseOpacityPercent = (value: string | undefined): number | null => {\n if (!value) return null\n const trimmed = value.trim()\n if (!trimmed.endsWith('%')) return null\n const num = Number(trimmed.slice(0, -1))\n if (!Number.isFinite(num)) return null\n return Math.max(0, Math.min(1, num / 100))\n }\n\n const getVideoContentBox = useCallback(() => {\n const container = containerRef?.current\n if (!container) return {x: 0, y: 0, width: 0, height: 0}\n\n const rect = container.getBoundingClientRect()\n const containerW = rect.width\n const containerH = rect.height\n\n const videoEl = videoElementRef?.current\n const videoW = videoEl?.videoWidth || 0\n const videoH = videoEl?.videoHeight || 0\n\n if (!videoW || !videoH || !containerW || !containerH) {\n return {x: 0, y: 0, width: containerW, height: containerH}\n }\n\n // object-fit: contain sizing\n const scale = Math.min(containerW / videoW, containerH / videoH)\n const contentW = videoW * scale\n const contentH = videoH * scale\n const offsetX = (containerW - contentW) / 2\n const offsetY = (containerH - contentH) / 2\n\n return {x: offsetX, y: offsetY, width: contentW, height: contentH}\n }, [containerRef, videoElementRef])\n\n const parseOverlayValue = (value: string | undefined): {n: number; unit: '%' | 'px'} | null => {\n if (!value) return null\n const trimmed = value.trim()\n const px = trimmed.endsWith('px')\n const pct = trimmed.endsWith('%')\n const num = Number(trimmed.replace(/px|%/g, ''))\n if (!Number.isFinite(num)) return null\n if (px) return {n: num, unit: 'px'}\n if (pct) return {n: num, unit: '%'}\n return null\n }\n\n const computeManualStyle = (overlay: MuxOverlaySettings) => {\n const rect = containerRef?.current?.getBoundingClientRect()\n const w = rect?.width ?? 0\n const h = rect?.height ?? 0\n const isVertical = h > w\n const baseW = isVertical ? 1080 : 1920\n const baseH = isVertical ? 1920 : 1080\n\n const hm = parseOverlayValue(overlay.horizontal_margin)\n const vm = parseOverlayValue(overlay.vertical_margin)\n const ww = parseOverlayValue(overlay.width)\n const manualOpacity = parseOpacityPercent(overlay.opacity)\n\n const toCss = (v: {n: number; unit: '%' | 'px'} | null, axis: 'x' | 'y') => {\n if (!v) return undefined\n if (v.unit === '%') return `${v.n}%`\n if (axis === 'x') return `${(v.n * w) / baseW}px`\n return `${(v.n * h) / baseH}px`\n }\n\n const computeHorizontalStyle = () => {\n if (overlay.horizontal_align === 'left') {\n return {left: toCss(hm, 'x'), right: undefined, transform: 'translate(0, 0)'}\n }\n if (overlay.horizontal_align === 'right') {\n return {right: toCss(hm, 'x'), left: undefined, transform: 'translate(0, 0)'}\n }\n return {left: '50%', right: undefined, transform: 'translate(-50%, 0)'}\n }\n\n const computeVerticalStyle = () => {\n if (overlay.vertical_align === 'top') {\n return {top: toCss(vm, 'y'), bottom: undefined}\n }\n if (overlay.vertical_align === 'bottom') {\n return {bottom: toCss(vm, 'y'), top: undefined}\n }\n return {top: '50%', bottom: undefined}\n }\n\n const hStyle = computeHorizontalStyle()\n const vStyle = computeVerticalStyle()\n\n let transform = hStyle.transform\n if (overlay.vertical_align === 'middle') {\n transform =\n overlay.horizontal_align === 'center' ? 'translate(-50%, -50%)' : 'translate(0, -50%)'\n }\n\n return {\n position: 'absolute' as const,\n ...hStyle,\n ...vStyle,\n transform,\n width: ww ? toCss(ww, 'x') : `${size}%`,\n opacity: manualOpacity ?? opacity,\n cursor: 'default',\n }\n }\n\n const debouncedOnChange = useCallback(\n (newWatermark: WatermarkConfig) => {\n if (debounceTimeoutRef.current) {\n clearTimeout(debounceTimeoutRef.current)\n }\n debounceTimeoutRef.current = setTimeout(() => {\n onChange(newWatermark)\n }, 300)\n },\n [onChange],\n )\n\n useEffect(() => {\n return () => {\n if (debounceTimeoutRef.current) {\n clearTimeout(debounceTimeoutRef.current)\n }\n }\n }, [])\n\n useEffect(() => {\n if (!isDragging && watermark.position) {\n // oxlint-disable-next-line react/set-state-in-effect\n setLocalPosition(watermark.position)\n }\n }, [watermark.position, isDragging])\n\n const handleMouseDown = useCallback(\n (e: React.MouseEvent) => {\n e.preventDefault()\n setIsDragging(true)\n setDragStart({x: e.clientX, y: e.clientY})\n setStartPosition({x: position.x, y: position.y})\n },\n [position],\n )\n\n const handleMouseMove = useCallback(\n (e: MouseEvent) => {\n if (!isDragging || !containerRef?.current) return\n\n const container = containerRef.current\n const rect = container.getBoundingClientRect()\n const content = getVideoContentBox()\n const contentW = content.width || rect.width\n const contentH = content.height || rect.height\n const dx = e.clientX - dragStart.x\n const dy = e.clientY - dragStart.y\n\n const deltaXPercent = (dx / contentW) * 100\n const deltaYPercent = (dy / contentH) * 100\n\n let newX = startPosition.x + deltaXPercent\n let newY = startPosition.y + deltaYPercent\n\n newX = Math.max(0, Math.min(100, newX))\n newY = Math.max(0, Math.min(100, newY))\n\n setLocalPosition({x: newX, y: newY})\n\n debouncedOnChange({\n ...watermark,\n position: {x: newX, y: newY},\n })\n },\n [\n isDragging,\n dragStart,\n startPosition,\n containerRef,\n watermark,\n debouncedOnChange,\n getVideoContentBox,\n ],\n )\n\n const handleMouseUp = useCallback(() => {\n setIsDragging(false)\n if (debounceTimeoutRef.current) {\n clearTimeout(debounceTimeoutRef.current)\n debounceTimeoutRef.current = null\n }\n onChange({\n ...watermark,\n position: localPosition,\n })\n }, [watermark, localPosition, onChange])\n\n useEffect(() => {\n if (isDragging) {\n document.addEventListener('mousemove', handleMouseMove)\n document.addEventListener('mouseup', handleMouseUp)\n return () => {\n document.removeEventListener('mousemove', handleMouseMove)\n document.removeEventListener('mouseup', handleMouseUp)\n }\n }\n return undefined\n }, [isDragging, handleMouseMove, handleMouseUp])\n\n if (!watermark.imageUrl) {\n return null\n }\n\n const hasManualOverlay = Boolean(watermark.overlay_settings)\n const opacityForRender = hasManualOverlay\n ? (parseOpacityPercent(watermark.overlay_settings?.opacity) ?? opacity)\n : opacity\n // oxlint-disable-next-line react/refs\n const contentBox = getVideoContentBox()\n const hasContentBox = contentBox.width > 0 && contentBox.height > 0\n\n const computeWatermarkStyle = () => {\n if (hasManualOverlay) {\n return computeManualStyle(watermark.overlay_settings!)\n }\n if (hasContentBox) {\n return {\n left: `${contentBox.x + (position.x / 100) * contentBox.width}px`,\n top: `${contentBox.y + (position.y / 100) * contentBox.height}px`,\n transform: 'translate(-50%, -50%)',\n width: `${Math.max(1, (size / 100) * contentBox.width)}px`,\n cursor: isDragging ? 'grabbing' : 'grab',\n }\n }\n return {\n left: `${position.x}%`,\n top: `${position.y}%`,\n transform: 'translate(-50%, -50%)',\n width: `${size}%`,\n cursor: isDragging ? 'grabbing' : 'grab',\n }\n }\n\n return (\n <WatermarkOverlay\n ref={watermarkRef}\n $opacity={opacityForRender}\n onMouseDown={hasManualOverlay ? undefined : handleMouseDown}\n // oxlint-disable-next-line react/refs\n style={computeWatermarkStyle()}\n >\n <img src={watermark.imageUrl} alt=\"Watermark\" draggable={false} />\n </WatermarkOverlay>\n )\n}\n\ninterface WatermarkControlsProps {\n watermark: WatermarkConfig\n onChange: (watermark: WatermarkConfig) => void\n onValidationChange?: (error: string | null) => void\n previewContainerRef?: React.RefObject<HTMLDivElement | null>\n previewVideoRef?: React.RefObject<HTMLVideoElement | null>\n}\n\nexport function WatermarkControls({\n watermark,\n onChange,\n onValidationChange,\n previewContainerRef,\n previewVideoRef,\n}: WatermarkControlsProps) {\n const [urlInput, setUrlInput] = useState(watermark.imageUrl || '')\n const [urlError, setUrlError] = useState<string | null>(null)\n const [isValidating, setIsValidating] = useState(false)\n const [isValid, setIsValid] = useState<boolean | null>(null)\n const validationTimeoutRef = useRef<NodeJS.Timeout | null>(null)\n const [mode, setMode] = useState<'canvas' | 'manual'>(\n watermark.overlay_settings ? 'manual' : 'canvas',\n )\n\n const isUpdatingRef = useRef(false)\n\n const isValidExtension = useCallback((extension: string) => {\n return extension.endsWith('.png') || extension.endsWith('.jpg') || extension.endsWith('.jpeg')\n }, [])\n\n const validateUrl = useCallback(\n (url: string) => {\n if (validationTimeoutRef.current) {\n clearTimeout(validationTimeoutRef.current)\n }\n\n if (!url) {\n setUrlError(null)\n setIsValid(null)\n setIsValidating(false)\n onValidationChange?.(null)\n isUpdatingRef.current = true\n onChange({\n ...watermark,\n enabled: false,\n imageUrl: undefined,\n overlay_settings: undefined,\n })\n return\n }\n\n setIsValidating(true)\n setIsValid(null)\n setUrlError(null)\n\n validationTimeoutRef.current = setTimeout(() => {\n try {\n const urlObj = new URL(url)\n const pathname = urlObj.pathname.toLowerCase()\n if (isValidExtension(pathname)) {\n setIsValid(true)\n setUrlError(null)\n onValidationChange?.(null)\n const img = new Image()\n img.onload = () => {\n const imageAspectRatio =\n img.naturalWidth && img.naturalHeight ? img.naturalWidth / img.naturalHeight : 1\n isUpdatingRef.current = true\n onChange({\n ...watermark,\n enabled: true,\n imageUrl: url,\n imageAspectRatio,\n })\n }\n img.onerror = () => {\n isUpdatingRef.current = true\n onChange({\n ...watermark,\n enabled: true,\n imageUrl: url,\n imageAspectRatio: watermark.imageAspectRatio,\n })\n }\n img.src = url\n } else {\n const errorMsg =\n 'Mux only supports PNG and JPG watermark images. Please use a .png or .jpg file.'\n setIsValid(false)\n setUrlError(errorMsg)\n onValidationChange?.(errorMsg)\n isUpdatingRef.current = true\n onChange({\n ...watermark,\n enabled: false,\n imageUrl: undefined,\n imageAspectRatio: undefined,\n overlay_settings: undefined,\n })\n }\n } catch {\n setIsValid(false)\n const errorMsg = 'Please enter a valid URL (e.g., https://example.com/watermark.png)'\n setUrlError(errorMsg)\n onValidationChange?.(errorMsg)\n isUpdatingRef.current = true\n onChange({\n ...watermark,\n enabled: false,\n imageUrl: undefined,\n imageAspectRatio: undefined,\n overlay_settings: undefined,\n })\n // oxlint-disable-next-line react/todo\n } finally {\n setIsValidating(false)\n }\n }, 500)\n },\n [watermark, onChange, onValidationChange, isValidExtension],\n )\n\n useEffect(() => {\n return () => {\n if (validationTimeoutRef.current) {\n clearTimeout(validationTimeoutRef.current)\n }\n }\n }, [])\n\n useEffect(() => {\n // oxlint-disable-next-line react/set-state-in-effect\n setMode(watermark.overlay_settings ? 'manual' : 'canvas')\n }, [watermark.overlay_settings])\n\n const handleUrlChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const url = e.target.value\n setUrlInput(url)\n\n if (watermark.imageUrl && url !== watermark.imageUrl) {\n isUpdatingRef.current = true\n onChange({\n ...watermark,\n enabled: false,\n imageUrl: undefined,\n imageAspectRatio: undefined,\n overlay_settings: undefined,\n })\n }\n\n validateUrl(url)\n }\n\n const normalizeZeroPercent = (value: string | undefined) => {\n if (!value) return value\n const trimmed = value.trim()\n if (!trimmed.endsWith('%')) return value\n const n = Number(trimmed.slice(0, -1))\n if (!Number.isFinite(n)) return value\n const epsilon = 1e-9\n if (n === 0 || Object.is(n, -0) || Math.abs(n) < epsilon) return '0.01%'\n return `${n}%`\n }\n\n const updateOverlaySettings = (next: Partial<MuxOverlaySettings>) => {\n const prev = watermark.overlay_settings\n const base: MuxOverlaySettings = prev ?? {\n vertical_align: 'bottom',\n vertical_margin: '2%',\n horizontal_align: 'right',\n horizontal_margin: '2%',\n width: `${watermark.size ?? 20}%`,\n opacity: `${Math.round((watermark.opacity ?? 0.7) * 100)}%`,\n }\n\n const merged: MuxOverlaySettings = {\n ...base,\n ...next,\n }\n\n onChange({\n ...watermark,\n enabled: true,\n overlay_settings: {\n ...merged,\n horizontal_margin:\n normalizeZeroPercent(merged.horizontal_margin) || merged.horizontal_margin,\n vertical_margin: normalizeZeroPercent(merged.vertical_margin) || merged.vertical_margin,\n },\n })\n }\n\n const getVideoContentBox = () => {\n const container = previewContainerRef?.current\n if (!container) return {x: 0, y: 0, width: 0, height: 0}\n\n const rect = container.getBoundingClientRect()\n const containerW = rect.width\n const containerH = rect.height\n\n const videoEl = previewVideoRef?.current\n const videoW = videoEl?.videoWidth || 0\n const videoH = videoEl?.videoHeight || 0\n\n if (!videoW || !videoH || !containerW || !containerH) {\n return {x: 0, y: 0, width: containerW, height: containerH}\n }\n\n const scale = Math.min(containerW / videoW, containerH / videoH)\n const contentW = videoW * scale\n const contentH = videoH * scale\n const offsetX = (containerW - contentW) / 2\n const offsetY = (containerH - contentH) / 2\n\n return {x: offsetX, y: offsetY, width: contentW, height: contentH}\n }\n\n return (\n <Stack gap={3}>\n <Stack gap={2}>\n <Text size={1} weight=\"medium\">\n Watermark Image URL\n </Text>\n <Text size={0} muted>\n Enter a URL to a PNG or JPG image. Mux will download this image and overlay it on your\n video.\n </Text>\n <Box style={{position: 'relative', width: '100%'}}>\n <input\n type=\"url\"\n value={urlInput}\n onChange={handleUrlChange}\n placeholder=\"https://example.com/watermark.png\"\n style={{\n padding: '8px 12px',\n paddingRight: (() => {\n if (urlInput) return '96px'\n if (isValid !== null) return '36px'\n return '12px'\n })(),\n border: (() => {\n if (urlError || isValid === false) return '1px solid #e74c3c'\n if (isValid === true) return '1px solid #4caf50'\n return '1px solid #ccc'\n })(),\n borderRadius: '4px',\n width: '100%',\n maxWidth: '100%',\n boxSizing: 'border-box',\n fontSize: '14px',\n }}\n />\n {(urlInput || isValidating || isValid !== null) && (\n <Box\n style={{\n position: 'absolute',\n right: '8px',\n top: '50%',\n transform: 'translateY(-50%)',\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n }}\n >\n {urlInput && (\n <Button\n text=\"Clear\"\n mode=\"bleed\"\n tone=\"critical\"\n onClick={() => {\n setUrlInput('')\n validateUrl('')\n }}\n disabled={isValidating}\n style={{fontSize: '11px', height: '24px'}}\n />\n )}\n {isValidating && (\n <Text size={0} muted>\n Validating...\n </Text>\n )}\n {isValid === true && !isValidating && (\n <CheckmarkCircleIcon style={{color: '#4caf50', fontSize: '18px'}} />\n )}\n {isValid === false && !isValidating && (\n <ErrorOutlineIcon style={{color: '#e74c3c', fontSize: '18px'}} />\n )}\n </Box>\n )}\n </Box>\n {urlError && (\n <Card padding={2} tone=\"critical\" radius={2}>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon style={{color: '#e74c3c', flexShrink: 0}} />\n <Text size={0} style={{color: '#e74c3c'}}>\n {urlError}\n </Text>\n </Flex>\n </Card>\n )}\n </Stack>\n\n {watermark.imageUrl && (\n <Stack gap={2}>\n <Card padding={3} tone=\"transparent\" border radius={2}>\n <Flex\n align=\"center\"\n justify=\"space-between\"\n gap={3}\n style={{flexWrap: 'wrap', alignItems: 'flex-start'}}\n >\n <Stack gap={2} style={{minWidth: 240, flex: 1}}>\n <Text size={1} weight=\"medium\">\n Positioning mode\n </Text>\n <Text size={0} muted>\n Choose between dragging on the canvas or manually editing the Mux{' '}\n <code>overlay_settings</code> fields (as in{' '}\n <a\n href=\"https://www.mux.com/docs/guides/add-watermarks-to-your-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n the docs\n </a>\n ).\n </Text>\n </Stack>\n <Flex gap={2} style={{flexWrap: 'wrap'}}>\n <Button\n text=\"Canvas\"\n mode={mode === 'canvas' ? 'default' : 'ghost'}\n onClick={() => {\n setMode('canvas')\n onChange({...watermark, enabled: true, overlay_settings: undefined})\n }}\n />\n <Button\n text=\"Manual\"\n mode={mode === 'manual' ? 'default' : 'ghost'}\n onClick={() => {\n setMode('manual')\n const overlay = convertWatermarkToMuxOverlay({...watermark, enabled: true})\n updateOverlaySettings(overlay ?? {})\n }}\n />\n </Flex>\n </Flex>\n </Card>\n\n {mode === 'manual' && (\n <Card padding={3} tone=\"transparent\" border radius={2}>\n <Stack gap={3}>\n <Text size={1} weight=\"medium\">\n Mux overlay_settings\n </Text>\n <Grid gridTemplateColumns={[1, 2]} gap={3} style={{width: '100%'}}>\n <Stack gap={2} style={{minWidth: 0}}>\n <Text size={0} muted>\n horizontal_align\n </Text>\n <select\n value={watermark.overlay_settings?.horizontal_align || 'right'}\n onChange={(e) =>\n updateOverlaySettings({\n horizontal_align: (e.target.value ||\n 'right') as MuxOverlaySettings['horizontal_align'],\n })\n }\n style={{\n width: '100%',\n padding: '8px 10px',\n border: '1px solid #ccc',\n borderRadius: 4,\n }}\n >\n <option value=\"left\">left</option>\n <option value=\"center\">center</option>\n <option value=\"right\">right</option>\n </select>\n </Stack>\n <Stack gap={2} style={{minWidth: 0}}>\n <Text size={0} muted>\n horizontal_margin (e.g. 2% or 40px)\n </Text>\n <TextInput\n value={watermark.overlay_settings?.horizontal_margin || '2%'}\n onChange={(e) =>\n updateOverlaySettings({horizontal_margin: e.currentTarget.value})\n }\n />\n </Stack>\n <Stack gap={2} style={{minWidth: 0}}>\n <Text size={0} muted>\n vertical_align\n </Text>\n <select\n value={watermark.overlay_settings?.vertical_align || 'bottom'}\n onChange={(e) =>\n updateOverlaySettings({\n vertical_align: (e.target.value ||\n 'bottom') as MuxOverlaySettings['vertical_align'],\n })\n }\n style={{\n width: '100%',\n padding: '8px 10px',\n border: '1px solid #ccc',\n borderRadius: 4,\n }}\n >\n <option value=\"top\">top</option>\n <option value=\"middle\">middle</option>\n <option value=\"bottom\">bottom</option>\n </select>\n </Stack>\n <Stack gap={2} style={{minWidth: 0}}>\n <Text size={0} muted>\n vertical_margin (e.g. 2% or 40px)\n </Text>\n <TextInput\n value={watermark.overlay_settings?.vertical_margin || '2%'}\n onChange={(e) =>\n updateOverlaySettings({vertical_margin: e.currentTarget.value})\n }\n />\n </Stack>\n <Stack gap={2} style={{minWidth: 0}}>\n <Text size={0} muted>\n width (e.g. 25% or 80px)\n </Text>\n <TextInput\n value={watermark.overlay_settings?.width || `${watermark.size ?? 20}%`}\n onChange={(e) => updateOverlaySettings({width: e.currentTarget.value})}\n />\n </Stack>\n <Stack gap={2} style={{minWidth: 0}}>\n <Text size={0} muted>\n opacity (e.g. 90%)\n </Text>\n <TextInput\n value={\n watermark.overlay_settings?.opacity ||\n `${Math.round((watermark.opacity ?? 0.7) * 100)}%`\n }\n onChange={(e) => updateOverlaySettings({opacity: e.currentTarget.value})}\n />\n </Stack>\n </Grid>\n <Text size={0} muted>\n Margins and width accept either percentages or pixels, per the Mux guide.\n </Text>\n </Stack>\n </Card>\n )}\n\n {mode === 'canvas' && (\n <>\n <Box>\n <Text size={1} weight=\"medium\">\n {/* oxlint-disable-next-line react/refs */}\n {(() => {\n const sizePct = watermark.size || 20\n const contentW = getVideoContentBox().width\n if (!contentW) return `Size: ${sizePct}%`\n const px = Math.max(1, Math.round((sizePct / 100) * contentW))\n return `Size: ${px}px`\n })()}\n </Text>\n <RangeInput\n type=\"range\"\n // oxlint-disable-next-line react/refs\n value={(() => {\n const sizePct = watermark.size || 20\n const contentW = getVideoContentBox().width\n if (!contentW) return sizePct\n return Math.max(1, Math.round((sizePct / 100) * contentW))\n })()}\n // oxlint-disable-next-line react/refs\n min={(() => {\n const contentW = getVideoContentBox().width\n if (!contentW) return 5\n return Math.max(1, Math.round(contentW * 0.05))\n })()}\n // oxlint-disable-next-line react/refs\n max={(() => {\n const contentW = getVideoContentBox().width\n if (!contentW) return 50\n return Math.max(1, Math.round(contentW * 0.5))\n })()}\n step={1}\n onChange={(e) => {\n const raw = Number(e.target.value)\n const contentW = getVideoContentBox().width\n const nextPct = contentW ? (raw / contentW) * 100 : raw\n const clampedPct = Math.max(5, Math.min(50, nextPct))\n onChange({\n ...watermark,\n size: clampedPct,\n })\n }}\n />\n </Box>\n\n <Box>\n <Text size={1} weight=\"medium\">\n Opacity: {Math.round((watermark.opacity ?? 0.7) * 100)}%\n </Text>\n <RangeInput\n type=\"range\"\n value={watermark.opacity ?? 0.7}\n min={0}\n max={1}\n step={0.05}\n onChange={(e) =>\n onChange({\n ...watermark,\n opacity: Number(e.target.value),\n })\n }\n />\n </Box>\n </>\n )}\n\n <Card padding={2} tone=\"transparent\" border radius={2}>\n <Text size={0} muted>\n {mode === 'manual'\n ? 'Manual mode: edit the overlay_settings fields above'\n : '💡 Drag the watermark on the preview to position it'}\n </Text>\n </Card>\n </Stack>\n )}\n </Stack>\n )\n}\n","import {TranslateIcon} from '@sanity/icons/Translate'\nimport {Box, Card, Checkbox, Flex, Stack, Text} from '@sanity/ui'\nimport {Autocomplete} from '@sanity/ui/autocomplete'\nimport {uuid} from '@sanity/uuid'\nimport LanguagesList from 'iso-639-1'\nimport {type Dispatch} from 'react'\nimport {FormField} from 'sanity'\n\nimport {type PluginConfig, SUPPORTED_MUX_LANGUAGES, type UploadTextTrack} from '../util/types'\n\nconst ALL_LANGUAGE_CODES = LanguagesList.getAllCodes().map((code) => ({\n value: code,\n label: LanguagesList.getNativeName(code),\n}))\n\nconst SUBTITLE_LANGUAGES: Record<\n Extract<UploadTextTrack, {language_code: any}>['type'],\n {value: string; label: string}[]\n> = {\n autogenerated: SUPPORTED_MUX_LANGUAGES.map((lang) => ({\n value: lang.code,\n label: lang.label,\n })),\n subtitles: ALL_LANGUAGE_CODES,\n captions: ALL_LANGUAGE_CODES,\n}\n\ntype TrackSubAction =\n | {subAction: 'add'; value: Partial<UploadTextTrack>}\n | {subAction: 'update'; value: Partial<UploadTextTrack>}\n | {subAction: 'delete'}\n\nexport type TrackAction = {action: 'track'; id: string} & TrackSubAction\n\nexport default function TextTracksEditor({\n tracks,\n dispatch,\n defaultLang,\n}: {\n /**\n * Although the schema for tracks is an array, which we'll eventually support to allow uploading\n * multiple custom subtitles, for now we only support a single auto-generated track.\n */\n tracks: (Partial<UploadTextTrack> & {_id: string})[]\n dispatch: Dispatch<TrackAction>\n defaultLang: PluginConfig['defaultAutogeneratedSubtitleLang']\n}) {\n const track = tracks[0]\n return (\n <FormField title=\"Auto-generated subtitle or caption\" path={[]}>\n <Stack gap={2}>\n <Flex align=\"center\">\n <Checkbox\n id=\"include-autogenerated-track\"\n style={{display: 'block'}}\n checked={!!track?.language_code}\n onChange={() => {\n if (track) {\n dispatch({action: 'track', id: track._id, subAction: 'delete'})\n } else {\n dispatch({\n action: 'track',\n id: uuid(),\n subAction: 'add',\n value: {\n type: 'autogenerated',\n name: defaultLang || undefined,\n language_code: defaultLang || undefined,\n },\n })\n }\n }}\n />\n <Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor=\"checkbox\">Generate captions</label>\n </Text>\n </Box>\n </Flex>\n {track && (\n <Autocomplete\n id={`text-tract-editor--language`}\n value={track.language_code}\n onChange={(newValue) =>\n dispatch({\n action: 'track',\n id: track._id,\n subAction: 'update',\n value: {\n language_code: newValue,\n name: LanguagesList.getNativeName(newValue),\n },\n })\n }\n options={SUBTITLE_LANGUAGES[track.type!]}\n icon={TranslateIcon}\n placeholder=\"Select language\"\n filterOption={(query, option) =>\n option.label.toLowerCase().indexOf(query.toLowerCase()) > -1 ||\n option.value.toLowerCase().indexOf(query.toLowerCase()) > -1\n }\n openButton\n renderValue={(value) =>\n SUBTITLE_LANGUAGES[track.type!].find((l) => l.value === value)?.label || value\n }\n renderOption={(option) => (\n <Card data-as=\"button\" padding={3} radius={2} tone=\"inherit\">\n <Text size={2} textOverflow=\"ellipsis\">\n {option.label} ({option.value})\n </Text>\n </Card>\n )}\n />\n )}\n </Stack>\n </FormField>\n )\n}\n","import {Checkbox, Flex, Grid, Text} from '@sanity/ui'\nimport {type ActionDispatch, type CSSProperties, type ReactNode, useState} from 'react'\n\nimport {type UploadConfigurationStateAction} from '../UploadConfiguration'\n\nexport default function PlaybackPolicyOption({\n id,\n checked,\n optionName,\n description,\n dispatch,\n action,\n disabled,\n}: {\n id: string\n checked: boolean\n optionName: string\n description: string | ReactNode\n dispatch: ActionDispatch<[action: UploadConfigurationStateAction]>\n action?: 'public_policy' | 'signed_policy' | 'drm_policy'\n disabled?: boolean\n}) {\n const [scale, setScale] = useState(1)\n\n const boxStyle: CSSProperties = {\n outline: '0.01rem solid grey',\n transform: `scale(${scale})`,\n transition: 'transform 0.1s ease-in-out',\n cursor: disabled ? 'not-allowed' : 'pointer',\n borderRadius: '0.25rem',\n }\n\n const triggerAnimation = () => {\n setScale(0.98)\n setTimeout(() => {\n setScale(1)\n }, 100)\n }\n\n const handleBoxClick = () => {\n if (!action) return\n triggerAnimation()\n dispatch({\n action,\n value: !checked,\n })\n }\n\n const descriptionJsx =\n typeof description === 'string' ? (\n <Text size={2} muted>\n {description}\n </Text>\n ) : (\n description\n )\n return (\n <label>\n <Flex gap={3} padding={3} style={boxStyle}>\n <Checkbox\n id={id}\n required\n checked={checked}\n onChange={handleBoxClick}\n disabled={disabled}\n />\n <Grid gap={3}>\n <Text size={3} weight=\"bold\">\n {optionName}\n </Text>\n {descriptionJsx}\n </Grid>\n </Flex>\n </label>\n )\n}\n","import {WarningFilledIcon} from '@sanity/icons/WarningFilled'\nimport {Box, Flex, Text} from '@sanity/ui'\nimport {type CSSProperties} from 'react'\n\nexport default function PlaybackPolicyWarning() {\n const textStyle: CSSProperties = {\n color: '#13141A',\n fontWeight: 500,\n }\n\n const boxStyle: CSSProperties = {\n outline: '0.01rem solid grey',\n backgroundColor: '#979cb0',\n borderRadius: '0.5rem',\n width: 'max-content',\n color: '#13141A',\n }\n\n return (\n <Box padding={2} style={boxStyle}>\n <Flex align=\"center\" gap={2}>\n <WarningFilledIcon />\n <Text size={1} style={textStyle}>\n Please select at least one Playback Policy\n </Text>\n </Flex>\n </Box>\n )\n}\n","import {Grid, Text} from '@sanity/ui'\nimport {Code} from '@sanity/ui/code'\nimport {type ActionDispatch} from 'react'\n\nimport {type Secrets, type UploadConfig} from '../../util/types'\nimport {type UploadConfigurationStateAction} from '../UploadConfiguration'\nimport PlaybackPolicyOption from './PlaybackPolicyOption'\nimport PlaybackPolicyWarning from './PlaybackPolicyWarning'\n\nexport default function PlaybackPolicy({\n id,\n config,\n secrets,\n dispatch,\n}: {\n id: string\n config: UploadConfig\n secrets: Secrets\n dispatch: ActionDispatch<[action: UploadConfigurationStateAction]>\n}) {\n const noPolicySelected = !(config.public_policy || config.signed_policy || config.drm_policy)\n const drmPolicyDisabled = !secrets.drmConfigId\n return (\n <Grid gap={3}>\n <Text weight=\"bold\">Advanced Playback Policies</Text>\n <PlaybackPolicyOption\n id={`${id}--public`}\n checked={config.public_policy}\n optionName=\"Public\"\n description={\n <>\n <Text size={2} muted>\n Playback IDs are accessible by constructing an HLS URL like\n </Text>\n <Code>{'https://stream.mux.com/{PLAYBACK_ID}'}</Code>\n </>\n }\n dispatch={dispatch}\n action=\"public_policy\"\n />\n {secrets.enableSignedUrls && (\n <PlaybackPolicyOption\n id={`${id}--signed`}\n checked={config.signed_policy}\n optionName=\"Signed\"\n description={\n <>\n <Text size={2} muted>\n Playback IDs should be used with tokens\n </Text>\n <Code>{'https://stream.mux.com/{PLAYBACK_ID}?token={TOKEN}'}</Code>\n <Text size={2} muted>\n See{' '}\n <a\n href=\"https://www.mux.com/docs/guides/secure-video-playback\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Secure video playback\n </a>{' '}\n for details about creating tokens.\n </Text>\n </>\n }\n // See Secure video playback for details about creating tokens.\"\n dispatch={dispatch}\n action=\"signed_policy\"\n />\n )}\n {drmPolicyDisabled ? (\n <PlaybackPolicyOption\n id={`${id}--drm`}\n checked={false}\n optionName=\"DRM - Disabled\"\n description={\n <>\n <Text size={2} muted>\n To enable DRM add your DRM Configuration Id to your plugin configuration in the API\n Credentials view.{' '}\n <a\n href=\"https://www.mux.com/support/human\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Contact us\n </a>{' '}\n to get started using DRM.\n </Text>\n </>\n }\n dispatch={dispatch}\n disabled\n />\n ) : (\n <PlaybackPolicyOption\n id={`${id}--drm`}\n checked={config.drm_policy}\n optionName=\"DRM\"\n description={\n <>\n <Text size={2} muted>\n Playback IDs should be used with tokens as with Signed playback, but require extra\n configuration.\n </Text>\n <Code>{'https://stream.mux.com/{PLAYBACK_ID}?token={TOKEN}'}</Code>\n <Text size={2} muted>\n See{' '}\n <a\n href=\"https://www.mux.com/docs/guides/protect-videos-with-drm#play-drm-protected-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Protect videos with DRM\n </a>{' '}\n for details about configuring your player for DRM playback and{' '}\n <a\n href=\"https://www.mux.com/docs/guides/secure-video-playback\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Secure video playback\n </a>{' '}\n for details about creating tokens.\n </Text>\n </>\n }\n dispatch={dispatch}\n action=\"drm_policy\"\n />\n )}\n {noPolicySelected && <PlaybackPolicyWarning />}\n </Grid>\n )\n}\n","import {Flex, Radio, Text} from '@sanity/ui'\nimport {type ActionDispatch} from 'react'\nimport {FormField} from 'sanity'\n\nimport {type UploadConfig} from '../../util/types'\nimport {type UploadConfigurationStateAction} from '../UploadConfiguration'\n\nexport const RESOLUTION_TIERS = [\n {value: '1080p', label: '1080p'},\n {value: '1440p', label: '1440p (2k)'},\n {value: '2160p', label: '2160p (4k)'},\n] as const satisfies {value: UploadConfig['max_resolution_tier']; label: string}[]\n\nexport const ResolutionTierSelector = ({\n id,\n config,\n dispatch,\n maxSupportedResolution,\n}: {\n id: string\n config: UploadConfig\n dispatch: ActionDispatch<[action: UploadConfigurationStateAction]>\n maxSupportedResolution: number\n}) => {\n return (\n <FormField\n path={[]}\n title=\"Resolution Tier\"\n description={\n <>\n The maximum{' '}\n <a\n href=\"https://docs.mux.com/api-reference#video/operation/create-direct-upload\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n resolution_tier\n </a>{' '}\n your asset is encoded, stored, and streamed at.\n </>\n }\n >\n <Flex gap={3} wrap={'wrap'}>\n {RESOLUTION_TIERS.map(({value, label}, index) => {\n const inputId = `${id}--type-${value}`\n\n if (index > maxSupportedResolution) return null\n\n return (\n <Flex key={value} align=\"center\" gap={2}>\n <Radio\n checked={config.max_resolution_tier === value}\n name=\"asset-resolutiontier\"\n onChange={(e) =>\n dispatch({\n action: 'max_resolution_tier',\n value: e.currentTarget.value as UploadConfig['max_resolution_tier'],\n })\n }\n value={value}\n id={inputId}\n />\n <Text as=\"label\" htmlFor={inputId}>\n {label}\n </Text>\n </Flex>\n )\n })}\n </Flex>\n </FormField>\n )\n}\n","import {Checkbox, Flex, Label, Radio, Stack, Text} from '@sanity/ui'\nimport {type ActionDispatch, useMemo, useState} from 'react'\nimport {FormField} from 'sanity'\n\nimport {type StaticRenditionResolution, type UploadConfig} from '../../util/types'\nimport {type UploadConfigurationStateAction} from '../UploadConfiguration'\n\nconst ADVANCED_RESOLUTIONS: {value: StaticRenditionResolution; label: string}[] = [\n {value: '270p', label: '270p'},\n {value: '360p', label: '360p'},\n {value: '480p', label: '480p'},\n {value: '540p', label: '540p'},\n {value: '720p', label: '720p'},\n {value: '1080p', label: '1080p'},\n {value: '1440p', label: '1440p'},\n {value: '2160p', label: '2160p'},\n]\n\nexport const StaticRenditionSelector = ({\n id,\n config,\n dispatch,\n}: {\n id: string\n config: UploadConfig\n dispatch: ActionDispatch<[action: UploadConfigurationStateAction]>\n}) => {\n // Determine if user is in advanced mode based on selected renditions\n const isAdvancedMode = useMemo(() => {\n const specificResolutions = config.static_renditions.filter(\n (r) => r !== 'highest' && r !== 'audio-only',\n )\n return specificResolutions.length > 0\n }, [config.static_renditions])\n\n const [renditionMode, setRenditionMode] = useState<'standard' | 'advanced'>(\n isAdvancedMode ? 'advanced' : 'standard',\n )\n\n // Helper to toggle a rendition\n const toggleRendition = (rendition: StaticRenditionResolution) => {\n const current = config.static_renditions\n const hasRendition = current.includes(rendition)\n\n if (hasRendition) {\n dispatch({\n action: 'static_renditions',\n value: current.filter((r) => r !== rendition),\n })\n } else {\n dispatch({\n action: 'static_renditions',\n value: [...current, rendition],\n })\n }\n }\n\n // When switching modes, clear renditions that don't apply\n const handleModeChange = (mode: 'standard' | 'advanced') => {\n setRenditionMode(mode)\n if (mode === 'standard') {\n // Remove specific resolutions, keep only highest and audio-only\n dispatch({\n action: 'static_renditions',\n value: config.static_renditions.filter((r) => r === 'highest' || r === 'audio-only'),\n })\n } else {\n // Remove highest, keep specific resolutions and audio-only\n dispatch({\n action: 'static_renditions',\n value: config.static_renditions.filter((r) => r !== 'highest'),\n })\n }\n }\n return (\n <Stack gap={3}>\n <FormField\n path={[]}\n title=\"Static Renditions\"\n description=\"Generate downloadable MP4 or M4A files. Note: Mux will not upscale to produce MP4 renditions - renditions that would cause upscaling are skipped.\"\n >\n <Stack gap={3}>\n {/* Mode Selector */}\n <Flex gap={3}>\n <Flex align=\"center\" gap={2}>\n <Radio\n checked={renditionMode === 'standard'}\n name=\"rendition-mode\"\n onChange={() => handleModeChange('standard')}\n value=\"standard\"\n id={`${id}--mode-standard`}\n />\n <Text as=\"label\" htmlFor={`${id}--mode-standard`}>\n Standard\n </Text>\n </Flex>\n <Flex align=\"center\" gap={2}>\n <Radio\n checked={renditionMode === 'advanced'}\n name=\"rendition-mode\"\n onChange={() => handleModeChange('advanced')}\n value=\"advanced\"\n id={`${id}--mode-advanced`}\n />\n <Text as=\"label\" htmlFor={`${id}--mode-advanced`}>\n Advanced\n </Text>\n </Flex>\n </Flex>\n\n {/* Standard Mode Options */}\n {renditionMode === 'standard' && (\n <Stack gap={2}>\n <Flex align=\"center\" gap={2} padding={[0, 2]}>\n <Checkbox\n id={`${id}--highest`}\n style={{display: 'block'}}\n checked={config.static_renditions.includes('highest')}\n onChange={() => toggleRendition('highest')}\n />\n <Text as=\"label\" htmlFor={`${id}--highest`}>\n Highest Resolution (up to 4K)\n </Text>\n </Flex>\n <Flex align=\"center\" gap={2} padding={[0, 2]}>\n <Checkbox\n id={`${id}--audio-only-standard`}\n style={{display: 'block'}}\n checked={config.static_renditions.includes('audio-only')}\n onChange={() => toggleRendition('audio-only')}\n />\n <Text as=\"label\" htmlFor={`${id}--audio-only-standard`}>\n Audio Only (M4A)\n </Text>\n </Flex>\n </Stack>\n )}\n\n {/* Advanced Mode Options */}\n {renditionMode === 'advanced' && (\n <Stack gap={2}>\n <Label size={1} muted>\n Select specific resolutions:\n </Label>\n <Flex gap={2} wrap=\"wrap\">\n {ADVANCED_RESOLUTIONS.map(({value, label}) => {\n const inputId = `${id}--resolution-${value}`\n return (\n <Flex key={value} align=\"center\" gap={2}>\n <Checkbox\n id={inputId}\n style={{display: 'block'}}\n checked={config.static_renditions.includes(value)}\n onChange={() => toggleRendition(value)}\n />\n <Text as=\"label\" htmlFor={inputId} size={1}>\n {label}\n </Text>\n </Flex>\n )\n })}\n </Flex>\n <Flex align=\"center\" gap={2} padding={[2, 2, 0, 2]}>\n <Checkbox\n id={`${id}--audio-only-advanced`}\n style={{display: 'block'}}\n checked={config.static_renditions.includes('audio-only')}\n onChange={() => toggleRendition('audio-only')}\n />\n <Text as=\"label\" htmlFor={`${id}--audio-only-advanced`}>\n Audio Only (M4A)\n </Text>\n </Flex>\n </Stack>\n )}\n </Stack>\n </FormField>\n </Stack>\n )\n}\n","import {DocumentVideoIcon} from '@sanity/icons/DocumentVideo'\nimport {ErrorOutlineIcon} from '@sanity/icons/ErrorOutline'\nimport {UploadIcon} from '@sanity/icons/Upload'\nimport {Box, Button, Card, Dialog, Flex, Label, Radio, Stack, Text} from '@sanity/ui'\nimport {uuid} from '@sanity/uuid'\nimport LanguagesList from 'iso-639-1'\nimport {memo, useEffect, useId, useReducer, useRef, useState} from 'react'\nimport {FormField} from 'sanity'\n\nimport {useFetchFileSize} from '../hooks/useFetchFileSize'\nimport {useMediaMetadata, type VideoAssetMetadata} from '../hooks/useMediaMetadata'\nimport {convertWatermarkToMuxOverlay} from '../util/convertWatermarkToMux'\nimport formatBytes from '../util/formatBytes'\nimport {formatSeconds} from '../util/formatSeconds'\nimport {\n type AutogeneratedTextTrack,\n type CustomTextTrack,\n isAutogeneratedTrack,\n isCustomTextTrack,\n type MuxNewAssetSettings,\n type PluginConfig,\n type Secrets,\n type StaticRenditionResolution,\n type SupportedMuxLanguage,\n type UploadConfig,\n type UploadTextTrack,\n type WatermarkConfig,\n} from '../util/types'\nimport DraggableWatermark, {WatermarkControls} from './DraggableWatermark'\nimport TextTracksEditor, {type TrackAction} from './TextTracksEditor'\nimport PlaybackPolicy from './uploadConfiguration/PlaybackPolicy'\nimport {\n RESOLUTION_TIERS,\n ResolutionTierSelector,\n} from './uploadConfiguration/ResolutionTierSelector'\nimport {StaticRenditionSelector} from './uploadConfiguration/StaticRenditionSelector'\nimport type {StagedUpload} from './Uploader'\n\nexport type UploadConfigurationStateAction =\n | {action: 'video_quality'; value: UploadConfig['video_quality']}\n | {action: 'max_resolution_tier'; value: UploadConfig['max_resolution_tier']}\n | {action: 'static_renditions'; value: UploadConfig['static_renditions']}\n | {action: 'normalize_audio'; value: UploadConfig['normalize_audio']}\n | {action: 'signed_policy'; value: UploadConfig['signed_policy']}\n | {action: 'public_policy'; value: UploadConfig['public_policy']}\n | {action: 'drm_policy'; value: UploadConfig['drm_policy']}\n | {action: 'watermark'; value: WatermarkConfig}\n | TrackAction\n\nconst VIDEO_QUALITY_LEVELS = [\n {value: 'basic', label: 'Basic'},\n {value: 'plus', label: 'Plus'},\n {value: 'premium', label: 'Premium'},\n] as const satisfies {value: UploadConfig['video_quality']; label: string}[]\n\n/**\n * Sanitizes static renditions configuration to ensure 'highest' is not mixed with specific resolutions.\n * If both are present, only 'highest' (and 'audio-only' if present) will be kept.\n */\nfunction sanitizeStaticRenditions(\n renditions: StaticRenditionResolution[],\n): StaticRenditionResolution[] {\n const hasHighest = renditions.includes('highest')\n const hasSpecificResolutions = renditions.some((r) => r !== 'highest' && r !== 'audio-only')\n\n if (hasHighest && hasSpecificResolutions) {\n return renditions.filter((r) => r === 'highest' || r === 'audio-only')\n }\n\n return renditions\n}\n\n/**\n * The modal for configuring a staged upload. Handles triggering of the asset\n * upload, even if no modal needs to be shown.\n *\n * @returns\n */\nexport default function UploadConfiguration({\n stagedUpload,\n secrets,\n pluginConfig,\n startUpload,\n onClose,\n}: {\n stagedUpload: StagedUpload\n secrets: Secrets\n pluginConfig: PluginConfig\n startUpload: (settings: MuxNewAssetSettings, watermark: WatermarkConfig | undefined) => void\n onClose: () => void\n}) {\n const id = useId()\n const [watermarkValidationError, setWatermarkValidationError] = useState<string | null>(null)\n const watermarkPreviewContainerRef = useRef<HTMLDivElement>(null)\n const watermarkPreviewVideoRef = useRef<HTMLVideoElement>(null)\n const autoTextTracks = useRef<NonNullable<UploadConfig['text_tracks']>>(\n pluginConfig.video_quality === 'plus' && pluginConfig.defaultAutogeneratedSubtitleLang\n ? [\n {\n _id: uuid(),\n type: 'autogenerated',\n language_code: pluginConfig.defaultAutogeneratedSubtitleLang,\n name: LanguagesList.getNativeName(pluginConfig.defaultAutogeneratedSubtitleLang),\n } satisfies AutogeneratedTextTrack,\n ]\n : [],\n ).current\n\n const [config, dispatch] = useReducer(\n (prev: UploadConfig, action: UploadConfigurationStateAction) => {\n switch (action.action) {\n case 'video_quality':\n // If video quality level switches to basic, remove plus-only features\n if (action.value === 'basic') {\n return Object.assign({}, prev, {\n video_quality: action.value,\n static_renditions: [],\n max_resolution_tier: '1080p',\n text_tracks: prev.text_tracks?.filter(({type}) => type !== 'autogenerated'),\n public_policy: true,\n signed_policy: false,\n drm_policy: false,\n })\n // If video quality level switches to plus, add back in default plus features\n }\n return Object.assign({}, prev, {\n video_quality: action.value,\n static_renditions: sanitizeStaticRenditions(pluginConfig.static_renditions || []),\n max_resolution_tier: pluginConfig.max_resolution_tier,\n text_tracks: [...autoTextTracks, ...(prev.text_tracks || [])],\n })\n\n case 'static_renditions':\n case 'max_resolution_tier':\n case 'normalize_audio':\n case 'signed_policy':\n return Object.assign({}, prev, {[action.action]: action.value})\n case 'public_policy':\n return Object.assign({}, prev, {[action.action]: action.value})\n case 'drm_policy':\n return Object.assign({}, prev, {[action.action]: action.value})\n case 'watermark':\n return Object.assign({}, prev, {watermark: action.value})\n // Updating individual tracks\n case 'track': {\n const text_tracks = [...prev.text_tracks]\n const target_track_i = text_tracks.findIndex(({_id}) => _id === action.id)\n switch (action.subAction) {\n case 'add':\n // Exit early if track already exists\n if (target_track_i !== -1) break\n text_tracks.push({\n _id: action.id,\n ...action.value,\n } as AutogeneratedTextTrack)\n break\n case 'update':\n if (target_track_i === -1) break\n text_tracks[target_track_i] = {\n ...text_tracks[target_track_i],\n ...action.value,\n } as UploadTextTrack\n break\n case 'delete':\n if (target_track_i === -1) break\n text_tracks.splice(target_track_i, 1)\n break\n }\n return Object.assign({}, prev, {text_tracks})\n }\n default:\n return prev\n }\n },\n {\n video_quality: pluginConfig.video_quality,\n max_resolution_tier: pluginConfig.max_resolution_tier,\n static_renditions: sanitizeStaticRenditions(pluginConfig.static_renditions || []),\n signed_policy: secrets.enableSignedUrls && pluginConfig.defaultSigned,\n public_policy: pluginConfig.defaultPublic,\n drm_policy: pluginConfig.defaultDrm && !!secrets.drmConfigId,\n normalize_audio: pluginConfig.normalize_audio,\n text_tracks: autoTextTracks,\n } as UploadConfig,\n )\n\n // Video validations\n const [validationError, setValidationError] = useState<string | null>(null)\n const MAX_FILE_SIZE = pluginConfig.maxAssetFileSize\n const MAX_DURATION_SECONDS = pluginConfig.maxAssetDuration\n\n const {fileSize, isLoadingFileSize, canSkipFileSizeValidation} = useFetchFileSize(\n stagedUpload,\n MAX_FILE_SIZE,\n )\n const {videoAssetMetadata, setVideoAssetMetadata, isLoadingMetadata} =\n useMediaMetadata(stagedUpload)\n\n useEffect(() => {\n if (fileSize) {\n setVideoAssetMetadata((old) => ({...old, size: fileSize}))\n }\n }, [fileSize, setVideoAssetMetadata])\n\n useEffect(() => {\n const validateDuration = (duration: number) => {\n if (MAX_DURATION_SECONDS && duration > MAX_DURATION_SECONDS) {\n setValidationError(\n `Video duration (${formatSeconds(duration)}) exceeds maximum allowed duration of ${formatSeconds(MAX_DURATION_SECONDS)}`,\n )\n return false\n }\n return true\n }\n\n const validateFileSize = (size: number): boolean => {\n if (MAX_FILE_SIZE === undefined || size <= MAX_FILE_SIZE) {\n return true\n }\n\n setValidationError(\n `File size (${formatBytes(size)}) exceeds maximum allowed size of ${formatBytes(MAX_FILE_SIZE)}`,\n )\n return false\n }\n\n const validateDrmAvailability = (isAudioOnly: boolean) => {\n if (config.drm_policy && isAudioOnly) {\n setValidationError('Audio-only asset cannot be DRM protected')\n return false\n }\n return true\n }\n\n let valid = true\n if (videoAssetMetadata?.size) {\n valid = valid && (canSkipFileSizeValidation || validateFileSize(videoAssetMetadata.size))\n }\n if (videoAssetMetadata?.duration) {\n valid = valid && validateDuration(videoAssetMetadata.duration)\n }\n if (videoAssetMetadata?.isAudioOnly != undefined) {\n valid = valid && validateDrmAvailability(videoAssetMetadata.isAudioOnly)\n }\n if (valid) {\n setValidationError(null)\n }\n }, [\n MAX_FILE_SIZE,\n MAX_DURATION_SECONDS,\n canSkipFileSizeValidation,\n videoAssetMetadata?.duration,\n videoAssetMetadata?.size,\n videoAssetMetadata?.height,\n videoAssetMetadata?.width,\n videoAssetMetadata,\n config.drm_policy,\n validationError,\n ])\n\n // If user-provided config is disabled, begin the upload immediately with\n // the developer-specified values from the schema or config or defaults.\n // This can include auto-generated subtitles!\n const {disableTextTrackConfig, disableUploadConfig} = pluginConfig\n const skipConfig = disableTextTrackConfig && disableUploadConfig\n useEffect(() => {\n if (skipConfig) {\n const {settings, watermark} = formatUploadConfig(config, secrets, {\n videoAspectRatio: videoAssetMetadata?.aspectRatio,\n })\n startUpload(settings, watermark)\n }\n // oxlint-disable-next-line react/rule-suppression\n // oxlint-disable-next-line react/exhaustive-deps -- intentionally mount-only: start upload once with developer-specified config\n }, [])\n if (skipConfig) return null\n\n const basicConfig = config.video_quality !== 'plus' && config.video_quality !== 'premium'\n const playbackPolicySelected = config.public_policy || config.signed_policy || config.drm_policy\n const maxSupportedResolution = RESOLUTION_TIERS.findIndex(\n (rt) => rt.value === pluginConfig.max_resolution_tier,\n )\n return (\n <Dialog\n animate\n open\n id=\"upload-configuration\"\n zOffset={1000}\n width={1}\n header=\"Configure Mux Upload\"\n onClose={onClose}\n >\n <Stack padding={4} gap={2}>\n {(validationError || watermarkValidationError) && (\n <Card padding={3} tone=\"critical\" radius={2} marginBottom={2}>\n <Flex gap={2} align=\"flex-start\">\n <ErrorOutlineIcon width={20} height={20} />\n <Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n Validation Error\n </Text>\n <Text size={1}>{validationError || watermarkValidationError}</Text>\n </Stack>\n </Flex>\n </Card>\n )}\n <Label size={3}>FILE TO UPLOAD</Label>\n <Card\n tone=\"transparent\"\n border\n padding={3}\n paddingY={4}\n style={{borderRadius: '0.1865rem'}}\n >\n <Flex gap={2}>\n <DocumentVideoIcon fontSize=\"2em\" />\n <Stack gap={2}>\n <Text textOverflow=\"ellipsis\" as=\"h2\" size={3}>\n {stagedUpload.type === 'file' ? stagedUpload.files[0]!.name : stagedUpload.url}\n </Text>\n <Text as=\"p\" size={1} muted>\n {stagedUpload.type === 'file'\n ? `Direct File Upload (${formatBytes(stagedUpload.files[0]!.size)})`\n : (() => {\n if (videoAssetMetadata?.size) {\n return `File From URL (${formatBytes(videoAssetMetadata.size)})`\n }\n if (isLoadingFileSize) {\n return 'File From URL (Loading size...)'\n }\n return 'File From URL (Unknown size)'\n })()}\n </Text>\n {stagedUpload.type === 'file' && (\n <Stack gap={1}>\n {isLoadingMetadata && (\n <Text as=\"p\" size={1} muted>\n Reading video metadata...\n </Text>\n )}\n {videoAssetMetadata?.duration && !validationError && (\n <Text as=\"p\" size={1} muted>\n Duration: {formatSeconds(videoAssetMetadata.duration)}\n </Text>\n )}\n </Stack>\n )}\n </Stack>\n </Flex>\n </Card>\n {!disableUploadConfig && (\n <Stack gap={3} paddingBottom={2}>\n <FormField\n path={[]}\n title=\"Video Quality Level\"\n description={\n <>\n The video quality level informs the cost, quality, and available platform features\n for the asset.{' '}\n <a\n href=\"https://docs.mux.com/guides/use-encoding-tiers\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n See the Mux guide for more details.\n </a>\n </>\n }\n >\n <Flex gap={3}>\n {VIDEO_QUALITY_LEVELS.map(({value, label}) => {\n const inputId = `${id}--encodingtier-${value}`\n return (\n <Flex key={value} align=\"center\" gap={2}>\n <Radio\n checked={config.video_quality === value}\n name=\"asset-encodingtier\"\n onChange={(e) =>\n dispatch({\n action: 'video_quality' as const,\n value: e.currentTarget.value as UploadConfig['video_quality'],\n })\n }\n value={value}\n id={inputId}\n />\n <Text as=\"label\" htmlFor={inputId}>\n {label}\n </Text>\n </Flex>\n )\n })}\n </Flex>\n </FormField>\n\n {!basicConfig && (\n <>\n <FormField title=\"Additional Configuration\" path={[]}>\n <Stack gap={3}>\n <PlaybackPolicy id={id} config={config} secrets={secrets} dispatch={dispatch} />\n {maxSupportedResolution > 0 && (\n <ResolutionTierSelector\n id={id}\n config={config}\n dispatch={dispatch}\n maxSupportedResolution={maxSupportedResolution}\n />\n )}\n <StaticRenditionSelector id={id} config={config} dispatch={dispatch} />\n {!disableTextTrackConfig && (\n <TextTracksEditor\n tracks={config.text_tracks}\n dispatch={dispatch}\n defaultLang={pluginConfig.defaultAutogeneratedSubtitleLang}\n />\n )}\n </Stack>\n </FormField>\n <WatermarkSection\n config={config}\n dispatch={dispatch}\n stagedUpload={stagedUpload}\n videoAssetMetadata={videoAssetMetadata}\n watermarkPreviewContainerRef={watermarkPreviewContainerRef}\n watermarkPreviewVideoRef={watermarkPreviewVideoRef}\n onValidationChange={setWatermarkValidationError}\n />\n </>\n )}\n </Stack>\n )}\n\n <Box marginTop={4}>\n <Button\n disabled={\n (!basicConfig && !playbackPolicySelected) ||\n validationError !== null ||\n isLoadingMetadata ||\n (isLoadingFileSize && !canSkipFileSizeValidation)\n }\n icon={UploadIcon}\n text=\"Upload\"\n tone=\"positive\"\n onClick={() => {\n if (!validationError) {\n const {settings, watermark} = formatUploadConfig(config, secrets, {\n videoAspectRatio: videoAssetMetadata?.aspectRatio,\n })\n startUpload(settings, watermark)\n }\n }}\n />\n </Box>\n </Stack>\n </Dialog>\n )\n}\n\nfunction setAdvancedPlaybackPolicy(\n config: UploadConfig,\n secrets: Secrets,\n): MuxNewAssetSettings['advanced_playback_policies'] {\n const advanced_playback_policies: MuxNewAssetSettings['advanced_playback_policies'] = []\n if (config.public_policy) {\n advanced_playback_policies.push({policy: 'public'})\n }\n if (config.signed_policy) {\n advanced_playback_policies.push({policy: 'signed'})\n }\n if (config.drm_policy) {\n if (secrets.drmConfigId)\n advanced_playback_policies.push({\n policy: 'drm',\n drm_configuration_id: secrets.drmConfigId ?? undefined,\n })\n else {\n console.error('Selected DRM Policy but missing DRM Configuration Id')\n }\n }\n return advanced_playback_policies\n}\n\nfunction formatUploadConfig(\n config: UploadConfig,\n secrets: Secrets,\n options?: {videoAspectRatio?: number | null},\n): {\n settings: MuxNewAssetSettings\n watermark?: WatermarkConfig\n} {\n const generated_subtitles = config.text_tracks\n .filter<AutogeneratedTextTrack>(isAutogeneratedTrack)\n .map<{name: string; language_code: SupportedMuxLanguage}>((track) => ({\n name: track.name,\n language_code: track.language_code,\n }))\n\n const inputs: NonNullable<MuxNewAssetSettings['input']> = [\n {\n type: 'video',\n generated_subtitles: generated_subtitles.length > 0 ? generated_subtitles : undefined,\n },\n ...config.text_tracks.filter<CustomTextTrack>(isCustomTextTrack).reduce(\n (acc, track) => {\n if (track.language_code && track.file && track.name) {\n acc.push({\n url: track.file.contents,\n type: 'text',\n text_type: track.type === 'subtitles' ? 'subtitles' : undefined,\n language_code: track.language_code,\n name: track.name,\n closed_captions: track.type === 'captions',\n })\n }\n return acc\n },\n [] as NonNullable<MuxNewAssetSettings['input']>,\n ),\n ]\n\n if (config.watermark?.imageUrl) {\n const watermarkForMux: WatermarkConfig = {...config.watermark, enabled: true}\n const overlaySettings = convertWatermarkToMuxOverlay(watermarkForMux, {\n videoAspectRatio: options?.videoAspectRatio ?? undefined,\n units: 'px',\n })\n if (overlaySettings) {\n inputs.push({\n url: config.watermark.imageUrl,\n overlay_settings: overlaySettings,\n })\n }\n }\n\n return {\n settings: {\n input: inputs,\n static_renditions:\n config.static_renditions.length > 0\n ? config.static_renditions.map((resolution) => ({resolution}))\n : undefined,\n advanced_playback_policies: setAdvancedPlaybackPolicy(config, secrets),\n max_resolution_tier: config.max_resolution_tier,\n video_quality: config.video_quality,\n normalize_audio: config.normalize_audio,\n },\n watermark: config.watermark?.imageUrl ? {...config.watermark, enabled: true} : undefined,\n }\n}\n\nfunction WatermarkSection({\n config,\n dispatch,\n stagedUpload,\n videoAssetMetadata,\n watermarkPreviewContainerRef,\n watermarkPreviewVideoRef,\n onValidationChange,\n}: {\n config: UploadConfig\n dispatch: (action: UploadConfigurationStateAction) => void\n stagedUpload: StagedUpload\n videoAssetMetadata: VideoAssetMetadata | null\n watermarkPreviewContainerRef: React.RefObject<HTMLDivElement | null>\n watermarkPreviewVideoRef: React.RefObject<HTMLVideoElement | null>\n onValidationChange: (error: string | null) => void\n}) {\n if (videoAssetMetadata?.isAudioOnly !== false) return null\n return (\n <FormField\n path={[]}\n title=\"Watermark\"\n description={\n <>\n Add a watermark overlay to your video using Mux's native watermark support.{' '}\n <a\n href=\"https://www.mux.com/docs/guides/add-watermarks-to-your-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Learn more about Mux watermarks.\n </a>\n </>\n }\n >\n <Stack gap={3}>\n <WatermarkControls\n watermark={config.watermark || {enabled: false}}\n onChange={(watermark) => {\n dispatch({action: 'watermark', value: watermark})\n }}\n onValidationChange={onValidationChange}\n previewContainerRef={watermarkPreviewContainerRef}\n previewVideoRef={watermarkPreviewVideoRef}\n />\n {config.watermark?.imageUrl &&\n stagedUpload.type === 'file' &&\n // Canvas preview is only shown in \"Canvas\" mode (no explicit overlay_settings)\n !config.watermark.overlay_settings && (\n <WatermarkPreview\n stagedUpload={stagedUpload}\n watermark={config.watermark}\n videoAspectRatio={videoAssetMetadata.aspectRatio}\n onWatermarkChange={(watermark) => {\n dispatch({action: 'watermark', value: watermark})\n }}\n previewContainerRef={watermarkPreviewContainerRef}\n videoRef={watermarkPreviewVideoRef}\n />\n )}\n </Stack>\n </FormField>\n )\n}\n\n// Memoized preview component to prevent unnecessary re-renders\nconst WatermarkPreview = memo(function WatermarkPreview({\n stagedUpload,\n watermark,\n onWatermarkChange,\n videoAspectRatio,\n previewContainerRef,\n videoRef,\n}: {\n stagedUpload: StagedUpload\n watermark: WatermarkConfig\n onWatermarkChange: (watermark: WatermarkConfig) => void\n videoAspectRatio?: number | null\n previewContainerRef: React.RefObject<HTMLDivElement | null>\n videoRef: React.RefObject<HTMLVideoElement | null>\n}) {\n // Initialize video source only once\n useEffect(() => {\n if (videoRef.current && stagedUpload.type === 'file') {\n const file = stagedUpload.files[0]\n const url = URL.createObjectURL(file!)\n videoRef.current.src = url\n\n return () => {\n URL.revokeObjectURL(url)\n }\n }\n return undefined\n }, [stagedUpload, videoRef])\n\n const isVertical =\n videoAspectRatio !== null && videoAspectRatio !== undefined && videoAspectRatio < 1\n\n return (\n <Card\n tone=\"transparent\"\n border\n style={{\n overflow: 'hidden',\n // For vertical videos, center the preview and limit its width\n display: 'flex',\n justifyContent: 'center',\n }}\n >\n {/* Inner container that exactly matches the video aspect ratio - no padding, no letterbox */}\n <div\n ref={previewContainerRef}\n style={{\n position: 'relative',\n // For vertical videos: limit width so the preview doesn't get too tall\n // For horizontal videos: use full width\n width: isVertical ? 'auto' : '100%',\n aspectRatio: videoAspectRatio ? String(videoAspectRatio) : '16/9',\n ...(isVertical ? {height: '400px', maxHeight: '50vh'} : {minHeight: '200px'}),\n overflow: 'hidden',\n }}\n >\n <video\n ref={videoRef}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n objectFit: 'fill',\n display: 'block',\n }}\n />\n <DraggableWatermark\n watermark={watermark}\n onChange={onWatermarkChange}\n containerRef={previewContainerRef as React.RefObject<HTMLDivElement>}\n videoElementRef={videoRef as React.RefObject<HTMLVideoElement>}\n />\n </div>\n </Card>\n )\n})\n","import {rem} from '@sanity/ui'\nimport type {ComponentType} from 'react'\nimport {css, styled} from 'styled-components'\n\nimport {focusRingBorderStyle, focusRingStyle} from './helpers'\n\nexport function withFocusRing<Props extends object>(component: ComponentType<Props>) {\n // `$border` is the only consumer-facing addition; `theme` comes from styled-components\n // (injected via DefaultTheme / ExecutionContext) and must not appear on public props.\n return styled(component)<{$border?: boolean}>(({$border, theme}) => {\n const border = {\n width: $border ? 1 : 0,\n color: 'var(--card-border-color)',\n }\n\n return css`\n --card-focus-box-shadow: ${focusRingBorderStyle(border)};\n\n border-radius: ${rem(\n // oxlint-disable-next-line no-deprecated -- deferred to a follow-up PR\n theme.sanity.radius[1]!,\n )};\n outline: none;\n box-shadow: var(--card-focus-box-shadow);\n\n &:focus {\n --card-focus-box-shadow: ${focusRingStyle({\n base:\n // oxlint-disable-next-line no-deprecated -- deferred to a follow-up PR\n theme.sanity.color.base,\n border,\n focusRing:\n // oxlint-disable-next-line no-deprecated -- deferred to a follow-up PR\n theme.sanity.focusRing,\n })};\n }\n `\n })\n}\n","import {Card, type CardTone} from '@sanity/ui'\nimport {useCallback, useRef} from 'react'\nimport {styled} from 'styled-components'\n\nimport {withFocusRing} from './withFocusRing'\n\nconst UploadCardWithFocusRing = withFocusRing(Card)\n\ninterface UploadCardProps {\n tone?: CardTone\n children: React.ReactNode\n onPaste: React.ClipboardEventHandler<HTMLInputElement>\n onDrop: React.DragEventHandler<HTMLDivElement>\n onDragOver: React.DragEventHandler<HTMLDivElement>\n onDragLeave: React.DragEventHandler<HTMLDivElement>\n onDragEnter: React.DragEventHandler<HTMLDivElement>\n}\nexport function UploadCard({\n children,\n tone,\n onPaste,\n onDrop,\n onDragEnter,\n onDragLeave,\n onDragOver,\n ref,\n}: UploadCardProps & {ref?: React.Ref<HTMLDivElement>}) {\n const inputRef = useRef<HTMLInputElement>(null)\n const handleKeyDown = useCallback<React.KeyboardEventHandler<HTMLDivElement>>((event) => {\n const target = event.target as HTMLElement\n\n // Don't steal focus when pasting into the VTT input\n if (target.closest('#vtt-url')) {\n return\n }\n\n if ((event.ctrlKey || event.metaKey) && event.key === 'v') {\n inputRef.current!.focus()\n }\n }, [])\n\n return (\n <UploadCardWithFocusRing\n tone={tone}\n ref={ref}\n padding={0}\n radius={2}\n shadow={0}\n tabIndex={0}\n onKeyDown={handleKeyDown}\n onPaste={onPaste}\n onDrop={onDrop}\n onDragEnter={onDragEnter}\n onDragLeave={onDragLeave}\n onDragOver={onDragOver}\n >\n <HiddenInput ref={inputRef} />\n {children}\n </UploadCardWithFocusRing>\n )\n}\n\nconst HiddenInput = styled.input.attrs({type: 'text'})`\n position: absolute;\n border: 0;\n color: white;\n opacity: 0;\n\n &:focus {\n outline: none;\n }\n`\n","import {Button, type ButtonProps} from '@sanity/ui'\nimport {useCallback, useId, useRef} from 'react'\nimport {styled} from 'styled-components'\n\nconst HiddenInput = styled.input`\n overflow: hidden;\n width: 0.1px;\n height: 0.1px;\n opacity: 0;\n position: absolute;\n z-index: -1;\n`\n\nconst Label = styled.label`\n position: relative;\n`\n\nexport interface FileInputButtonProps extends Omit<ButtonProps, 'onSelect'> {\n onSelect: (files: FileList) => void\n accept: string\n}\nexport const FileInputButton = ({onSelect, accept, ...props}: FileInputButtonProps) => {\n const inputId = `FileSelect${useId()}`\n const inputRef = useRef<HTMLInputElement>(null)\n const handleSelect = useCallback<React.ChangeEventHandler<HTMLInputElement>>(\n (event) => {\n if (onSelect) {\n onSelect(event.target.files!)\n }\n },\n [onSelect],\n )\n const handleButtonClick = useCallback(() => inputRef.current?.click(), [])\n return (\n <Label htmlFor={inputId}>\n <HiddenInput\n accept={accept}\n ref={inputRef}\n tabIndex={0}\n type=\"file\"\n id={inputId}\n onChange={handleSelect}\n value=\"\"\n />\n <Button\n onClick={handleButtonClick}\n mode=\"default\"\n tone=\"primary\"\n style={{width: '100%'}}\n {...props}\n />\n </Label>\n )\n}\n","import {DocumentVideoIcon} from '@sanity/icons/DocumentVideo'\nimport {PlugIcon} from '@sanity/icons/Plug'\nimport {SearchIcon} from '@sanity/icons/Search'\nimport {UploadIcon} from '@sanity/icons/Upload'\nimport {Button, Card, Flex, Inline, Text} from '@sanity/ui'\nimport {useCallback} from 'react'\n\nimport {useAccessControl} from '../hooks/useAccessControl'\nimport type {SetDialogState} from '../hooks/useDialogState'\nimport {type PluginConfig} from '../util/types'\nimport {FileInputButton, type FileInputButtonProps} from './FileInputButton'\n\nfunction formatAcceptString(accept: string): string {\n return accept\n .split(',')\n .map((type) => type.trim().replace('/*', ''))\n .join(' or ')\n}\n\ninterface UploadPlaceholderProps {\n setDialogState: SetDialogState\n readOnly: boolean\n hovering: boolean\n needsSetup: boolean\n onSelect: FileInputButtonProps['onSelect']\n config: PluginConfig\n accept: string\n}\nexport default function UploadPlaceholder(props: UploadPlaceholderProps) {\n const {setDialogState, readOnly, onSelect, hovering, needsSetup, accept} = props\n const handleBrowse = useCallback(() => setDialogState('select-video'), [setDialogState])\n const handleConfigureApi = useCallback(() => setDialogState('secrets'), [setDialogState])\n const {hasConfigAccess} = useAccessControl(props.config)\n\n return (\n <Card\n sizing=\"border\"\n tone={readOnly ? 'transparent' : 'inherit'}\n border\n radius={2}\n paddingX={3}\n paddingY={1}\n style={hovering ? {borderColor: 'transparent'} : undefined}\n >\n <Flex\n align=\"center\"\n justify=\"space-between\"\n gap={4}\n direction={['column', 'column', 'row']}\n paddingY={2}\n sizing=\"border\"\n >\n <Flex align=\"center\" justify=\"flex-start\" gap={2} flex={1}>\n <Flex justify=\"center\">\n <Text muted>\n <DocumentVideoIcon />\n </Text>\n </Flex>\n <Flex justify=\"center\">\n <Text size={1} muted>\n Drag {formatAcceptString(accept)} file or paste URL here\n </Text>\n </Flex>\n </Flex>\n <Inline gap={2}>\n <FileInputButton\n accept={accept}\n mode=\"bleed\"\n tone=\"default\"\n icon={UploadIcon}\n text=\"Upload\"\n onSelect={onSelect}\n />\n <Button mode=\"bleed\" icon={SearchIcon} text=\"Select\" onClick={handleBrowse} />\n\n {hasConfigAccess && (\n <Button\n padding={3}\n radius={3}\n tone={needsSetup ? 'critical' : undefined}\n onClick={handleConfigureApi}\n icon={PlugIcon}\n mode=\"bleed\"\n title=\"Configure plugin credentials\"\n />\n )}\n </Inline>\n </Flex>\n </Card>\n )\n}\n","import {ErrorOutlineIcon} from '@sanity/icons/ErrorOutline'\nimport {Button, type CardTone, Flex, Text} from '@sanity/ui'\nimport {useToast} from '@sanity/ui/toast'\nimport {useCallback, useEffect, useReducer, useRef, useState} from 'react'\nimport {type Observable, Subject, Subscription} from 'rxjs'\nimport {takeUntil, tap} from 'rxjs/operators'\nimport type {SanityClient} from 'sanity'\nimport {PatchEvent, set, setIfMissing} from 'sanity'\n\nimport {uploadFile, uploadUrl} from '../actions/upload'\nimport {DialogStateProvider} from '../context/DialogStateContext'\nimport {type DialogState, type SetDialogState} from '../hooks/useDialogState'\nimport {isServerError, isValidUrl} from '../util/asserters'\nimport {extractDroppedFiles} from '../util/extractFiles'\nimport {hasPlaybackPolicy} from '../util/getPlaybackPolicy'\nimport type {\n MuxInputProps,\n MuxNewAssetSettings,\n PluginConfig,\n Secrets,\n VideoAssetDocument,\n} from '../util/types'\nimport InputBrowser from './InputBrowser'\nimport Player from './Player'\nimport PlayerActionsMenu from './PlayerActionsMenu'\nimport UploadConfiguration from './UploadConfiguration'\nimport {UploadCard} from './Uploader.styled'\nimport UploadPlaceholder from './UploadPlaceholder'\nimport {UploadProgress} from './UploadProgress'\n\ninterface Props extends Pick<MuxInputProps, 'onChange' | 'readOnly'> {\n config: PluginConfig\n client: SanityClient\n secrets: Secrets\n asset: VideoAssetDocument | null | undefined\n dialogState: DialogState\n setDialogState: SetDialogState\n needsSetup: boolean\n}\n\nexport type StagedUpload = {type: 'file'; files: FileList | File[]} | {type: 'url'; url: string}\ntype UploadStatus = {\n progress: number\n file?: {name: string | undefined; type: string}\n uuid?: string\n url?: string\n}\n\ninterface State {\n stagedUpload: StagedUpload | null\n uploadStatus: UploadStatus | null\n error: Error | null\n}\n\nconst INITIAL_STATE: State = {\n stagedUpload: null,\n uploadStatus: null,\n error: null,\n}\n\ntype UploadFileEvent = ReturnType<typeof uploadFile> extends Observable<infer T> ? T : never\ntype UploadUrlEvent = ReturnType<typeof uploadUrl> extends Observable<infer T> ? T : never\ntype UploaderStateAction =\n | {action: 'stageUpload'; input: NonNullable<State['stagedUpload']>}\n | {action: 'commitUpload'}\n | ({action: 'progressInfo'} & (\n | Extract<UploadFileEvent, {type: 'uuid' | 'file'}>\n | Extract<UploadUrlEvent, {type: 'url'}>\n ))\n | {action: 'progress'; percent: number}\n | {action: 'error'; error: Error; settings: MuxNewAssetSettings}\n | {action: 'complete' | 'reset'}\n\n/**\n * The main interface for inputting a Mux Video. It handles staging an upload\n * file, setting its configuration, displaying upload progress, and showing\n * the preview player.\n */\nexport default function Uploader(props: Props) {\n const toast = useToast()\n const containerRef = useRef<HTMLDivElement>(null)\n\n const dragEnteredEls = useRef<EventTarget[]>([])\n const [dragState, setDragState] = useState<'valid' | 'invalid' | null>(null)\n\n const cancelUploadButton = useRef(\n (() => {\n const events$ = new Subject()\n return {\n observable: events$.asObservable(),\n handleClick: (event: React.MouseEvent<HTMLButtonElement>) => events$.next(event),\n }\n })(),\n ).current\n\n const uploadRef = useRef<Subscription | null>(null)\n const uploadingDocumentId = useRef<string | null>(null)\n const [state, dispatch] = useReducer(\n // oxlint-disable-next-line react/refs\n (prev: State, action: UploaderStateAction) => {\n switch (action.action) {\n case 'stageUpload':\n return Object.assign({}, INITIAL_STATE, {stagedUpload: action.input})\n case 'commitUpload':\n return Object.assign({}, prev, {uploadStatus: {progress: 0}})\n case 'progressInfo': {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {type, action: _, ...payload} = action\n return Object.assign({}, prev, {\n uploadStatus: {\n ...prev.uploadStatus,\n progress: prev.uploadStatus!.progress,\n ...payload,\n },\n } satisfies Pick<typeof prev, 'uploadStatus'>)\n }\n case 'progress':\n return Object.assign({}, prev, {\n uploadStatus: {\n ...prev.uploadStatus,\n progress: action.percent,\n },\n } satisfies Pick<typeof prev, 'uploadStatus'>)\n case 'reset':\n case 'complete':\n // Clear upload observable on completion\n uploadRef.current?.unsubscribe()\n uploadRef.current = null\n uploadingDocumentId.current = null\n return INITIAL_STATE\n case 'error': {\n // Clear upload observable on error\n uploadRef.current?.unsubscribe()\n uploadRef.current = null\n uploadingDocumentId.current = null\n\n let error = action.error\n if (isServerError(action.error) && hasPlaybackPolicy(action.settings, 'drm')) {\n error = new Error(\n 'Unknown Error while uploading DRM protected content. Make sure your DRM configuration ID is valid and set correctly',\n )\n }\n\n return Object.assign({}, INITIAL_STATE, {error: error})\n }\n default:\n return prev\n }\n },\n {\n stagedUpload: null,\n uploadStatus: null,\n error: null,\n },\n )\n\n // Make sure we close out the upload observer on dismount\n // and cleanup orphaned documents if upload was in progress\n useEffect(() => {\n const cleanup = () => {\n // Cancel subscription\n if (uploadRef.current && !uploadRef.current.closed) {\n uploadRef.current.unsubscribe()\n }\n\n // Delete orphaned document if upload was in progress and document is different from the saved asset\n if (uploadingDocumentId.current && props.asset?._id !== uploadingDocumentId.current) {\n const docId = uploadingDocumentId.current\n uploadingDocumentId.current = null\n\n props.client.delete(docId).catch((err) => {\n console.warn('Failed to cleanup orphaned upload document:', err)\n })\n }\n }\n\n const handleBeforeUnload = () => {\n cleanup()\n }\n\n window.addEventListener('beforeunload', handleBeforeUnload)\n window.addEventListener('pagehide', handleBeforeUnload)\n\n return () => {\n window.removeEventListener('beforeunload', handleBeforeUnload)\n window.removeEventListener('pagehide', handleBeforeUnload)\n cleanup()\n }\n }, [props.client, props.asset?._id])\n\n /* -------------------------------------------------------------------------- */\n /* Uploading */\n /* -------------------------------------------------------------------------- */\n\n /**\n * Begins a file or URL upload with the staged files or URL.\n *\n * Should only be called from the UploadConfiguration component, which provides\n * the Mux configuration for the direct asset upload.\n *\n * @param settings The Mux new_asset_settings object to send to Sanity\n * @param watermark Optional watermark configuration\n * @returns\n */\n const startUpload = (\n settings: MuxNewAssetSettings,\n watermark?: import('../util/types').WatermarkConfig,\n ) => {\n const {stagedUpload} = state\n if (!stagedUpload || uploadRef.current) return\n dispatch({action: 'commitUpload'})\n let uploadObservable: Observable<UploadFileEvent | UploadUrlEvent>\n switch (stagedUpload.type) {\n case 'url':\n uploadObservable = uploadUrl({\n client: props.client,\n url: stagedUpload.url,\n settings,\n watermark,\n })\n break\n case 'file':\n uploadObservable = uploadFile({\n client: props.client,\n file: stagedUpload.files[0]!,\n settings,\n watermark,\n }).pipe(\n takeUntil(\n cancelUploadButton.observable.pipe(\n tap(() => {\n if (uploadingDocumentId.current) {\n void props.client.delete(uploadingDocumentId.current)\n uploadingDocumentId.current = null\n }\n }),\n ),\n ),\n )\n break\n }\n uploadRef.current = uploadObservable.subscribe({\n next: (event) => {\n switch (event.type) {\n case 'uuid':\n // Track the document ID for cleanup on unmount\n uploadingDocumentId.current = event.uuid\n dispatch({action: 'progressInfo', ...event})\n break\n case 'file':\n case 'url':\n dispatch({action: 'progressInfo', ...event})\n break\n case 'progress':\n dispatch({action: 'progress', percent: event.percent})\n break\n case 'success':\n dispatch({action: 'progress', percent: 100})\n uploadingDocumentId.current = null\n props.onChange(\n PatchEvent.from([\n setIfMissing({asset: {}}),\n set({_type: 'reference', _weak: true, _ref: event.asset._id}, ['asset']),\n ]),\n )\n break\n case 'pause':\n case 'resume':\n default:\n break\n }\n },\n complete: () => dispatch({action: 'complete'}),\n error: (error) => dispatch({action: 'error', error, settings}),\n })\n }\n\n const invalidFileToast = useCallback(() => {\n toast.push({\n status: 'error',\n title: `Invalid file type. Accepted types: ${props.config.acceptedMimeTypes?.join(', ')}`,\n })\n }, [props.config.acceptedMimeTypes, toast])\n\n /**\n * Validates if any file in the provided FileList or File array has an unsupported MIME type\n * @param files - FileList or File array to validate\n * @returns true if any file has an invalid MIME type, false if all files are valid\n */\n const isInvalidFile = (files: FileList | File[]) => {\n const isInvalid = Array.from(files).some((file) => {\n return !props.config.acceptedMimeTypes?.some((acceptedType) => {\n // Convert mime type pattern to regex (e.g., 'audio/*' -> /^audio\\/.*$/)\n const pattern = `^${acceptedType.replace('*', '.*')}$`\n return new RegExp(pattern).test(file.type)\n })\n })\n\n return isInvalid\n }\n\n /* -------------------------- Upload Initialization ------------------------- */\n // The below populate the uploadInput state field, which then triggers the\n // upload configuration, or the startUpload function if no config is required.\n\n // Stages an upload from the file selector\n const handleUpload = (files: FileList | File[]) => {\n if (isInvalidFile(files)) return\n dispatch({\n action: 'stageUpload',\n input: {type: 'file', files},\n })\n }\n\n // Stages and validates an upload from pasting an asset URL\n const handlePaste: React.ClipboardEventHandler<HTMLInputElement> = (event) => {\n const target = event.target as HTMLElement\n\n // Ignore paste coming from the VTT URL input\n if (target.closest('#vtt-url')) {\n return\n }\n\n event.preventDefault()\n event.stopPropagation()\n const clipboardData =\n event.clipboardData || (window as Window & {clipboardData?: DataTransfer}).clipboardData\n const url = clipboardData?.getData('text')?.trim()\n if (!isValidUrl(url)) {\n toast.push({status: 'error', title: 'Invalid URL for Mux video input.'})\n return\n }\n dispatch({action: 'stageUpload', input: {type: 'url', url: url}})\n }\n\n // Stages and validates an upload from dragging+dropping files or folders\n const handleDrop: React.DragEventHandler<HTMLDivElement> = (event) => {\n event.preventDefault()\n event.stopPropagation()\n if (dragState === 'invalid') {\n invalidFileToast()\n setDragState(null)\n return\n }\n setDragState(null)\n void extractDroppedFiles(event.nativeEvent.dataTransfer!).then((files) => {\n dispatch({\n action: 'stageUpload',\n input: {type: 'file', files},\n })\n })\n }\n\n /* ------------------------------- Drag State ------------------------------- */\n\n const handleDragOver: React.DragEventHandler<HTMLDivElement> = (event) => {\n event.preventDefault()\n event.stopPropagation()\n }\n\n const handleDragEnter: React.DragEventHandler<HTMLDivElement> = (event) => {\n event.stopPropagation()\n dragEnteredEls.current.push(event.target)\n const type = event.dataTransfer.items?.[0]?.type\n const mimeTypes = props.config.acceptedMimeTypes\n\n // Check if the dragged file type matches any of the accepted mime types\n const isValidType = mimeTypes?.some((acceptedType) => {\n // Convert mime type pattern to regex (e.g., 'video/*' -> /^video\\/.*$/)\n const pattern = `^${acceptedType.replace('*', '.*')}$`\n return new RegExp(pattern).test(type!)\n })\n\n setDragState(isValidType ? 'valid' : 'invalid')\n }\n\n const handleDragLeave: React.DragEventHandler<HTMLDivElement> = (event) => {\n event.stopPropagation()\n const idx = dragEnteredEls.current.indexOf(event.target)\n if (idx > -1) {\n dragEnteredEls.current.splice(idx, 1)\n }\n if (dragEnteredEls.current.length === 0) {\n setDragState(null)\n }\n }\n\n /* -------------------------------- Rendering ------------------------------- */\n\n // Upload has errored\n if (state.error !== null) {\n const error = state.error\n return (\n <Flex gap={3} direction=\"column\" justify=\"center\" align=\"center\">\n <Text size={5} muted>\n <ErrorOutlineIcon />\n </Text>\n <Text>Something went wrong</Text>\n {error instanceof Error && error.message && (\n <Text size={1} muted weight=\"semibold\" style={{textAlign: 'center'}}>\n {error.message}\n </Text>\n )}\n <Button text=\"Upload another file\" onClick={() => dispatch({action: 'reset'})} />\n </Flex>\n )\n }\n\n // Upload is in progress\n if (state.uploadStatus !== null) {\n const {uploadStatus} = state\n return (\n <UploadProgress\n // oxlint-disable-next-line react/refs\n onCancel={cancelUploadButton.handleClick}\n progress={uploadStatus.progress}\n filename={uploadStatus.file?.name || uploadStatus.url}\n />\n )\n }\n\n // Upload needs configuration\n if (state.stagedUpload !== null) {\n return (\n <UploadConfiguration\n stagedUpload={state.stagedUpload}\n pluginConfig={props.config}\n secrets={props.secrets}\n startUpload={startUpload}\n onClose={() => dispatch({action: 'reset'})}\n />\n )\n }\n\n // Default: No staged upload\n let tone: CardTone | undefined\n if (dragState) tone = dragState === 'valid' ? 'positive' : 'critical'\n\n const acceptMimeString = props.config?.acceptedMimeTypes?.length\n ? props.config.acceptedMimeTypes.join(',')\n : 'video/*, audio/*'\n\n return (\n <>\n <UploadCard\n tone={tone}\n onDrop={handleDrop}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDragEnter={handleDragEnter}\n onPaste={handlePaste}\n ref={containerRef}\n >\n {props.asset ? (\n <DialogStateProvider\n dialogState={props.dialogState}\n setDialogState={props.setDialogState}\n >\n <Player\n readOnly={props.readOnly}\n asset={props.asset}\n onChange={props.onChange}\n config={props.config}\n buttons={\n <PlayerActionsMenu\n accept={acceptMimeString}\n asset={props.asset}\n dialogState={props.dialogState}\n setDialogState={props.setDialogState}\n onChange={props.onChange}\n onSelect={handleUpload}\n readOnly={props.readOnly}\n config={props.config}\n />\n }\n />\n </DialogStateProvider>\n ) : (\n <UploadPlaceholder\n accept={acceptMimeString}\n hovering={dragState !== null}\n onSelect={handleUpload}\n readOnly={!!props.readOnly}\n setDialogState={props.setDialogState}\n needsSetup={props.needsSetup}\n config={props.config}\n />\n )}\n </UploadCard>\n {props.dialogState === 'select-video' && (\n <InputBrowser\n config={props.config}\n asset={props.asset}\n onChange={props.onChange}\n setDialogState={props.setDialogState}\n />\n )}\n </>\n )\n}\n","import {Card} from '@sanity/ui'\nimport {memo, Suspense} from 'react'\n\nimport {useAccessControl} from '../hooks/useAccessControl'\nimport {useAssetDocumentValues} from '../hooks/useAssetDocumentValues'\nimport {useClient} from '../hooks/useClient'\nimport {useDialogState} from '../hooks/useDialogState'\nimport {useMuxPolling} from '../hooks/useMuxPolling'\nimport {useSecretsDocumentValues} from '../hooks/useSecretsDocumentValues'\nimport type {MuxInputProps, PluginConfig} from '../util/types'\nimport {ConfigureApiDialog} from './ConfigureApi'\nimport ErrorBoundaryCard from './ErrorBoundaryCard'\nimport {InputFallback} from './Input.styled'\nimport Onboard from './Onboard'\nimport Uploader from './Uploader'\n\nexport interface InputProps extends MuxInputProps {\n config: PluginConfig\n}\nconst Input = (props: InputProps) => {\n const client = useClient()\n const secretDocumentValues = useSecretsDocumentValues()\n const assetDocumentValues = useAssetDocumentValues(props.value?.asset)\n const poll = useMuxPolling(props.readOnly ? undefined : assetDocumentValues?.value || undefined)\n const [dialogState, setDialogState] = useDialogState()\n const {hasConfigAccess} = useAccessControl(props.config)\n\n const error = secretDocumentValues.error || assetDocumentValues.error || poll.error /*||\n // @TODO move errored logic to Uploader, where handleRemoveVideo can be called\n (assetDocumentValues.value?.status === 'errored'\n ? new Error(assetDocumentValues.value.data?.errors?.messages?.join(' '))\n : undefined)\n // */\n if (error) {\n // @TODO deal with it more gracefully\n throw error\n }\n const isLoading = secretDocumentValues.isLoading || assetDocumentValues.isLoading\n\n return (\n <Card>\n <ErrorBoundaryCard schemaType={props.schemaType}>\n <Suspense fallback={<InputFallback />}>\n {isLoading ? (\n <InputFallback />\n ) : (\n <>\n {secretDocumentValues.value.needsSetup && !assetDocumentValues.value ? (\n <Onboard setDialogState={setDialogState} config={props.config} />\n ) : (\n <Uploader\n {...props}\n config={props.config}\n onChange={props.onChange}\n client={client}\n secrets={secretDocumentValues.value.secrets}\n asset={assetDocumentValues.value}\n dialogState={dialogState}\n setDialogState={setDialogState}\n needsSetup={secretDocumentValues.value.needsSetup}\n />\n )}\n\n {dialogState === 'secrets' && hasConfigAccess && (\n <ConfigureApiDialog\n setDialogState={setDialogState}\n secrets={secretDocumentValues.value.secrets}\n />\n )}\n </>\n )}\n </Suspense>\n </ErrorBoundaryCard>\n </Card>\n )\n}\n\nexport default memo(Input)\n","import Input from './components/Input'\nimport VideoThumbnail from './components/VideoThumbnail'\nimport {MuxApiHostProvider} from './context/MuxApiHostContext'\nimport type {MuxInputProps, PluginConfig, VideoAssetDocument} from './util/types'\n\nexport function muxVideoCustomRendering(config: PluginConfig) {\n return {\n components: {\n input: (props: MuxInputProps) => (\n <MuxApiHostProvider muxApiHost={config.muxApiHost}>\n <Input config={{...config, ...props.schemaType.options}} {...props} />\n </MuxApiHostProvider>\n ),\n },\n preview: {\n select: {\n filename: 'asset.filename',\n playbackId: 'asset.playbackId',\n status: 'asset.status',\n assetId: 'asset.assetId',\n thumbTime: 'asset.thumbTime',\n data: 'asset.data',\n },\n prepare: (asset: Partial<VideoAssetDocument>) => {\n const {filename, playbackId, status} = asset\n return {\n title: filename || playbackId || '',\n subtitle: status ? `status: ${status}` : null,\n media: asset.playbackId ? <VideoThumbnail asset={asset} width={64} /> : null,\n }\n },\n },\n }\n}\n","export const muxVideoSchema = {\n name: 'mux.video',\n type: 'object',\n title: 'Video asset reference',\n fields: [\n {\n title: 'Video',\n name: 'asset',\n type: 'reference',\n weak: true,\n to: [{type: 'mux.videoAsset'}],\n },\n ],\n}\n\nconst muxTrack = {\n name: 'mux.track',\n type: 'object',\n fields: [\n {type: 'string', name: 'id'},\n {type: 'string', name: 'type'},\n {type: 'number', name: 'max_width'},\n {type: 'number', name: 'max_frame_rate'},\n {type: 'number', name: 'duration'},\n {type: 'number', name: 'max_height'},\n {type: 'string', name: 'language_code'},\n {type: 'string', name: 'name'},\n {type: 'string', name: 'status'},\n {type: 'string', name: 'text_source'},\n {type: 'string', name: 'text_type'},\n ],\n}\n\nconst muxPlaybackId = {\n name: 'mux.playbackId',\n type: 'object',\n fields: [\n {type: 'string', name: 'id'},\n {type: 'string', name: 'policy'},\n ],\n}\n\nconst muxStaticRenditionFile = {\n name: 'mux.staticRenditionFile',\n type: 'object',\n fields: [\n {type: 'string', name: 'name'},\n {type: 'string', name: 'ext'},\n {type: 'number', name: 'height'},\n {type: 'number', name: 'width'},\n {type: 'number', name: 'bitrate'},\n {type: 'string', name: 'filesize'},\n {type: 'string', name: 'type'},\n {type: 'string', name: 'status'},\n {type: 'string', name: 'resolution_tier'},\n {type: 'string', name: 'resolution'},\n {type: 'string', name: 'id'},\n {type: 'string', name: 'passthrough'},\n ],\n}\n\nconst muxStaticRenditions = {\n name: 'mux.staticRenditions',\n type: 'object',\n fields: [\n {type: 'string', name: 'status'},\n {\n name: 'files',\n type: 'array',\n of: [{type: 'mux.staticRenditionFile'}],\n },\n ],\n}\n\nconst muxMasterFile = {\n name: 'mux.masterFile',\n type: 'object',\n fields: [\n {type: 'string', name: 'status'},\n {type: 'string', name: 'url'},\n ],\n}\n\nconst muxAssetData = {\n name: 'mux.assetData',\n title: 'Mux asset data',\n type: 'object',\n fields: [\n {\n type: 'string',\n name: 'resolution_tier',\n },\n {\n type: 'string',\n name: 'upload_id',\n },\n {\n type: 'string',\n name: 'created_at',\n },\n {\n type: 'string',\n name: 'id',\n },\n {\n type: 'string',\n name: 'status',\n },\n {\n type: 'string',\n name: 'max_stored_resolution',\n },\n {\n type: 'string',\n name: 'passthrough',\n },\n {\n type: 'string',\n name: 'encoding_tier',\n },\n {\n type: 'string',\n name: 'video_quality',\n },\n {\n type: 'string',\n name: 'master_access',\n },\n {\n type: 'string',\n name: 'aspect_ratio',\n },\n {\n type: 'number',\n name: 'duration',\n },\n {\n type: 'number',\n name: 'max_stored_frame_rate',\n },\n {\n type: 'string',\n name: 'mp4_support',\n },\n {\n type: 'string',\n name: 'max_resolution_tier',\n },\n {\n name: 'tracks',\n type: 'array',\n of: [{type: 'mux.track'}],\n },\n {\n name: 'playback_ids',\n type: 'array',\n of: [{type: 'mux.playbackId'}],\n },\n {\n name: 'static_renditions',\n type: 'mux.staticRenditions',\n },\n {\n name: 'master',\n type: 'mux.masterFile',\n },\n ],\n}\n\nconst muxVideoAsset = {\n name: 'mux.videoAsset',\n type: 'document',\n title: 'Video asset',\n fields: [\n {\n type: 'string',\n name: 'status',\n },\n {\n type: 'string',\n name: 'assetId',\n },\n {\n type: 'string',\n name: 'playbackId',\n },\n {\n type: 'string',\n name: 'filename',\n },\n {\n type: 'number',\n name: 'thumbTime',\n },\n {\n type: 'mux.assetData',\n name: 'data',\n },\n ],\n}\n\nexport const schemaTypes = [\n muxTrack,\n muxPlaybackId,\n muxStaticRenditionFile,\n muxStaticRenditions,\n muxMasterFile,\n muxAssetData,\n muxVideoAsset,\n]\n","import '@sanity/ui/styles.css'\nimport {definePlugin} from 'sanity'\n\nimport createStudioTool, {DEFAULT_TOOL_CONFIG} from '../components/StudioTool'\nimport {muxVideoCustomRendering} from '../plugin'\nimport {muxVideoSchema, schemaTypes} from '../schema'\nimport {normalizeMuxApiHost} from '../util/muxAddonClient'\nimport type {PluginConfig, StaticRenditionResolution} from '../util/types'\nexport type {VideoAssetDocument} from '../util/types'\n\nexport const defaultConfig: PluginConfig = {\n static_renditions: [],\n // oxlint-disable-next-line no-deprecated -- kept for backwards-compatible defaults until next major\n mp4_support: 'none',\n video_quality: 'plus',\n max_resolution_tier: '1080p',\n normalize_audio: false,\n defaultPublic: true,\n defaultSigned: false,\n defaultDrm: false,\n tool: DEFAULT_TOOL_CONFIG,\n allowedRolesForConfiguration: [],\n acceptedMimeTypes: ['video/*', 'audio/*'],\n}\n\n/**\n * Converts legacy mp4_support configuration to static_renditions format\n */\nfunction convertLegacyConfig(config: Partial<PluginConfig>): {\n static_renditions: StaticRenditionResolution[]\n} {\n // If static_renditions is already provided, use it\n if (config.static_renditions && config.static_renditions.length > 0) {\n return {static_renditions: config.static_renditions}\n }\n\n // Convert legacy mp4_support to static_renditions\n // oxlint-disable-next-line no-deprecated -- migrate legacy plugin option until next major\n if (config.mp4_support === 'standard') {\n return {static_renditions: ['highest']}\n }\n\n return {static_renditions: []}\n}\n\nexport const muxInput = definePlugin<Partial<PluginConfig> | void>((userConfig) => {\n // TODO: Remove this on next major version when we end support for encoding_tier\n if (typeof userConfig === 'object' && 'encoding_tier' in userConfig) {\n // oxlint-disable-next-line no-deprecated -- migrate legacy plugin option until next major\n const deprecated_encoding_tier = userConfig.encoding_tier\n if (!userConfig.video_quality) {\n if (deprecated_encoding_tier === 'baseline') {\n userConfig.video_quality = 'basic'\n }\n if (deprecated_encoding_tier === 'smart') {\n userConfig.video_quality = 'plus'\n }\n }\n }\n const config: PluginConfig = {\n ...defaultConfig,\n ...userConfig,\n ...convertLegacyConfig(userConfig || {}),\n }\n if (config.muxApiHost !== undefined) {\n // Fail early on an invalid value (including an empty string), instead of on the first Mux request\n config.muxApiHost = normalizeMuxApiHost(config.muxApiHost)\n }\n return {\n name: 'mux-input',\n schema: {\n types: [\n ...schemaTypes,\n {\n ...muxVideoSchema,\n ...muxVideoCustomRendering(config),\n },\n ],\n },\n tools: config.tool === false ? undefined : [createStudioTool(config)],\n }\n})\n"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"index.js","names":["{\n muxApiHost,\n children,\n}: {\n muxApiHost: string | undefined\n children: React.ReactNode\n}","<MuxApiHostContext.Provider value={muxApiHost}>{children}</MuxApiHostContext.Provider>","MuxApiHostContext.Provider","_c","<svg\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 24 24\"\n height=\"1em\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M21 3H3c-1.11 0-2 .89-2 2v12c0 1.1.89 2 2 2h5v2h8v-2h5c1.1 0 1.99-.9 1.99-2L23 5c0-1.11-.9-2-2-2zm0 14H3V5h18v12zm-5-6l-7 4V7z\" />\n </svg>","_c","{\n config,\n children,\n}: DrmPlaybackWarningContextProviderProps","warningDisabled || window.localStorage.getItem(LOCAL_STORAGE_HAS_SHOWN_WARNING_KEY) === 'true'","(b: boolean) => {\n window.localStorage.setItem(LOCAL_STORAGE_HAS_SHOWN_WARNING_KEY, b.toString())\n setHasWarnedAboutDrmPlayback(b)\n }","useCallback((b: boolean) => {\n window.localStorage.setItem(LOCAL_STORAGE_HAS_SHOWN_WARNING_KEY, b.toString())\n setHasWarnedAboutDrmPlayback(b)\n }, [])","{\n hasShownWarning: hasWarnedAboutDrmPlayback,\n setHasWarnedAboutDrmPlayback: setHasShownWarning,\n }","useMemo(\n () => ({\n hasShownWarning: hasWarnedAboutDrmPlayback,\n setHasWarnedAboutDrmPlayback: setHasShownWarning,\n }),\n [hasWarnedAboutDrmPlayback, setHasShownWarning],\n )","<DrmPlaybackWarningContext.Provider value={value}>\n {children}\n </DrmPlaybackWarningContext.Provider>","DrmPlaybackWarningContext.Provider","{onClose}: {onClose: () => void}","() => {\n setHasWarnedAboutDrmPlayback(true)\n onClose()\n }","<Stack padding={3}>\n <Button mode=\"ghost\" tone=\"primary\" onClick={_onClose} text=\"Ok\" />\n </Stack>","[3, 3, 3]","<Card padding={[3, 3, 3]} radius={2}>\n <Stack gap={3}>\n <Text size={1} weight=\"semibold\">\n DRM-protected playback will generate a license with a small associated cost. The\n plugin will attempt to play signed or public playback IDs instead whenever possible.\n </Text>\n </Stack>\n </Card>","<Stack gap={3} padding={3}>\n <Card padding={[3, 3, 3]} radius={2}>\n <Stack gap={3}>\n <Text size={1} weight=\"semibold\">\n DRM-protected playback will generate a license with a small associated cost. The\n plugin will attempt to play signed or public playback IDs instead whenever possible.\n </Text>\n </Stack>\n </Card>\n <Card padding={[3, 3, 3]} radius={2} tone=\"suggest\">\n <Stack gap={3}>\n <Text size={1} weight=\"semibold\">\n This is a one time warning. If it persists, you can disable it from your plugin\n configuration.\n </Text>\n </Stack>\n </Card>\n </Stack>","<Dialog\n open\n id=\"drm-playback-warn\"\n onClose={_onClose}\n header=\"DRM Playback Warning\"\n footer={\n <Stack padding={3}>\n <Button mode=\"ghost\" tone=\"primary\" onClick={_onClose} text=\"Ok\" />\n </Stack>\n }\n >\n <Stack gap={3} padding={3}>\n <Card padding={[3, 3, 3]} radius={2}>\n <Stack gap={3}>\n <Text size={1} weight=\"semibold\">\n DRM-protected playback will generate a license with a small associated cost. The\n plugin will attempt to play signed or public playback IDs instead whenever possible.\n </Text>\n </Stack>\n </Card>\n <Card padding={[3, 3, 3]} radius={2} tone=\"suggest\">\n <Stack gap={3}>\n <Text size={1} weight=\"semibold\">\n This is a one time warning. If it persists, you can disable it from your plugin\n configuration.\n </Text>\n </Stack>\n </Card>\n </Stack>\n </Dialog>","_c","hasWarned","{apiVersion: SANITY_API_VERSION}","muxApiHost ? withMuxApiHost(client, muxApiHost) : client","useMemo(\n () => (muxApiHost ? withMuxApiHost(client, muxApiHost) : client),\n [client, muxApiHost],\n )","useClient","_c","useSanityClient","{documentStore, sort, searchQuery}","assetDocuments = []","useMemo(() => ({documentStore, sort, searchQuery}), [documentStore, sort, searchQuery])","collate<VideoAssetDocument>(assetDocuments).map(\n (collated) =>\n ({\n ...(collated.draft || collated.published),\n _id: collated.id,\n }) as VideoAssetDocument,\n )","(collated) =>\n ({\n ...(collated.draft || collated.published),\n _id: collated.id,\n }) as VideoAssetDocument","useMemo(\n () =>\n // Avoid displaying both drafts & published assets by collating them together and giving preference to drafts\n collate<VideoAssetDocument>(assetDocuments).map(\n (collated) =>\n ({\n ...(collated.draft || collated.published),\n _id: collated.id,\n }) as VideoAssetDocument,\n ),\n [assetDocuments],\n )","{\n assets,\n isLoading,\n sort,\n searchQuery,\n setSort,\n setSearchQuery,\n }","_c","_temp","{\n token: value?.token || null,\n secretKey: value?.secretKey || null,\n enableSignedUrls: value?.enableSignedUrls || false,\n signingKeyId: value?.signingKeyId || null,\n signingKeyPrivate: value?.signingKeyPrivate || null,\n drmConfigId: value?.drmConfigId || null,\n }","value?.token || null","value?.secretKey || null","value?.enableSignedUrls || false","value?.signingKeyId || null","value?.signingKeyPrivate || null","value?.drmConfigId || null","{\n isInitialSetup: !exists,\n needsSetup: !secrets?.token || !secrets?.secretKey,\n secrets,\n }","!exists","!secrets?.token || !secrets?.secretKey","useMemo(() => {\n const exists = Boolean(value)\n const secrets: Secrets = {\n token: value?.token || null,\n secretKey: value?.secretKey || null,\n enableSignedUrls: value?.enableSignedUrls || false,\n signingKeyId: value?.signingKeyId || null,\n signingKeyPrivate: value?.signingKeyPrivate || null,\n drmConfigId: value?.drmConfigId || null,\n }\n return {\n isInitialSetup: !exists,\n needsSetup: !secrets?.token || !secrets?.secretKey,\n secrets,\n }\n }, [value])","{error, isLoading, value: cache}","path","_c","{height = 26}: Props","height = 26","{\n fillRule: 'nonzero',\n }","{height: `${height}px`}","`${height}px`","<path\n d=\"M994.287,93.486c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m0,-93.486c-34.509,-0 -62.484,27.976 -62.484,62.486l0,187.511c0,68.943 -56.09,125.033 -125.032,125.033c-68.942,-0 -125.03,-56.09 -125.03,-125.033l0,-187.511c0,-34.51 -27.976,-62.486 -62.485,-62.486c-34.509,-0 -62.484,27.976 -62.484,62.486l0,187.511c0,137.853 112.149,250.003 249.999,250.003c137.851,-0 250.001,-112.15 250.001,-250.003l0,-187.511c0,-34.51 -27.976,-62.486 -62.485,-62.486\"\n style={pathStyle}\n />","<path\n d=\"M1537.51,468.511c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m-275.883,-218.509l-143.33,143.329c-24.402,24.402 -24.402,63.966 0,88.368c24.402,24.402 63.967,24.402 88.369,-0l143.33,-143.329l143.328,143.329c24.402,24.4 63.967,24.402 88.369,-0c24.403,-24.402 24.403,-63.966 0.001,-88.368l-143.33,-143.329l0.001,-0.004l143.329,-143.329c24.402,-24.402 24.402,-63.965 0,-88.367c-24.402,-24.402 -63.967,-24.402 -88.369,-0l-143.329,143.328l-143.329,-143.328c-24.402,-24.401 -63.967,-24.402 -88.369,-0c-24.402,24.402 -24.402,63.965 0,88.367l143.329,143.329l0,0.004Z\"\n style={pathStyle}\n />","<path\n d=\"M437.511,468.521c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m23.915,-463.762c-23.348,-9.672 -50.226,-4.327 -68.096,13.544l-143.331,143.329l-143.33,-143.329c-17.871,-17.871 -44.747,-23.216 -68.096,-13.544c-23.349,9.671 -38.574,32.455 -38.574,57.729l0,375.026c0,34.51 27.977,62.486 62.487,62.486c34.51,-0 62.486,-27.976 62.486,-62.486l0,-224.173l80.843,80.844c24.404,24.402 63.965,24.402 88.369,-0l80.843,-80.844l0,224.173c0,34.51 27.976,62.486 62.486,62.486c34.51,-0 62.486,-27.976 62.486,-62.486l0,-375.026c0,-25.274 -15.224,-48.058 -38.573,-57.729\"\n style={pathStyle}\n />","<g id=\"Layer-1\" fill={fillColor}>\n <path\n d=\"M994.287,93.486c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m0,-93.486c-34.509,-0 -62.484,27.976 -62.484,62.486l0,187.511c0,68.943 -56.09,125.033 -125.032,125.033c-68.942,-0 -125.03,-56.09 -125.03,-125.033l0,-187.511c0,-34.51 -27.976,-62.486 -62.485,-62.486c-34.509,-0 -62.484,27.976 -62.484,62.486l0,187.511c0,137.853 112.149,250.003 249.999,250.003c137.851,-0 250.001,-112.15 250.001,-250.003l0,-187.511c0,-34.51 -27.976,-62.486 -62.485,-62.486\"\n style={pathStyle}\n />\n <path\n d=\"M1537.51,468.511c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m-275.883,-218.509l-143.33,143.329c-24.402,24.402 -24.402,63.966 0,88.368c24.402,24.402 63.967,24.402 88.369,-0l143.33,-143.329l143.328,143.329c24.402,24.4 63.967,24.402 88.369,-0c24.403,-24.402 24.403,-63.966 0.001,-88.368l-143.33,-143.329l0.001,-0.004l143.329,-143.329c24.402,-24.402 24.402,-63.965 0,-88.367c-24.402,-24.402 -63.967,-24.402 -88.369,-0l-143.329,143.328l-143.329,-143.328c-24.402,-24.401 -63.967,-24.402 -88.369,-0c-24.402,24.402 -24.402,63.965 0,88.367l143.329,143.329l0,0.004Z\"\n style={pathStyle}\n />\n <path\n d=\"M437.511,468.521c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m23.915,-463.762c-23.348,-9.672 -50.226,-4.327 -68.096,13.544l-143.331,143.329l-143.33,-143.329c-17.871,-17.871 -44.747,-23.216 -68.096,-13.544c-23.349,9.671 -38.574,32.455 -38.574,57.729l0,375.026c0,34.51 27.977,62.486 62.487,62.486c34.51,-0 62.486,-27.976 62.486,-62.486l0,-224.173l80.843,80.844c24.404,24.402 63.965,24.402 88.369,-0l80.843,-80.844l0,224.173c0,34.51 27.976,62.486 62.486,62.486c34.51,-0 62.486,-27.976 62.486,-62.486l0,-375.026c0,-25.274 -15.224,-48.058 -38.573,-57.729\"\n style={pathStyle}\n />\n </g>","<svg\n aria-labelledby={titleId}\n style={{height: `${height}px`}}\n viewBox=\"0 0 1600 500\"\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlSpace=\"preserve\"\n >\n <g id=\"Layer-1\" fill={fillColor}>\n <path\n d=\"M994.287,93.486c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m0,-93.486c-34.509,-0 -62.484,27.976 -62.484,62.486l0,187.511c0,68.943 -56.09,125.033 -125.032,125.033c-68.942,-0 -125.03,-56.09 -125.03,-125.033l0,-187.511c0,-34.51 -27.976,-62.486 -62.485,-62.486c-34.509,-0 -62.484,27.976 -62.484,62.486l0,187.511c0,137.853 112.149,250.003 249.999,250.003c137.851,-0 250.001,-112.15 250.001,-250.003l0,-187.511c0,-34.51 -27.976,-62.486 -62.485,-62.486\"\n style={pathStyle}\n />\n <path\n d=\"M1537.51,468.511c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m-275.883,-218.509l-143.33,143.329c-24.402,24.402 -24.402,63.966 0,88.368c24.402,24.402 63.967,24.402 88.369,-0l143.33,-143.329l143.328,143.329c24.402,24.4 63.967,24.402 88.369,-0c24.403,-24.402 24.403,-63.966 0.001,-88.368l-143.33,-143.329l0.001,-0.004l143.329,-143.329c24.402,-24.402 24.402,-63.965 0,-88.367c-24.402,-24.402 -63.967,-24.402 -88.369,-0l-143.329,143.328l-143.329,-143.328c-24.402,-24.401 -63.967,-24.402 -88.369,-0c-24.402,24.402 -24.402,63.965 0,88.367l143.329,143.329l0,0.004Z\"\n style={pathStyle}\n />\n <path\n d=\"M437.511,468.521c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m23.915,-463.762c-23.348,-9.672 -50.226,-4.327 -68.096,13.544l-143.331,143.329l-143.33,-143.329c-17.871,-17.871 -44.747,-23.216 -68.096,-13.544c-23.349,9.671 -38.574,32.455 -38.574,57.729l0,375.026c0,34.51 27.977,62.486 62.487,62.486c34.51,-0 62.486,-27.976 62.486,-62.486l0,-224.173l80.843,80.844c24.404,24.402 63.965,24.402 88.369,-0l80.843,-80.844l0,224.173c0,34.51 27.976,62.486 62.486,62.486c34.51,-0 62.486,-27.976 62.486,-62.486l0,-375.026c0,-25.274 -15.224,-48.058 -38.573,-57.729\"\n style={pathStyle}\n />\n </g>\n </svg>","_c","<>\n <Logo>\n <MuxLogo height={13} />\n </Logo>\n API Credentials\n </>","_c","_Fragment","title || <em>Untitled</em>","<Text as=\"label\" htmlFor={inputId} weight=\"semibold\" size={1}>\n {title || <em>Untitled</em>}\n </Text>","description && (\n <Text muted size={1}>\n {description}\n </Text>\n )","<Flex align=\"flex-end\">\n <Box flex={1} paddingY={2}>\n <Stack gap={2}>\n <Text as=\"label\" htmlFor={inputId} weight=\"semibold\" size={1}>\n {title || <em>Untitled</em>}\n </Text>\n\n {description && (\n <Text muted size={1}>\n {description}\n </Text>\n )}\n </Stack>\n </Box>\n </Flex>","<div>{children}</div>","<Stack gap={1}>\n <Flex align=\"flex-end\">\n <Box flex={1} paddingY={2}>\n <Stack gap={2}>\n <Text as=\"label\" htmlFor={inputId} weight=\"semibold\" size={1}>\n {title || <em>Untitled</em>}\n </Text>\n\n {description && (\n <Text muted size={1}>\n {description}\n </Text>\n )}\n </Stack>\n </Box>\n </Flex>\n <div>{children}</div>\n </Stack>","FormField","_c","{secrets, setDialogState}: ConfigureApiDialogProps","() => setDialogState(false)","useCallback(() => setDialogState(false), [setDialogState])","fieldNames.map((field) => `${id}-${field}`)","(event: SubmitEvent<HTMLFormElement>) => {\n event.preventDefault()\n\n if (!saving.current && event.currentTarget.reportValidity()) {\n saving.current = true\n dispatch({type: 'submit'})\n const {token, secretKey, enableSignedUrls, drmConfigId} = state\n handleSaveSecrets({token, secretKey, enableSignedUrls, drmConfigId})\n .then((savedSecrets) => {\n const {projectId, dataset} = client.config()\n clear([cacheNs, secretsId, projectId, dataset])\n preload(() => Promise.resolve(savedSecrets), [cacheNs, secretsId, projectId, dataset])\n setDialogState(false)\n })\n .catch((err) => dispatch({type: 'error', payload: err.message}))\n .finally(() => {\n saving.current = false\n })\n }\n }","useCallback(\n (event: SubmitEvent<HTMLFormElement>) => {\n event.preventDefault()\n\n if (!saving.current && event.currentTarget.reportValidity()) {\n saving.current = true\n dispatch({type: 'submit'})\n const {token, secretKey, enableSignedUrls, drmConfigId} = state\n handleSaveSecrets({token, secretKey, enableSignedUrls, drmConfigId})\n .then((savedSecrets) => {\n const {projectId, dataset} = client.config()\n clear([cacheNs, secretsId, projectId, dataset])\n preload(() => Promise.resolve(savedSecrets), [cacheNs, secretsId, projectId, dataset])\n setDialogState(false)\n })\n .catch((err) => dispatch({type: 'error', payload: err.message}))\n .finally(() => {\n saving.current = false\n })\n }\n },\n [client, dispatch, handleSaveSecrets, setDialogState, state],\n )","(event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'token', value: event.currentTarget.value},\n })\n }","event","useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'token', value: event.currentTarget.value},\n })\n },\n [dispatch],\n )","(event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'secretKey', value: event.currentTarget.value},\n })\n }","useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'secretKey', value: event.currentTarget.value},\n })\n },\n [dispatch],\n )","(event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'enableSignedUrls', value: event.currentTarget.checked},\n })\n }","useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'enableSignedUrls', value: event.currentTarget.checked},\n })\n },\n [dispatch],\n )","(event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'drmConfigId', value: event.currentTarget.value},\n })\n }","useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'drmConfigId', value: event.currentTarget.value},\n })\n },\n [dispatch],\n )","() => {\n if (firstField.current) {\n firstField.current.focus()\n }\n }","[firstField]","<Header />","!hasSecretsInitially && (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"primary\">\n <Stack gap={3}>\n <Text size={1}>\n To set up a new access token, go to your{' '}\n <a\n href=\"https://dashboard.mux.com/settings/access-tokens\"\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n >\n account on mux.com\n </a>\n .\n </Text>\n <Text size={1}>\n The access token needs permissions: <strong>Mux Video </strong>\n (Full Access) and <strong>Mux Data</strong> (Read)\n <br />\n To use Signed URLs, the token must also have System permissions.\n <br />\n The credentials will be stored safely in a hidden document only available to\n editors.\n </Text>\n </Stack>\n </Card>\n )","<TextInput\n id={tokenId}\n ref={firstField}\n onChange={handleChangeToken}\n type=\"text\"\n value={state.token ?? ''}\n required={!!state.secretKey || state.enableSignedUrls}\n />","state.token ?? ''","!!state.secretKey || state.enableSignedUrls","<FormField title=\"Access Token\" inputId={tokenId}>\n <TextInput\n id={tokenId}\n ref={firstField}\n onChange={handleChangeToken}\n type=\"text\"\n value={state.token ?? ''}\n required={!!state.secretKey || state.enableSignedUrls}\n />\n </FormField>","<TextInput\n id={secretKeyId}\n onChange={handleChangeSecretKey}\n type=\"text\"\n value={state.secretKey ?? ''}\n required={!!state.token || state.enableSignedUrls}\n />","state.secretKey ?? ''","!!state.token || state.enableSignedUrls","<FormField title=\"Secret Key\" inputId={secretKeyId}>\n <TextInput\n id={secretKeyId}\n onChange={handleChangeSecretKey}\n type=\"text\"\n value={state.secretKey ?? ''}\n required={!!state.token || state.enableSignedUrls}\n />\n </FormField>","{display: 'block'}","<Checkbox\n id={enableSignedUrlsId}\n onChange={handleChangeEnableSignedUrls}\n checked={state.enableSignedUrls}\n style={{display: 'block'}}\n />","enableSignedUrls","<Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor={enableSignedUrlsId}>Enable Signed Urls</label>\n </Text>\n </Box>","<Flex align=\"center\">\n <Checkbox\n id={enableSignedUrlsId}\n onChange={handleChangeEnableSignedUrls}\n checked={state.enableSignedUrls}\n style={{display: 'block'}}\n />\n <Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor={enableSignedUrlsId}>Enable Signed Urls</label>\n </Text>\n </Box>\n </Flex>","secrets.signingKeyId && state.enableSignedUrls ? (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"caution\">\n <Stack gap={3}>\n <Text size={1}>The signing key ID that Sanity will use is:</Text>\n <Code size={1}>{secrets.signingKeyId}</Code>\n <Text size={1}>\n This key is only used for previewing content in the Sanity UI.\n <br />\n You should generate a different key to use in your application server.\n </Text>\n </Stack>\n </Card>\n ) : null","signingKeyId","<Stack gap={4}>\n <Flex align=\"center\">\n <Checkbox\n id={enableSignedUrlsId}\n onChange={handleChangeEnableSignedUrls}\n checked={state.enableSignedUrls}\n style={{display: 'block'}}\n />\n <Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor={enableSignedUrlsId}>Enable Signed Urls</label>\n </Text>\n </Box>\n </Flex>\n {secrets.signingKeyId && state.enableSignedUrls ? (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"caution\">\n <Stack gap={3}>\n <Text size={1}>The signing key ID that Sanity will use is:</Text>\n <Code size={1}>{secrets.signingKeyId}</Code>\n <Text size={1}>\n This key is only used for previewing content in the Sanity UI.\n <br />\n You should generate a different key to use in your application server.\n </Text>\n </Stack>\n </Card>\n ) : null}\n </Stack>","<TextInput\n id={drmConfigIdId}\n onChange={handleChangeDrmConfigId}\n type=\"text\"\n value={state.drmConfigId ?? ''}\n required={false}\n />","state.drmConfigId ?? ''","<FormField title=\"DRM Configuration ID\" inputId={drmConfigIdId}>\n <TextInput\n id={drmConfigIdId}\n onChange={handleChangeDrmConfigId}\n type=\"text\"\n value={state.drmConfigId ?? ''}\n required={false}\n />\n </FormField>","[3, 3, 3]","<Text size={1}>\n DRM (Digital Rights Management) provides an extra layer of content security for\n video content streamed from Mux. For additional information check out our{' '}\n <a\n href=\"https://www.mux.com/docs/guides/protect-videos-with-drm#play-drm-protected-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n DRM Guide\n </a>\n .\n </Text>","<Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"neutral\">\n <Stack gap={3}>\n <Text size={1}>\n DRM (Digital Rights Management) provides an extra layer of content security for\n video content streamed from Mux. For additional information check out our{' '}\n <a\n href=\"https://www.mux.com/docs/guides/protect-videos-with-drm#play-drm-protected-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n DRM Guide\n </a>\n .\n </Text>\n <Text size={1}>\n <a\n href=\"https://www.mux.com/support/human\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Contact us\n </a>{' '}\n to get started using DRM.\n </Text>\n </Stack>\n </Card>","<Button\n text=\"Save\"\n disabled={!dirty}\n loading={state.submitting}\n tone=\"primary\"\n mode=\"default\"\n type=\"submit\"\n />","submitting","!dirty","<Button\n disabled={state.submitting}\n text=\"Cancel\"\n mode=\"bleed\"\n onClick={handleClose}\n />","<Inline gap={2}>\n <Button\n text=\"Save\"\n disabled={!dirty}\n loading={state.submitting}\n tone=\"primary\"\n mode=\"default\"\n type=\"submit\"\n />\n <Button\n disabled={state.submitting}\n text=\"Cancel\"\n mode=\"bleed\"\n onClick={handleClose}\n />\n </Inline>","state.error && (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"critical\">\n <Text>{state.error}</Text>\n </Card>\n )","error","<Stack gap={4}>\n {!hasSecretsInitially && (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"primary\">\n <Stack gap={3}>\n <Text size={1}>\n To set up a new access token, go to your{' '}\n <a\n href=\"https://dashboard.mux.com/settings/access-tokens\"\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n >\n account on mux.com\n </a>\n .\n </Text>\n <Text size={1}>\n The access token needs permissions: <strong>Mux Video </strong>\n (Full Access) and <strong>Mux Data</strong> (Read)\n <br />\n To use Signed URLs, the token must also have System permissions.\n <br />\n The credentials will be stored safely in a hidden document only available to\n editors.\n </Text>\n </Stack>\n </Card>\n )}\n <FormField title=\"Access Token\" inputId={tokenId}>\n <TextInput\n id={tokenId}\n ref={firstField}\n onChange={handleChangeToken}\n type=\"text\"\n value={state.token ?? ''}\n required={!!state.secretKey || state.enableSignedUrls}\n />\n </FormField>\n <FormField title=\"Secret Key\" inputId={secretKeyId}>\n <TextInput\n id={secretKeyId}\n onChange={handleChangeSecretKey}\n type=\"text\"\n value={state.secretKey ?? ''}\n required={!!state.token || state.enableSignedUrls}\n />\n </FormField>\n\n <Stack gap={4}>\n <Flex align=\"center\">\n <Checkbox\n id={enableSignedUrlsId}\n onChange={handleChangeEnableSignedUrls}\n checked={state.enableSignedUrls}\n style={{display: 'block'}}\n />\n <Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor={enableSignedUrlsId}>Enable Signed Urls</label>\n </Text>\n </Box>\n </Flex>\n {secrets.signingKeyId && state.enableSignedUrls ? (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"caution\">\n <Stack gap={3}>\n <Text size={1}>The signing key ID that Sanity will use is:</Text>\n <Code size={1}>{secrets.signingKeyId}</Code>\n <Text size={1}>\n This key is only used for previewing content in the Sanity UI.\n <br />\n You should generate a different key to use in your application server.\n </Text>\n </Stack>\n </Card>\n ) : null}\n </Stack>\n\n <FormField title=\"DRM Configuration ID\" inputId={drmConfigIdId}>\n <TextInput\n id={drmConfigIdId}\n onChange={handleChangeDrmConfigId}\n type=\"text\"\n value={state.drmConfigId ?? ''}\n required={false}\n />\n </FormField>\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"neutral\">\n <Stack gap={3}>\n <Text size={1}>\n DRM (Digital Rights Management) provides an extra layer of content security for\n video content streamed from Mux. For additional information check out our{' '}\n <a\n href=\"https://www.mux.com/docs/guides/protect-videos-with-drm#play-drm-protected-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n DRM Guide\n </a>\n .\n </Text>\n <Text size={1}>\n <a\n href=\"https://www.mux.com/support/human\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Contact us\n </a>{' '}\n to get started using DRM.\n </Text>\n </Stack>\n </Card>\n\n <Inline gap={2}>\n <Button\n text=\"Save\"\n disabled={!dirty}\n loading={state.submitting}\n tone=\"primary\"\n mode=\"default\"\n type=\"submit\"\n />\n <Button\n disabled={state.submitting}\n text=\"Cancel\"\n mode=\"bleed\"\n onClick={handleClose}\n />\n </Inline>\n {state.error && (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"critical\">\n <Text>{state.error}</Text>\n </Card>\n )}\n </Stack>","<Box padding={3}>\n <form onSubmit={handleSubmit} noValidate>\n <Stack gap={4}>\n {!hasSecretsInitially && (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"primary\">\n <Stack gap={3}>\n <Text size={1}>\n To set up a new access token, go to your{' '}\n <a\n href=\"https://dashboard.mux.com/settings/access-tokens\"\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n >\n account on mux.com\n </a>\n .\n </Text>\n <Text size={1}>\n The access token needs permissions: <strong>Mux Video </strong>\n (Full Access) and <strong>Mux Data</strong> (Read)\n <br />\n To use Signed URLs, the token must also have System permissions.\n <br />\n The credentials will be stored safely in a hidden document only available to\n editors.\n </Text>\n </Stack>\n </Card>\n )}\n <FormField title=\"Access Token\" inputId={tokenId}>\n <TextInput\n id={tokenId}\n ref={firstField}\n onChange={handleChangeToken}\n type=\"text\"\n value={state.token ?? ''}\n required={!!state.secretKey || state.enableSignedUrls}\n />\n </FormField>\n <FormField title=\"Secret Key\" inputId={secretKeyId}>\n <TextInput\n id={secretKeyId}\n onChange={handleChangeSecretKey}\n type=\"text\"\n value={state.secretKey ?? ''}\n required={!!state.token || state.enableSignedUrls}\n />\n </FormField>\n\n <Stack gap={4}>\n <Flex align=\"center\">\n <Checkbox\n id={enableSignedUrlsId}\n onChange={handleChangeEnableSignedUrls}\n checked={state.enableSignedUrls}\n style={{display: 'block'}}\n />\n <Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor={enableSignedUrlsId}>Enable Signed Urls</label>\n </Text>\n </Box>\n </Flex>\n {secrets.signingKeyId && state.enableSignedUrls ? (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"caution\">\n <Stack gap={3}>\n <Text size={1}>The signing key ID that Sanity will use is:</Text>\n <Code size={1}>{secrets.signingKeyId}</Code>\n <Text size={1}>\n This key is only used for previewing content in the Sanity UI.\n <br />\n You should generate a different key to use in your application server.\n </Text>\n </Stack>\n </Card>\n ) : null}\n </Stack>\n\n <FormField title=\"DRM Configuration ID\" inputId={drmConfigIdId}>\n <TextInput\n id={drmConfigIdId}\n onChange={handleChangeDrmConfigId}\n type=\"text\"\n value={state.drmConfigId ?? ''}\n required={false}\n />\n </FormField>\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"neutral\">\n <Stack gap={3}>\n <Text size={1}>\n DRM (Digital Rights Management) provides an extra layer of content security for\n video content streamed from Mux. For additional information check out our{' '}\n <a\n href=\"https://www.mux.com/docs/guides/protect-videos-with-drm#play-drm-protected-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n DRM Guide\n </a>\n .\n </Text>\n <Text size={1}>\n <a\n href=\"https://www.mux.com/support/human\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Contact us\n </a>{' '}\n to get started using DRM.\n </Text>\n </Stack>\n </Card>\n\n <Inline gap={2}>\n <Button\n text=\"Save\"\n disabled={!dirty}\n loading={state.submitting}\n tone=\"primary\"\n mode=\"default\"\n type=\"submit\"\n />\n <Button\n disabled={state.submitting}\n text=\"Cancel\"\n mode=\"bleed\"\n onClick={handleClose}\n />\n </Inline>\n {state.error && (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"critical\">\n <Text>{state.error}</Text>\n </Card>\n )}\n </Stack>\n </form>\n </Box>","<Dialog\n animate\n id={id}\n onClose={handleClose}\n onClickOutside={handleClose}\n header={<Header />}\n zOffset={DIALOGS_Z_INDEX}\n position=\"fixed\"\n width={1}\n >\n <Box padding={3}>\n <form onSubmit={handleSubmit} noValidate>\n <Stack gap={4}>\n {!hasSecretsInitially && (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"primary\">\n <Stack gap={3}>\n <Text size={1}>\n To set up a new access token, go to your{' '}\n <a\n href=\"https://dashboard.mux.com/settings/access-tokens\"\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n >\n account on mux.com\n </a>\n .\n </Text>\n <Text size={1}>\n The access token needs permissions: <strong>Mux Video </strong>\n (Full Access) and <strong>Mux Data</strong> (Read)\n <br />\n To use Signed URLs, the token must also have System permissions.\n <br />\n The credentials will be stored safely in a hidden document only available to\n editors.\n </Text>\n </Stack>\n </Card>\n )}\n <FormField title=\"Access Token\" inputId={tokenId}>\n <TextInput\n id={tokenId}\n ref={firstField}\n onChange={handleChangeToken}\n type=\"text\"\n value={state.token ?? ''}\n required={!!state.secretKey || state.enableSignedUrls}\n />\n </FormField>\n <FormField title=\"Secret Key\" inputId={secretKeyId}>\n <TextInput\n id={secretKeyId}\n onChange={handleChangeSecretKey}\n type=\"text\"\n value={state.secretKey ?? ''}\n required={!!state.token || state.enableSignedUrls}\n />\n </FormField>\n\n <Stack gap={4}>\n <Flex align=\"center\">\n <Checkbox\n id={enableSignedUrlsId}\n onChange={handleChangeEnableSignedUrls}\n checked={state.enableSignedUrls}\n style={{display: 'block'}}\n />\n <Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor={enableSignedUrlsId}>Enable Signed Urls</label>\n </Text>\n </Box>\n </Flex>\n {secrets.signingKeyId && state.enableSignedUrls ? (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"caution\">\n <Stack gap={3}>\n <Text size={1}>The signing key ID that Sanity will use is:</Text>\n <Code size={1}>{secrets.signingKeyId}</Code>\n <Text size={1}>\n This key is only used for previewing content in the Sanity UI.\n <br />\n You should generate a different key to use in your application server.\n </Text>\n </Stack>\n </Card>\n ) : null}\n </Stack>\n\n <FormField title=\"DRM Configuration ID\" inputId={drmConfigIdId}>\n <TextInput\n id={drmConfigIdId}\n onChange={handleChangeDrmConfigId}\n type=\"text\"\n value={state.drmConfigId ?? ''}\n required={false}\n />\n </FormField>\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"neutral\">\n <Stack gap={3}>\n <Text size={1}>\n DRM (Digital Rights Management) provides an extra layer of content security for\n video content streamed from Mux. For additional information check out our{' '}\n <a\n href=\"https://www.mux.com/docs/guides/protect-videos-with-drm#play-drm-protected-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n DRM Guide\n </a>\n .\n </Text>\n <Text size={1}>\n <a\n href=\"https://www.mux.com/support/human\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Contact us\n </a>{' '}\n to get started using DRM.\n </Text>\n </Stack>\n </Card>\n\n <Inline gap={2}>\n <Button\n text=\"Save\"\n disabled={!dirty}\n loading={state.submitting}\n tone=\"primary\"\n mode=\"default\"\n type=\"submit\"\n />\n <Button\n disabled={state.submitting}\n text=\"Cancel\"\n mode=\"bleed\"\n onClick={handleClose}\n />\n </Inline>\n {state.error && (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"critical\">\n <Text>{state.error}</Text>\n </Card>\n )}\n </Stack>\n </form>\n </Box>\n </Dialog>","() => setDialogOpen('secrets')","useCallback(() => setDialogOpen('secrets'), [setDialogOpen])","<ConfigureApiDialog\n secrets={secretDocumentValues.value.secrets}\n setDialogState={setDialogOpen}\n />","secrets","<Button mode=\"bleed\" text=\"Configure plugin\" onClick={openDialog} />","_c","useClient","secretsId","FormField","{client, enabled}: {client: SanityClient; enabled: boolean}","{loading: true, cursor: null}","() => {\n if (!enabled) return\n\n const subscription = defer(() =>\n fetchMuxAssetsPage(\n client,\n // When we've already successfully loaded before (fully or partially), we start from the next cursor to avoid re-fetching\n 'data' in state && state.data && state.data.length > 0 && !state.error\n ? state.cursor\n : null,\n ),\n )\n .pipe(\n // Here we use \"expand\" to recursively fetch next pages\n expand((pageResult) => {\n // if fetched page has next_cursor, we continue emitting, requesting the next page\n // after 2s to avoid rate limiting\n if (hasMorePages(pageResult)) {\n return timer(2000).pipe(\n concatMap(() =>\n defer(() =>\n fetchMuxAssetsPage(\n client,\n 'next_cursor' in pageResult ? pageResult.next_cursor : null,\n ),\n ),\n ),\n )\n }\n\n // Else, we stop emitting\n return of()\n }),\n\n // On each iteration, persist intermediate states to give feedback to users\n tap((pageResult) =>\n setState((prevState) => accumulateIntermediateState(prevState, pageResult)),\n ),\n )\n .subscribe({\n // Once done, let the user know we've stopped loading\n complete: () => {\n setState((prev) => ({\n ...prev,\n loading: false,\n }))\n },\n })\n\n // Unsubscribe on component unmount to prevent memory leaks or fetching unnecessarily\n return () => subscription.unsubscribe()\n // oxlint-disable-next-line react/rule-suppression\n // oxlint-disable-next-line react/exhaustive-deps -- secrets/pluginConfig are stable for the asset fetch lifecycle once enabled\n }","pageResult","(prev) => ({\n ...prev,\n loading: false,\n })","[enabled]","_c","_temp","{\n client,\n enabled: hasSecrets && dialogOpen,\n }","hasSecrets && dialogOpen","assetsInSanity && muxAssets.data\n ? muxAssets.data.filter((a) => !assetExistsInSanity(a, assetsInSanity))\n : undefined","data","useMemo(() => {\n return assetsInSanity && muxAssets.data\n ? muxAssets.data.filter((a) => !assetExistsInSanity(a, assetsInSanity))\n : undefined\n }, [assetsInSanity, muxAssets.data])","[]","() => {\n if (importState !== 'importing') setImportState('closed')\n }","() => {\n if (importState === 'closed') setImportState('idle')\n }","async function importAssets() {\n setImportState('importing')\n const documents = selectedAssets.flatMap((asset) => muxAssetToSanityDocument(asset) || [])\n\n const tx = client.transaction()\n documents.forEach((doc) => tx.create(doc))\n\n try {\n await tx.commit({returnDocuments: false})\n setSelectedAssets([])\n setImportState('done')\n } catch (error) {\n setImportState('error')\n setImportError(error)\n }\n }","(asset) => muxAssetToSanityDocument(asset) || []","error","{\n assetsInSanityLoading,\n closeDialog,\n dialogOpen,\n importState,\n importError,\n hasSecrets,\n importAssets,\n missingAssets,\n muxAssets,\n openDialog,\n selectedAssets,\n setSelectedAssets,\n }","_c","useClient","_temp","options: IntersectionOptions = {}","() => {\n if (!ref.current) return\n\n const observer = new IntersectionObserver(([entry], obs) => {\n // ==== from react-intersection-observer ====\n // While it would be nice if you could just look at isIntersecting to determine if the component is inside the viewport, browsers can't agree on how to use it.\n // -Firefox ignores `threshold` when considering `isIntersecting`, so it will never be false again if `threshold` is > 0\n const nowInView =\n entry!.isIntersecting &&\n obs.thresholds.some((threshold) => entry!.intersectionRatio >= threshold)\n\n // Update our state when observer callback fires\n setInView(nowInView)\n options?.onChange?.(nowInView)\n }, options)\n\n const toObserve = ref.current\n observer.observe(toObserve)\n\n return () => {\n if (toObserve) observer.unobserve(toObserve)\n }\n }","[options, ref]","options?.onChange","ref.current","[entry]","_c","Image","useClient","_Fragment","{\n asset,\n selectAsset,\n selected,\n}: {\n asset: MuxAsset\n selectAsset: (selected: boolean) => void\n selected: boolean\n}","{position: 'relative'}","(e) => {\n selectAsset(e.currentTarget.checked)\n }","<MissingAssetCheckbox\n checked={selected}\n onChange={(e) => {\n selectAsset(e.currentTarget.checked)\n }}\n aria-label={selected ? `Import video ${asset.id}` : `Skip import of video ${asset.id}`}\n />","selected ? `Import video ${asset.id}` : `Skip import of video ${asset.id}`","asset.playback_ids.find((p) => p.id)?.id","playback_ids","(p) => p.id","<VideoThumbnail\n asset={{\n assetId: asset.id,\n data: asset,\n filename: asset.id,\n playbackId: asset.playback_ids.find((p) => p.id)?.id,\n }}\n width={150}\n />","asset.id","truncateString(asset.id, 15)","id","<Code size={2}>{truncateString(asset.id, 15)}</Code>","<Text muted size={2}>\n ({duration.formatted})\n </Text>","formatted","<Flex align=\"center\" gap={1}>\n <Code size={2}>{truncateString(asset.id, 15)}</Code>{' '}\n <Text muted size={2}>\n ({duration.formatted})\n </Text>\n </Flex>","new Date(Number(asset.created_at) * 1000).toLocaleDateString('en', {\n year: 'numeric',\n day: '2-digit',\n month: '2-digit',\n })","Number(asset.created_at) * 1000","<Text size={1}>\n Uploaded at{' '}\n {new Date(Number(asset.created_at) * 1000).toLocaleDateString('en', {\n year: 'numeric',\n day: '2-digit',\n month: '2-digit',\n })}\n </Text>","<Stack gap={2}>\n <Flex align=\"center\" gap={1}>\n <Code size={2}>{truncateString(asset.id, 15)}</Code>{' '}\n <Text muted size={2}>\n ({duration.formatted})\n </Text>\n </Flex>\n <Text size={1}>\n Uploaded at{' '}\n {new Date(Number(asset.created_at) * 1000).toLocaleDateString('en', {\n year: 'numeric',\n day: '2-digit',\n month: '2-digit',\n })}\n </Text>\n </Stack>","<Flex align=\"center\" gap={2}>\n <MissingAssetCheckbox\n checked={selected}\n onChange={(e) => {\n selectAsset(e.currentTarget.checked)\n }}\n aria-label={selected ? `Import video ${asset.id}` : `Skip import of video ${asset.id}`}\n />\n <VideoThumbnail\n asset={{\n assetId: asset.id,\n data: asset,\n filename: asset.id,\n playbackId: asset.playback_ids.find((p) => p.id)?.id,\n }}\n width={150}\n />\n <Stack gap={2}>\n <Flex align=\"center\" gap={1}>\n <Code size={2}>{truncateString(asset.id, 15)}</Code>{' '}\n <Text muted size={2}>\n ({duration.formatted})\n </Text>\n </Flex>\n <Text size={1}>\n Uploaded at{' '}\n {new Date(Number(asset.created_at) * 1000).toLocaleDateString('en', {\n year: 'numeric',\n day: '2-digit',\n month: '2-digit',\n })}\n </Text>\n </Stack>\n </Flex>","<Card\n key={asset.id}\n tone={selected ? 'positive' : undefined}\n border\n paddingX={2}\n paddingY={3}\n style={{position: 'relative'}}\n radius={1}\n >\n <Flex align=\"center\" gap={2}>\n <MissingAssetCheckbox\n checked={selected}\n onChange={(e) => {\n selectAsset(e.currentTarget.checked)\n }}\n aria-label={selected ? `Import video ${asset.id}` : `Skip import of video ${asset.id}`}\n />\n <VideoThumbnail\n asset={{\n assetId: asset.id,\n data: asset,\n filename: asset.id,\n playbackId: asset.playback_ids.find((p) => p.id)?.id,\n }}\n width={150}\n />\n <Stack gap={2}>\n <Flex align=\"center\" gap={1}>\n <Code size={2}>{truncateString(asset.id, 15)}</Code>{' '}\n <Text muted size={2}>\n ({duration.formatted})\n </Text>\n </Flex>\n <Text size={1}>\n Uploaded at{' '}\n {new Date(Number(asset.created_at) * 1000).toLocaleDateString('en', {\n year: 'numeric',\n day: '2-digit',\n month: '2-digit',\n })}\n </Text>\n </Stack>\n </Flex>\n </Card>","selected ? 'positive' : undefined","importState !== 'done' &&\n !noAssetsToImport && (\n <Card padding={3}>\n <Flex justify=\"space-between\" align=\"center\">\n <Button\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Cancel\"\n tone=\"critical\"\n onClick={props.closeDialog}\n disabled={isImporting}\n />\n {props.missingAssets && (\n <Button\n icon={RetrieveIcon}\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text={\n props.selectedAssets?.length > 0\n ? `Import ${props.selectedAssets.length} video(s)`\n : 'No video(s) selected'\n }\n tone=\"positive\"\n onClick={props.importAssets}\n iconRight={isImporting && Spinner}\n disabled={!canTriggerImport}\n />\n )}\n </Flex>\n </Card>\n )","closeDialog","importAssets","missingAssets","selectedAssets","props.muxAssets.hasSkippedAssetsWithoutPlayback && (\n <Card tone=\"caution\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <InfoOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Some videos were skipped\n </Text>\n <Text size={1}>\n Videos without playback IDs cannot be imported and have been excluded from the\n list.\n </Text>\n </Stack>\n </Flex>\n </Card>\n )","hasSkippedAssetsWithoutPlayback","(props.muxAssets.loading || props.assetsInSanityLoading) && (\n <Card tone=\"primary\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Loading assets from Mux\n </Text>\n <Text size={1}>\n This may take a while.\n {props.missingAssets &&\n props.missingAssets.length > 0 &&\n ` There are at least ${props.missingAssets.length} video${props.missingAssets.length > 1 ? 's' : ''} currently not in Sanity...`}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )","assetsInSanityLoading","loading","props.muxAssets.error && (\n <Card tone=\"critical\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error getting all data from Mux\n </Text>\n <Text size={1}>\n {props.missingAssets\n ? `But we've found ${props.missingAssets.length} video${props.missingAssets.length > 1 ? 's' : ''} not in Sanity, which you can start importing now.`\n : 'Please try again or contact a developer for help.'}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )","error","importState === 'importing' && (\n <Card tone=\"primary\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Importing {props.selectedAssets.length} video\n {props.selectedAssets.length > 1 && 's'} from Mux\n </Text>\n </Stack>\n </Flex>\n </Card>\n )","importState === 'error' && (\n <Card tone=\"critical\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error importing videos\n </Text>\n <Text size={1}>\n {props.importError\n ? `Error: ${props.importError}`\n : 'Please try again or contact a developer for help.'}\n </Text>\n <Box marginTop={1}>\n <Button\n icon={RetryIcon}\n text=\"Retry\"\n tone=\"primary\"\n onClick={props.importAssets}\n />\n </Box>\n </Stack>\n </Flex>\n </Card>\n )","importError","(noAssetsToImport || importState === 'done') && (\n <Stack paddingY={5} marginBottom={4} gap={3} style={{textAlign: 'center'}}>\n <Box>\n <CheckmarkCircleIcon fontSize={48} />\n </Box>\n <Heading size={2}>\n {importState === 'done'\n ? `Videos imported successfully`\n : 'There are no Mux videos to import'}\n </Heading>\n <Text size={2}>\n {importState === 'done'\n ? 'You can now use them in your Sanity content.'\n : \"They're all in Sanity and ready to be used in your content.\"}\n </Text>\n </Stack>\n )","props.missingAssets &&\n props.missingAssets.length > 0 &&\n (importState === 'idle' || importState === 'error') && (\n <Stack gap={4}>\n <Heading size={1}>\n There are {props.missingAssets.length}\n {props.muxAssets.loading && '+'} Mux video{props.missingAssets.length > 1 && 's'}{' '}\n not in Sanity\n </Heading>\n {!props.muxAssets.loading && (\n <Flex align=\"center\" paddingX={2}>\n <Checkbox\n id=\"import-all\"\n style={{display: 'block'}}\n onClick={(e) => {\n const selectAll = e.currentTarget.checked\n if (selectAll) {\n // eslint-disable-next-line no-unused-expressions\n props.missingAssets && props.setSelectedAssets(props.missingAssets)\n } else {\n props.setSelectedAssets([])\n }\n }}\n checked={props.selectedAssets.length === props.missingAssets.length}\n />\n <Box flex={1} paddingLeft={3} as=\"label\" htmlFor=\"import-all\">\n <Text>Import all</Text>\n </Box>\n </Flex>\n )}\n {props.missingAssets.map((asset) => (\n <MissingAsset\n key={asset.id}\n asset={asset}\n selectAsset={(selected) => {\n if (selected) {\n props.setSelectedAssets([...props.selectedAssets, asset])\n } else {\n props.setSelectedAssets(props.selectedAssets.filter((a) => a.id !== asset.id))\n }\n }}\n selected={props.selectedAssets.some((a) => a.id === asset.id)}\n />\n ))}\n </Stack>\n )","props.missingAssets","a","<Box padding={3}>\n {/* WARNING: SKIPPED ASSETS WITHOUT PLAYBACK */}\n {props.muxAssets.hasSkippedAssetsWithoutPlayback && (\n <Card tone=\"caution\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <InfoOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Some videos were skipped\n </Text>\n <Text size={1}>\n Videos without playback IDs cannot be imported and have been excluded from the\n list.\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* LOADING ASSETS STATE */}\n {(props.muxAssets.loading || props.assetsInSanityLoading) && (\n <Card tone=\"primary\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Loading assets from Mux\n </Text>\n <Text size={1}>\n This may take a while.\n {props.missingAssets &&\n props.missingAssets.length > 0 &&\n ` There are at least ${props.missingAssets.length} video${props.missingAssets.length > 1 ? 's' : ''} currently not in Sanity...`}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR LOADING MUX */}\n {props.muxAssets.error && (\n <Card tone=\"critical\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error getting all data from Mux\n </Text>\n <Text size={1}>\n {props.missingAssets\n ? `But we've found ${props.missingAssets.length} video${props.missingAssets.length > 1 ? 's' : ''} not in Sanity, which you can start importing now.`\n : 'Please try again or contact a developer for help.'}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* IMPORTING STATE */}\n {importState === 'importing' && (\n <Card tone=\"primary\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Importing {props.selectedAssets.length} video\n {props.selectedAssets.length > 1 && 's'} from Mux\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR IMPORTING */}\n {importState === 'error' && (\n <Card tone=\"critical\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error importing videos\n </Text>\n <Text size={1}>\n {props.importError\n ? `Error: ${props.importError}`\n : 'Please try again or contact a developer for help.'}\n </Text>\n <Box marginTop={1}>\n <Button\n icon={RetryIcon}\n text=\"Retry\"\n tone=\"primary\"\n onClick={props.importAssets}\n />\n </Box>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* NO ASSETS TO IMPORT or SUCESS STATE */}\n {(noAssetsToImport || importState === 'done') && (\n <Stack paddingY={5} marginBottom={4} gap={3} style={{textAlign: 'center'}}>\n <Box>\n <CheckmarkCircleIcon fontSize={48} />\n </Box>\n <Heading size={2}>\n {importState === 'done'\n ? `Videos imported successfully`\n : 'There are no Mux videos to import'}\n </Heading>\n <Text size={2}>\n {importState === 'done'\n ? 'You can now use them in your Sanity content.'\n : \"They're all in Sanity and ready to be used in your content.\"}\n </Text>\n </Stack>\n )}\n\n {/* MISSING ASSETS SELECTOR */}\n {props.missingAssets &&\n props.missingAssets.length > 0 &&\n (importState === 'idle' || importState === 'error') && (\n <Stack gap={4}>\n <Heading size={1}>\n There are {props.missingAssets.length}\n {props.muxAssets.loading && '+'} Mux video{props.missingAssets.length > 1 && 's'}{' '}\n not in Sanity\n </Heading>\n {!props.muxAssets.loading && (\n <Flex align=\"center\" paddingX={2}>\n <Checkbox\n id=\"import-all\"\n style={{display: 'block'}}\n onClick={(e) => {\n const selectAll = e.currentTarget.checked\n if (selectAll) {\n // eslint-disable-next-line no-unused-expressions\n props.missingAssets && props.setSelectedAssets(props.missingAssets)\n } else {\n props.setSelectedAssets([])\n }\n }}\n checked={props.selectedAssets.length === props.missingAssets.length}\n />\n <Box flex={1} paddingLeft={3} as=\"label\" htmlFor=\"import-all\">\n <Text>Import all</Text>\n </Box>\n </Flex>\n )}\n {props.missingAssets.map((asset) => (\n <MissingAsset\n key={asset.id}\n asset={asset}\n selectAsset={(selected) => {\n if (selected) {\n props.setSelectedAssets([...props.selectedAssets, asset])\n } else {\n props.setSelectedAssets(props.selectedAssets.filter((a) => a.id !== asset.id))\n }\n }}\n selected={props.selectedAssets.some((a) => a.id === asset.id)}\n />\n ))}\n </Stack>\n )}\n </Box>","<Dialog\n animate\n header={'Import videos from Mux'}\n zOffset={DIALOGS_Z_INDEX}\n id=\"video-details-dialog\"\n onClose={props.closeDialog}\n onClickOutside={props.closeDialog}\n width={1}\n position=\"fixed\"\n footer={\n importState !== 'done' &&\n !noAssetsToImport && (\n <Card padding={3}>\n <Flex justify=\"space-between\" align=\"center\">\n <Button\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Cancel\"\n tone=\"critical\"\n onClick={props.closeDialog}\n disabled={isImporting}\n />\n {props.missingAssets && (\n <Button\n icon={RetrieveIcon}\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text={\n props.selectedAssets?.length > 0\n ? `Import ${props.selectedAssets.length} video(s)`\n : 'No video(s) selected'\n }\n tone=\"positive\"\n onClick={props.importAssets}\n iconRight={isImporting && Spinner}\n disabled={!canTriggerImport}\n />\n )}\n </Flex>\n </Card>\n )\n }\n >\n <Box padding={3}>\n {/* WARNING: SKIPPED ASSETS WITHOUT PLAYBACK */}\n {props.muxAssets.hasSkippedAssetsWithoutPlayback && (\n <Card tone=\"caution\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <InfoOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Some videos were skipped\n </Text>\n <Text size={1}>\n Videos without playback IDs cannot be imported and have been excluded from the\n list.\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* LOADING ASSETS STATE */}\n {(props.muxAssets.loading || props.assetsInSanityLoading) && (\n <Card tone=\"primary\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Loading assets from Mux\n </Text>\n <Text size={1}>\n This may take a while.\n {props.missingAssets &&\n props.missingAssets.length > 0 &&\n ` There are at least ${props.missingAssets.length} video${props.missingAssets.length > 1 ? 's' : ''} currently not in Sanity...`}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR LOADING MUX */}\n {props.muxAssets.error && (\n <Card tone=\"critical\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error getting all data from Mux\n </Text>\n <Text size={1}>\n {props.missingAssets\n ? `But we've found ${props.missingAssets.length} video${props.missingAssets.length > 1 ? 's' : ''} not in Sanity, which you can start importing now.`\n : 'Please try again or contact a developer for help.'}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* IMPORTING STATE */}\n {importState === 'importing' && (\n <Card tone=\"primary\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Importing {props.selectedAssets.length} video\n {props.selectedAssets.length > 1 && 's'} from Mux\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR IMPORTING */}\n {importState === 'error' && (\n <Card tone=\"critical\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error importing videos\n </Text>\n <Text size={1}>\n {props.importError\n ? `Error: ${props.importError}`\n : 'Please try again or contact a developer for help.'}\n </Text>\n <Box marginTop={1}>\n <Button\n icon={RetryIcon}\n text=\"Retry\"\n tone=\"primary\"\n onClick={props.importAssets}\n />\n </Box>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* NO ASSETS TO IMPORT or SUCESS STATE */}\n {(noAssetsToImport || importState === 'done') && (\n <Stack paddingY={5} marginBottom={4} gap={3} style={{textAlign: 'center'}}>\n <Box>\n <CheckmarkCircleIcon fontSize={48} />\n </Box>\n <Heading size={2}>\n {importState === 'done'\n ? `Videos imported successfully`\n : 'There are no Mux videos to import'}\n </Heading>\n <Text size={2}>\n {importState === 'done'\n ? 'You can now use them in your Sanity content.'\n : \"They're all in Sanity and ready to be used in your content.\"}\n </Text>\n </Stack>\n )}\n\n {/* MISSING ASSETS SELECTOR */}\n {props.missingAssets &&\n props.missingAssets.length > 0 &&\n (importState === 'idle' || importState === 'error') && (\n <Stack gap={4}>\n <Heading size={1}>\n There are {props.missingAssets.length}\n {props.muxAssets.loading && '+'} Mux video{props.missingAssets.length > 1 && 's'}{' '}\n not in Sanity\n </Heading>\n {!props.muxAssets.loading && (\n <Flex align=\"center\" paddingX={2}>\n <Checkbox\n id=\"import-all\"\n style={{display: 'block'}}\n onClick={(e) => {\n const selectAll = e.currentTarget.checked\n if (selectAll) {\n // eslint-disable-next-line no-unused-expressions\n props.missingAssets && props.setSelectedAssets(props.missingAssets)\n } else {\n props.setSelectedAssets([])\n }\n }}\n checked={props.selectedAssets.length === props.missingAssets.length}\n />\n <Box flex={1} paddingLeft={3} as=\"label\" htmlFor=\"import-all\">\n <Text>Import all</Text>\n </Box>\n </Flex>\n )}\n {props.missingAssets.map((asset) => (\n <MissingAsset\n key={asset.id}\n asset={asset}\n selectAsset={(selected) => {\n if (selected) {\n props.setSelectedAssets([...props.selectedAssets, asset])\n } else {\n props.setSelectedAssets(props.selectedAssets.filter((a) => a.id !== asset.id))\n }\n }}\n selected={props.selectedAssets.some((a) => a.id === asset.id)}\n />\n ))}\n </Stack>\n )}\n </Box>\n </Dialog>","<ImportVideosDialog {...importAssets} />","<Button mode=\"bleed\" text=\"Import from Mux\" onClick={importAssets.openDialog} />","openDialog","_c","_temp","() => {\n // Constraint in bounds.\n const clamped = Math.min(props.total - 1, Math.max(0, page))\n if (page !== clamped) {\n setPage(clamped)\n }\n }","[page, props.total, setPage]","total","{cursor: 'pointer'}","() => {\n setPage((p) => {\n return Math.min(props.total - 1, Math.max(0, p - 1))\n })\n }","<Button\n icon={ChevronLeftIcon}\n mode=\"bleed\"\n padding={3}\n style={{cursor: 'pointer'}}\n disabled={page <= 0}\n onClick={() => {\n setPage((p) => {\n return Math.min(props.total - 1, Math.max(0, p - 1))\n })\n }}\n />","page <= 0","<Label muted>\n Page {page + 1}/{props.total}\n </Label>","page + 1","() => {\n setPage((p) => {\n return Math.min(props.total - 1, Math.max(0, p + 1))\n })\n }","p","<Button\n icon={ChevronRightIcon}\n mode=\"bleed\"\n padding={3}\n style={{cursor: 'pointer'}}\n disabled={page >= props.total - 1}\n onClick={() => {\n setPage((p) => {\n return Math.min(props.total - 1, Math.max(0, p + 1))\n })\n }}\n />","page >= props.total - 1","<>\n <Button\n icon={ChevronLeftIcon}\n mode=\"bleed\"\n padding={3}\n style={{cursor: 'pointer'}}\n disabled={page <= 0}\n onClick={() => {\n setPage((p) => {\n return Math.min(props.total - 1, Math.max(0, p - 1))\n })\n }}\n />\n <Label muted>\n Page {page + 1}/{props.total}\n </Label>\n <Button\n icon={ChevronRightIcon}\n mode=\"bleed\"\n padding={3}\n style={{cursor: 'pointer'}}\n disabled={page >= props.total - 1}\n onClick={() => {\n setPage((p) => {\n return Math.min(props.total - 1, Math.max(0, p + 1))\n })\n }}\n />\n </>","_c","_Fragment","{\n client,\n enabled: hasSecrets && dialogOpen,\n }","hasSecrets && dialogOpen","sanityAssets && muxAssets.data\n ? sanityAssets.map((sanityDoc) => {\n const muxAsset = muxAssets.data?.find(\n (m) => m.id === sanityDoc.assetId || m.id === sanityDoc.data?.id,\n )\n return {\n sanityDoc,\n muxAsset,\n muxTitle: muxAsset?.meta?.title,\n currentTitle: sanityDoc.filename,\n }\n })\n : undefined","data","useMemo(() => {\n return sanityAssets && muxAssets.data\n ? sanityAssets.map((sanityDoc) => {\n const muxAsset = muxAssets.data?.find(\n (m) => m.id === sanityDoc.assetId || m.id === sanityDoc.data?.id,\n )\n return {\n sanityDoc,\n muxAsset,\n muxTitle: muxAsset?.meta?.title,\n currentTitle: sanityDoc.filename,\n }\n })\n : undefined\n }, [sanityAssets, muxAssets.data])","() => {\n if (resyncState !== 'syncing') setResyncState('closed')\n }","() => {\n if (resyncState === 'closed') setResyncState('idle')\n }","async function syncAllVideos() {\n if (!matchedAssets) return\n\n setResyncState('syncing')\n\n try {\n const tx = client.transaction()\n\n matchedAssets.forEach((matched) => {\n // Update all videos with the Mux title, even if it's undefined/empty\n const newTitle = matched.muxTitle || ''\n tx.patch(matched.sanityDoc._id, {set: {filename: newTitle}})\n })\n\n await tx.commit({returnDocuments: false})\n setResyncState('done')\n } catch (error) {\n setResyncState('error')\n setResyncError(error)\n }\n }","error","async function syncOnlyEmpty() {\n if (!matchedAssets) return\n\n setResyncState('syncing')\n\n try {\n const tx = client.transaction()\n\n matchedAssets.forEach((matched) => {\n // Only update if the current title is empty or has the placeholder format\n // AND there's a new title available from Mux\n if (\n matched.muxAsset &&\n matched.muxTitle &&\n isEmptyOrPlaceholderTitle(matched.currentTitle, matched.muxAsset.id)\n ) {\n tx.patch(matched.sanityDoc._id, {set: {filename: matched.muxTitle}})\n }\n })\n\n await tx.commit({returnDocuments: false})\n setResyncState('done')\n } catch (error) {\n setResyncState('error')\n setResyncError(error)\n }\n }","tx","matched","async function syncFullData() {\n if (!matchedAssets) return\n\n setResyncState('syncing')\n\n try {\n const tx = client.transaction()\n\n matchedAssets.forEach((matched) => {\n if (!matched.muxAsset) return\n\n const dataWithKeys = addKeysToMuxData(matched.muxAsset)\n\n // Update all fields: filename, status, and full data from Mux\n tx.patch(matched.sanityDoc._id, {\n set: {\n filename: matched.muxTitle || matched.currentTitle || '',\n status: matched.muxAsset.status,\n data: dataWithKeys,\n },\n })\n })\n\n await tx.commit({returnDocuments: false})\n setResyncState('done')\n } catch (error) {\n setResyncState('error')\n setResyncError(error)\n }\n }","{\n sanityAssetsLoading,\n closeDialog,\n dialogOpen,\n resyncState,\n resyncError,\n hasSecrets,\n syncAllVideos,\n syncOnlyEmpty,\n syncFullData,\n matchedAssets,\n muxAssets,\n openDialog,\n }","_c","useClient","{\n id,\n selected,\n onSelect,\n title,\n count,\n description,\n disabled,\n}: OptionCardProps","{\n cursor: disabled ? 'not-allowed' : 'pointer',\n opacity: disabled ? 0.5 : 1,\n }","disabled ? 'not-allowed' : 'pointer'","disabled ? 0.5 : 1","() => onSelect(id)","<Box paddingTop={1}>\n <Radio\n checked={selected}\n onChange={() => onSelect(id)}\n disabled={disabled}\n name=\"sync-option\"\n />\n </Box>","<Flex align=\"center\" gap={2}>\n <Text size={2} weight=\"semibold\">\n {title} ({count})\n </Text>\n </Flex>","<Text size={1} muted>\n {description}\n </Text>","<Stack gap={2} flex={1}>\n <Flex align=\"center\" gap={2}>\n <Text size={2} weight=\"semibold\">\n {title} ({count})\n </Text>\n </Flex>\n <Text size={1} muted>\n {description}\n </Text>\n </Stack>","<Flex gap={3} align=\"flex-start\">\n <Box paddingTop={1}>\n <Radio\n checked={selected}\n onChange={() => onSelect(id)}\n disabled={disabled}\n name=\"sync-option\"\n />\n </Box>\n <Stack gap={2} flex={1}>\n <Flex align=\"center\" gap={2}>\n <Text size={2} weight=\"semibold\">\n {title} ({count})\n </Text>\n </Flex>\n <Text size={1} muted>\n {description}\n </Text>\n </Stack>\n </Flex>","<Card\n as=\"label\"\n padding={3}\n radius={2}\n border\n tone={selected ? 'primary' : 'default'}\n style={{\n cursor: disabled ? 'not-allowed' : 'pointer',\n opacity: disabled ? 0.5 : 1,\n }}\n >\n <Flex gap={3} align=\"flex-start\">\n <Box paddingTop={1}>\n <Radio\n checked={selected}\n onChange={() => onSelect(id)}\n disabled={disabled}\n name=\"sync-option\"\n />\n </Box>\n <Stack gap={2} flex={1}>\n <Flex align=\"center\" gap={2}>\n <Text size={2} weight=\"semibold\">\n {title} ({count})\n </Text>\n </Flex>\n <Text size={1} muted>\n {description}\n </Text>\n </Stack>\n </Flex>\n </Card>","selected ? 'primary' : 'default'","props.matchedAssets?.filter((m) => m.muxAsset).length || 0","matchedAssets","(m) => m.muxAsset","props.matchedAssets?.filter(\n (m) => m.muxAsset && m.muxTitle && isEmptyOrPlaceholderTitle(m.currentTitle, m.muxAsset.id),\n ).length || 0","(m) => m.muxAsset && m.muxTitle && isEmptyOrPlaceholderTitle(m.currentTitle, m.muxAsset.id)","() => {\n switch (selectedOption) {\n case 'fillEmpty':\n void props.syncOnlyEmpty()\n break\n case 'syncTitles':\n void props.syncAllVideos()\n break\n case 'fullResync':\n void props.syncFullData()\n break\n default:\n break\n }\n }","!isDone && (\n <Card padding={3}>\n <Flex justify=\"flex-end\" gap={2}>\n <Button\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Cancel\"\n onClick={props.closeDialog}\n disabled={isResyncing}\n />\n <Button\n icon={SyncIcon}\n fontSize={2}\n padding={3}\n text=\"Run sync\"\n tone=\"primary\"\n onClick={handleSync}\n iconRight={isResyncing && Spinner}\n disabled={!canTriggerResync || isLoading}\n />\n </Flex>\n </Card>\n )","closeDialog","isLoading && (\n <Card tone=\"primary\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Loading assets from Mux\n </Text>\n <Text size={1} muted>\n This may take a while.\n </Text>\n </Stack>\n </Flex>\n </Card>\n )","props.muxAssets.error && (\n <Card tone=\"critical\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error getting data from Mux\n </Text>\n <Text size={1}>Please try again or contact a developer for help.</Text>\n </Stack>\n </Flex>\n </Card>\n )","error","resyncState === 'syncing' && (\n <Card tone=\"primary\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Syncing metadata\n </Text>\n <Text size={1} muted>\n Updating videos from Mux...\n </Text>\n </Stack>\n </Flex>\n </Card>\n )","resyncState === 'error' && (\n <Card tone=\"critical\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error syncing metadata\n </Text>\n <Text size={1}>\n {props.resyncError\n ? `Error: ${props.resyncError}`\n : 'Please try again or contact a developer for help.'}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )","resyncError","resyncState === 'done' && (\n <Stack paddingY={5} gap={3} style={{textAlign: 'center'}}>\n <Box>\n <CheckmarkCircleIcon fontSize={48} />\n </Box>\n <Heading size={2}>Sync completed</Heading>\n <Text size={2} muted>\n Videos have been updated from Mux.\n </Text>\n </Stack>\n )","!isDone && !isLoading && !props.muxAssets.error && (\n <Stack gap={4}>\n <Text size={1} muted>\n Found {videosToUpdate} video{videosToUpdate === 1 ? '' : 's'} linked to Mux.\n </Text>\n\n <Stack gap={3}>\n {hasEmptyTitles && (\n <OptionCard\n id=\"fillEmpty\"\n selected={selectedOption === 'fillEmpty'}\n onSelect={setSelectedOption}\n title=\"Fill missing titles only\"\n count={videosWithEmptyOrPlaceholder}\n description=\"Updates only videos without a title or with placeholder titles (e.g., 'Asset #123') using the title from Mux.\"\n disabled={isResyncing}\n />\n )}\n\n <OptionCard\n id=\"syncTitles\"\n selected={selectedOption === 'syncTitles'}\n onSelect={setSelectedOption}\n title=\"Sync all titles\"\n count={videosToUpdate}\n description=\"Replaces the title in Sanity with the title from Mux for all videos.\"\n disabled={isResyncing}\n />\n\n <OptionCard\n id=\"fullResync\"\n selected={selectedOption === 'fullResync'}\n onSelect={setSelectedOption}\n title=\"Full resync\"\n count={videosToUpdate}\n description=\"Updates all fields from Mux including status, duration, tracks, captions, and renditions.\"\n disabled={isResyncing}\n />\n </Stack>\n </Stack>\n )","<Box padding={4}>\n {/* LOADING ASSETS STATE */}\n {isLoading && (\n <Card tone=\"primary\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Loading assets from Mux\n </Text>\n <Text size={1} muted>\n This may take a while.\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR LOADING MUX */}\n {props.muxAssets.error && (\n <Card tone=\"critical\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error getting data from Mux\n </Text>\n <Text size={1}>Please try again or contact a developer for help.</Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* SYNCING STATE */}\n {resyncState === 'syncing' && (\n <Card tone=\"primary\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Syncing metadata\n </Text>\n <Text size={1} muted>\n Updating videos from Mux...\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR SYNCING */}\n {resyncState === 'error' && (\n <Card tone=\"critical\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error syncing metadata\n </Text>\n <Text size={1}>\n {props.resyncError\n ? `Error: ${props.resyncError}`\n : 'Please try again or contact a developer for help.'}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* SUCCESS STATE */}\n {resyncState === 'done' && (\n <Stack paddingY={5} gap={3} style={{textAlign: 'center'}}>\n <Box>\n <CheckmarkCircleIcon fontSize={48} />\n </Box>\n <Heading size={2}>Sync completed</Heading>\n <Text size={2} muted>\n Videos have been updated from Mux.\n </Text>\n </Stack>\n )}\n\n {/* OPTIONS */}\n {!isDone && !isLoading && !props.muxAssets.error && (\n <Stack gap={4}>\n <Text size={1} muted>\n Found {videosToUpdate} video{videosToUpdate === 1 ? '' : 's'} linked to Mux.\n </Text>\n\n <Stack gap={3}>\n {hasEmptyTitles && (\n <OptionCard\n id=\"fillEmpty\"\n selected={selectedOption === 'fillEmpty'}\n onSelect={setSelectedOption}\n title=\"Fill missing titles only\"\n count={videosWithEmptyOrPlaceholder}\n description=\"Updates only videos without a title or with placeholder titles (e.g., 'Asset #123') using the title from Mux.\"\n disabled={isResyncing}\n />\n )}\n\n <OptionCard\n id=\"syncTitles\"\n selected={selectedOption === 'syncTitles'}\n onSelect={setSelectedOption}\n title=\"Sync all titles\"\n count={videosToUpdate}\n description=\"Replaces the title in Sanity with the title from Mux for all videos.\"\n disabled={isResyncing}\n />\n\n <OptionCard\n id=\"fullResync\"\n selected={selectedOption === 'fullResync'}\n onSelect={setSelectedOption}\n title=\"Full resync\"\n count={videosToUpdate}\n description=\"Updates all fields from Mux including status, duration, tracks, captions, and renditions.\"\n disabled={isResyncing}\n />\n </Stack>\n </Stack>\n )}\n </Box>","<Dialog\n animate\n header=\"Sync with Mux\"\n zOffset={DIALOGS_Z_INDEX}\n id=\"resync-metadata-dialog\"\n onClose={props.closeDialog}\n onClickOutside={props.closeDialog}\n width={1}\n position=\"fixed\"\n footer={\n !isDone && (\n <Card padding={3}>\n <Flex justify=\"flex-end\" gap={2}>\n <Button\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Cancel\"\n onClick={props.closeDialog}\n disabled={isResyncing}\n />\n <Button\n icon={SyncIcon}\n fontSize={2}\n padding={3}\n text=\"Run sync\"\n tone=\"primary\"\n onClick={handleSync}\n iconRight={isResyncing && Spinner}\n disabled={!canTriggerResync || isLoading}\n />\n </Flex>\n </Card>\n )\n }\n >\n <Box padding={4}>\n {/* LOADING ASSETS STATE */}\n {isLoading && (\n <Card tone=\"primary\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Loading assets from Mux\n </Text>\n <Text size={1} muted>\n This may take a while.\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR LOADING MUX */}\n {props.muxAssets.error && (\n <Card tone=\"critical\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error getting data from Mux\n </Text>\n <Text size={1}>Please try again or contact a developer for help.</Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* SYNCING STATE */}\n {resyncState === 'syncing' && (\n <Card tone=\"primary\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Syncing metadata\n </Text>\n <Text size={1} muted>\n Updating videos from Mux...\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR SYNCING */}\n {resyncState === 'error' && (\n <Card tone=\"critical\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error syncing metadata\n </Text>\n <Text size={1}>\n {props.resyncError\n ? `Error: ${props.resyncError}`\n : 'Please try again or contact a developer for help.'}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* SUCCESS STATE */}\n {resyncState === 'done' && (\n <Stack paddingY={5} gap={3} style={{textAlign: 'center'}}>\n <Box>\n <CheckmarkCircleIcon fontSize={48} />\n </Box>\n <Heading size={2}>Sync completed</Heading>\n <Text size={2} muted>\n Videos have been updated from Mux.\n </Text>\n </Stack>\n )}\n\n {/* OPTIONS */}\n {!isDone && !isLoading && !props.muxAssets.error && (\n <Stack gap={4}>\n <Text size={1} muted>\n Found {videosToUpdate} video{videosToUpdate === 1 ? '' : 's'} linked to Mux.\n </Text>\n\n <Stack gap={3}>\n {hasEmptyTitles && (\n <OptionCard\n id=\"fillEmpty\"\n selected={selectedOption === 'fillEmpty'}\n onSelect={setSelectedOption}\n title=\"Fill missing titles only\"\n count={videosWithEmptyOrPlaceholder}\n description=\"Updates only videos without a title or with placeholder titles (e.g., 'Asset #123') using the title from Mux.\"\n disabled={isResyncing}\n />\n )}\n\n <OptionCard\n id=\"syncTitles\"\n selected={selectedOption === 'syncTitles'}\n onSelect={setSelectedOption}\n title=\"Sync all titles\"\n count={videosToUpdate}\n description=\"Replaces the title in Sanity with the title from Mux for all videos.\"\n disabled={isResyncing}\n />\n\n <OptionCard\n id=\"fullResync\"\n selected={selectedOption === 'fullResync'}\n onSelect={setSelectedOption}\n title=\"Full resync\"\n count={videosToUpdate}\n description=\"Updates all fields from Mux including status, duration, tracks, captions, and renditions.\"\n disabled={isResyncing}\n />\n </Stack>\n </Stack>\n )}\n </Box>\n </Dialog>","m","<ResyncMetadataDialog {...resyncMetadata} />","<Button mode=\"bleed\" text=\"Sync with Mux\" onClick={resyncMetadata.openDialog} />","openDialog","_c","_temp","_temp2","<Button text=\"Sort\" icon={SortIcon} mode=\"bleed\" padding={3} style={{cursor: 'pointer'}} />","Object.entries(ASSET_SORT_OPTIONS)","<Menu>\n {Object.entries(ASSET_SORT_OPTIONS).map(([type, {label}]) => (\n <MenuItem\n key={type}\n data-as=\"button\"\n onClick={() => props.setSort(type as SortOption)}\n padding={3}\n tone=\"default\"\n text={label}\n pressed={type === props.sort}\n />\n ))}\n </Menu>","{label}","[type, {label}]","<MenuButton\n button={\n <Button text=\"Sort\" icon={SortIcon} mode=\"bleed\" padding={3} style={{cursor: 'pointer'}} />\n }\n id={id}\n menu={\n <Menu>\n {Object.entries(ASSET_SORT_OPTIONS).map(([type, {label}]) => (\n <MenuItem\n key={type}\n data-as=\"button\"\n onClick={() => props.setSort(type as SortOption)}\n padding={3}\n tone=\"default\"\n text={label}\n pressed={type === props.sort}\n />\n ))}\n </Menu>\n }\n popover={CONTEXT_MENU_POPOVER_PROPS}\n />","_c","<Box\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: '150px',\n }}\n >\n <Spinner />\n </Box>","_c","<Icon />","<Text size={(props.size || 1) + 1} muted>\n <Icon />\n </Text>","(props.size || 1) + 1","<Text size={props.size || 1} muted={props.muted}>\n {props.text}\n </Text>","muted","text","props.size || 1","<Flex gap={2} align=\"center\" padding={1}>\n <Text size={(props.size || 1) + 1} muted>\n <Icon />\n </Text>\n <Text size={props.size || 1} muted={props.muted}>\n {props.text}\n </Text>\n </Flex>","_c","<path\n fill=\"currentColor\"\n d=\"M20 9V6h-3V4h5v5h-2ZM2 9V4h5v2H4v3H2Zm15 11v-2h3v-3h2v5h-5ZM2 20v-5h2v3h3v2H2Zm4-4V8h12v8H6Zm2-2h8v-4H8v4Zm0 0v-4v4Z\"\n />","<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\" {...props}>\n <path\n fill=\"currentColor\"\n d=\"M20 9V6h-3V4h5v5h-2ZM2 9V4h5v2H4v3H2Zm15 11v-2h3v-3h2v5h-5ZM2 20v-5h2v3h3v2H2Zm4-4V8h12v8H6Zm2-2h8v-4H8v4Zm0 0v-4v4Z\"\n />\n </svg>","_c","<path d=\"M232 306.667h48V176h-48v130.667z\" fill=\"currentColor\" />","<path\n d=\"M407.67 170.271l30.786-30.786-33.942-33.941-30.785 30.786C341.217 111.057 300.369 96 256 96 149.961 96 64 181.961 64 288s85.961 192 192 192 192-85.961 192-192c0-44.369-15.057-85.217-40.33-117.729zm-45.604 223.795C333.734 422.398 296.066 438 256 438s-77.735-15.602-106.066-43.934C121.602 365.735 106 328.066 106 288s15.602-77.735 43.934-106.066C178.265 153.602 215.934 138 256 138s77.734 15.602 106.066 43.934C390.398 210.265 406 247.934 406 288s-15.602 77.735-43.934 106.066z\"\n fill=\"currentColor\"\n />","<path d=\"M192 32h128v48H192z\" fill=\"currentColor\" />","<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 512 512\"\n {...props}\n >\n <path d=\"M232 306.667h48V176h-48v130.667z\" fill=\"currentColor\" />\n <path\n d=\"M407.67 170.271l30.786-30.786-33.942-33.941-30.785 30.786C341.217 111.057 300.369 96 256 96 149.961 96 64 181.961 64 288s85.961 192 192 192 192-85.961 192-192c0-44.369-15.057-85.217-40.33-117.729zm-45.604 223.795C333.734 422.398 296.066 438 256 438s-77.735-15.602-106.066-43.934C121.602 365.735 106 328.066 106 288s15.602-77.735 43.934-106.066C178.265 153.602 215.934 138 256 138s77.734 15.602 106.066 43.934C390.398 210.265 406 247.934 406 288s-15.602 77.735-43.934 106.066z\"\n fill=\"currentColor\"\n />\n <path d=\"M192 32h128v48H192z\" fill=\"currentColor\" />\n </svg>","_c","useClient","<Stack gap={3}>\n <Text size={1} muted>\n When you enable the mezzanine file, Mux creates a copy equivalent in quality to your\n original video — ideal for offline editing or archiving. Unlike the streamable MP4 (static)\n renditions, it is not meant for streaming.\n </Text>\n <Text size={1} muted>\n The file is prepared in the background and may take a few minutes depending on the\n asset's duration and resolution. Enabling is free and the download stays available for\n 24 hours.\n </Text>\n </Stack>","_c","{asset, withExplanation = true}: Props","withExplanation = true","<Label muted size={1}>\n Mezzanine\n </Label>","<Flex align=\"center\" justify=\"space-between\" gap={3}>\n <Label muted size={1}>\n Mezzanine\n </Label>\n <Text size={1}>\n <a href={MEZZANINE_LEARN_MORE_URL} target=\"_blank\" rel=\"noopener noreferrer\">\n Learn more\n </a>\n </Text>\n </Flex>","<Text size={1} muted={!isReady}>\n mezzanine.mp4\n </Text>","!isReady","resolution && (\n <Text size={1} muted>\n {resolution}\n </Text>\n )","<Stack gap={2}>\n <Text size={1} muted={!isReady}>\n mezzanine.mp4\n </Text>\n {resolution && (\n <Text size={1} muted>\n {resolution}\n </Text>\n )}\n </Stack>","withExplanation && showExplanation && <MezzanineExplanation />","showExplanation && (expired || status === 'errored') && (\n <Stack gap={2}>\n {expired && (\n <Text size={1} muted>\n The previous mezzanine file expired. Enable it again to download.\n </Text>\n )}\n {status === 'errored' && (\n <Text size={1} style={{color: 'var(--card-critical-color)'}}>\n Mux could not prepare the mezzanine file. Please try again.\n </Text>\n )}\n </Stack>\n )","isPreparing && (\n <Text size={1} muted>\n Preparing the mezzanine file… this can take a few minutes. You can close this and come\n back later.\n </Text>\n )","isReady && (\n <Text size={1} muted>\n Ready to download. The link stays available for about 24 hours.\n </Text>\n )","<Flex justify=\"flex-end\" gap={2}>\n {isPreparing ? (\n <Flex align=\"center\" gap={2}>\n <Spinner muted size={1} />\n <Text size={1} muted>\n Preparing…\n </Text>\n </Flex>\n ) : isReady ? (\n <Button\n icon={DownloadIcon}\n text=\"Download\"\n tone=\"positive\"\n fontSize={1}\n padding={3}\n loading={busy}\n disabled={busy}\n onClick={() => void download()}\n />\n ) : (\n <Button\n text={status === 'errored' ? 'Try again' : 'Enable'}\n tone=\"primary\"\n fontSize={1}\n padding={3}\n loading={busy}\n disabled={busy || !assetReady}\n onClick={() => void enable()}\n />\n )}\n </Flex>","<Card padding={3} radius={2} tone=\"transparent\" border>\n <Stack gap={4}>\n <Flex align=\"center\" justify=\"space-between\" gap={3}>\n <Label muted size={1}>\n Mezzanine\n </Label>\n <Text size={1}>\n <a href={MEZZANINE_LEARN_MORE_URL} target=\"_blank\" rel=\"noopener noreferrer\">\n Learn more\n </a>\n </Text>\n </Flex>\n\n <Stack gap={2}>\n <Text size={1} muted={!isReady}>\n mezzanine.mp4\n </Text>\n {resolution && (\n <Text size={1} muted>\n {resolution}\n </Text>\n )}\n </Stack>\n\n {withExplanation && showExplanation && <MezzanineExplanation />}\n\n {showExplanation && (expired || status === 'errored') && (\n <Stack gap={2}>\n {expired && (\n <Text size={1} muted>\n The previous mezzanine file expired. Enable it again to download.\n </Text>\n )}\n {status === 'errored' && (\n <Text size={1} style={{color: 'var(--card-critical-color)'}}>\n Mux could not prepare the mezzanine file. Please try again.\n </Text>\n )}\n </Stack>\n )}\n\n {isPreparing && (\n <Text size={1} muted>\n Preparing the mezzanine file… this can take a few minutes. You can close this and come\n back later.\n </Text>\n )}\n\n {isReady && (\n <Text size={1} muted>\n Ready to download. The link stays available for about 24 hours.\n </Text>\n )}\n\n <Flex justify=\"flex-end\" gap={2}>\n {isPreparing ? (\n <Flex align=\"center\" gap={2}>\n <Spinner muted size={1} />\n <Text size={1} muted>\n Preparing…\n </Text>\n </Flex>\n ) : isReady ? (\n <Button\n icon={DownloadIcon}\n text=\"Download\"\n tone=\"positive\"\n fontSize={1}\n padding={3}\n loading={busy}\n disabled={busy}\n onClick={() => void download()}\n />\n ) : (\n <Button\n text={status === 'errored' ? 'Try again' : 'Enable'}\n tone=\"primary\"\n fontSize={1}\n padding={3}\n loading={busy}\n disabled={busy || !assetReady}\n onClick={() => void enable()}\n />\n )}\n </Flex>\n </Stack>\n </Card>","_c","async (asset: VideoAssetDocument) => {\n if (!asset.assetId) {\n if (showToast) {\n toast.push({\n title: 'Cannot resync',\n description: 'Asset has no Mux ID',\n status: 'error',\n })\n }\n options?.onError?.(new Error('Asset has no Mux ID'))\n return undefined\n }\n\n if (!asset._id) {\n if (showToast) {\n toast.push({\n title: 'Cannot resync',\n description: 'Asset has no document ID',\n status: 'error',\n })\n }\n options?.onError?.(new Error('Asset has no document ID'))\n return undefined\n }\n\n setResyncState('syncing')\n setResyncError(null)\n\n try {\n const response = await getAsset(client, asset.assetId)\n const muxData = response.data\n const dataWithKeys = addKeysToMuxData(muxData)\n\n await client\n .patch(asset._id)\n .set({\n status: muxData.status,\n data: dataWithKeys,\n ...(muxData.meta?.title && {filename: muxData.meta.title}),\n })\n .commit({returnDocuments: false})\n\n setResyncState('success')\n if (showToast) {\n toast.push({\n title: 'Asset synced',\n description: 'Data has been updated from Mux',\n status: 'success',\n })\n }\n\n options?.onSuccess?.(muxData)\n return muxData\n } catch (error) {\n setResyncState('error')\n setResyncError(error)\n console.error('Failed to refresh asset data:', error)\n if (showToast) {\n toast.push({\n title: 'Sync failed',\n description: 'Could not sync asset from Mux',\n status: 'error',\n })\n }\n options?.onError?.(error)\n return undefined\n }\n }","options?.onError","error","useCallback(\n async (asset: VideoAssetDocument) => {\n if (!asset.assetId) {\n if (showToast) {\n toast.push({\n title: 'Cannot resync',\n description: 'Asset has no Mux ID',\n status: 'error',\n })\n }\n options?.onError?.(new Error('Asset has no Mux ID'))\n return undefined\n }\n\n if (!asset._id) {\n if (showToast) {\n toast.push({\n title: 'Cannot resync',\n description: 'Asset has no document ID',\n status: 'error',\n })\n }\n options?.onError?.(new Error('Asset has no document ID'))\n return undefined\n }\n\n setResyncState('syncing')\n setResyncError(null)\n\n try {\n const response = await getAsset(client, asset.assetId)\n const muxData = response.data\n const dataWithKeys = addKeysToMuxData(muxData)\n\n await client\n .patch(asset._id)\n .set({\n status: muxData.status,\n data: dataWithKeys,\n ...(muxData.meta?.title && {filename: muxData.meta.title}),\n })\n .commit({returnDocuments: false})\n\n setResyncState('success')\n if (showToast) {\n toast.push({\n title: 'Asset synced',\n description: 'Data has been updated from Mux',\n status: 'success',\n })\n }\n\n options?.onSuccess?.(muxData)\n return muxData\n } catch (error) {\n setResyncState('error')\n setResyncError(error)\n console.error('Failed to refresh asset data:', error)\n if (showToast) {\n toast.push({\n title: 'Sync failed',\n description: 'Could not sync asset from Mux',\n status: 'error',\n })\n }\n options?.onError?.(error)\n return undefined\n }\n },\n [client, toast, options, showToast],\n )","{\n resyncState,\n resyncError,\n resyncAsset,\n isResyncing: resyncState === 'syncing',\n }","resyncState === 'syncing'","_c","useClient","LANGUAGE_OPTIONS","useClient","useClient","{\n track,\n iconOnly,\n downloadingTrackId,\n deletingTrackId,\n trackToEdit,\n getTrackSourceLabel,\n handleDownload,\n setTrackToEdit,\n setTrackToDelete,\n}: TrackCardProps","(action: 'download' | 'edit' | 'delete') => {\n if (action === 'download') {\n return (\n downloadingTrackId !== null || deletingTrackId === track.id || trackToEdit?.id === track.id\n )\n }\n if (action === 'edit') {\n return (\n downloadingTrackId === track.id ||\n deletingTrackId === track.id ||\n trackToEdit?.id === track.id\n )\n }\n return (\n downloadingTrackId === track.id || deletingTrackId !== null || trackToEdit?.id === track.id\n )\n }","id","() => {\n if (track.status === 'preparing') {\n return (\n <Flex align=\"center\" gap={2}>\n <Spinner\n muted\n style={{\n width: '0.75em',\n height: '0.75em',\n verticalAlign: 'middle',\n display: 'inline-block',\n marginBottom: '-2px',\n }}\n />\n <Text size={1} muted>\n Processing...\n </Text>\n </Flex>\n )\n }\n\n return (\n <Flex gap={2}>\n {track.status !== 'errored' && (\n <Button\n icon={\n downloadingTrackId === track.id ? (\n <Spinner\n style={{\n verticalAlign: 'middle',\n display: 'inline-block',\n marginTop: '-2px',\n width: '0.5em',\n height: '0.5em',\n }}\n />\n ) : (\n <DownloadIcon />\n )\n }\n text={iconOnly ? undefined : 'Download'}\n mode=\"ghost\"\n tone=\"primary\"\n fontSize={1}\n padding={2}\n onClick={() => handleDownload(track)}\n disabled={isDisabled('download')}\n title=\"Download\"\n />\n )}\n <Button\n icon={<EditIcon />}\n text={iconOnly ? undefined : 'Edit'}\n mode=\"ghost\"\n tone=\"primary\"\n fontSize={1}\n padding={2}\n disabled={isDisabled('edit')}\n onClick={() => setTrackToEdit(track)}\n title=\"Edit\"\n />\n <Button\n icon={\n deletingTrackId === track.id ? (\n <Spinner\n style={{\n verticalAlign: 'middle',\n display: 'inline-block',\n marginTop: '-2px',\n width: '0.5em',\n height: '0.5em',\n }}\n />\n ) : (\n <TrashIcon />\n )\n }\n text={iconOnly ? undefined : 'Delete'}\n mode=\"ghost\"\n tone=\"critical\"\n fontSize={1}\n padding={2}\n disabled={isDisabled('delete')}\n onClick={() => setTrackToDelete(track)}\n title=\"Delete\"\n />\n </Flex>\n )\n }","track.status","<Text weight=\"semibold\">{track.name || 'Untitled'}</Text>","track.name || 'Untitled'","getTrackSourceLabel(track)","<Text size={1} muted>\n ({getTrackSourceLabel(track)})\n </Text>","track.status === 'errored' && (\n <ErrorOutlineIcon\n style={{color: 'var(--card-critical-color)'}}\n aria-label=\"Error\"\n fontSize={20}\n />\n )","status","<Flex align=\"center\" gap={2}>\n <Text weight=\"semibold\">{track.name || 'Untitled'}</Text>\n <Text size={1} muted>\n ({getTrackSourceLabel(track)})\n </Text>\n {track.status === 'errored' && (\n <ErrorOutlineIcon\n style={{color: 'var(--card-critical-color)'}}\n aria-label=\"Error\"\n fontSize={20}\n />\n )}\n </Flex>","track.language_code && (\n <Text size={1} muted>\n Language: {track.language_code}\n </Text>\n )","language_code","track.status === 'errored' && track.error && (\n <Text size={1} style={{color: 'var(--card-critical-color)'}}>\n {track.error.messages?.[0] || track.error.type || 'Failed to process track'}\n </Text>\n )","error","<Stack gap={2} flex={1}>\n <Flex align=\"center\" gap={2}>\n <Text weight=\"semibold\">{track.name || 'Untitled'}</Text>\n <Text size={1} muted>\n ({getTrackSourceLabel(track)})\n </Text>\n {track.status === 'errored' && (\n <ErrorOutlineIcon\n style={{color: 'var(--card-critical-color)'}}\n aria-label=\"Error\"\n fontSize={20}\n />\n )}\n </Flex>\n {track.language_code && (\n <Text size={1} muted>\n Language: {track.language_code}\n </Text>\n )}\n {track.status === 'errored' && track.error && (\n <Text size={1} style={{color: 'var(--card-critical-color)'}}>\n {track.error.messages?.[0] || track.error.type || 'Failed to process track'}\n </Text>\n )}\n </Stack>","renderActionButtons()","<Flex align=\"center\" justify=\"space-between\" gap={3}>\n <Stack gap={2} flex={1}>\n <Flex align=\"center\" gap={2}>\n <Text weight=\"semibold\">{track.name || 'Untitled'}</Text>\n <Text size={1} muted>\n ({getTrackSourceLabel(track)})\n </Text>\n {track.status === 'errored' && (\n <ErrorOutlineIcon\n style={{color: 'var(--card-critical-color)'}}\n aria-label=\"Error\"\n fontSize={20}\n />\n )}\n </Flex>\n {track.language_code && (\n <Text size={1} muted>\n Language: {track.language_code}\n </Text>\n )}\n {track.status === 'errored' && track.error && (\n <Text size={1} style={{color: 'var(--card-critical-color)'}}>\n {track.error.messages?.[0] || track.error.type || 'Failed to process track'}\n </Text>\n )}\n </Stack>\n {renderActionButtons()}\n </Flex>","<Card\n padding={3}\n radius={2}\n tone={track.status === 'errored' ? 'caution' : 'transparent'}\n border\n >\n <Flex align=\"center\" justify=\"space-between\" gap={3}>\n <Stack gap={2} flex={1}>\n <Flex align=\"center\" gap={2}>\n <Text weight=\"semibold\">{track.name || 'Untitled'}</Text>\n <Text size={1} muted>\n ({getTrackSourceLabel(track)})\n </Text>\n {track.status === 'errored' && (\n <ErrorOutlineIcon\n style={{color: 'var(--card-critical-color)'}}\n aria-label=\"Error\"\n fontSize={20}\n />\n )}\n </Flex>\n {track.language_code && (\n <Text size={1} muted>\n Language: {track.language_code}\n </Text>\n )}\n {track.status === 'errored' && track.error && (\n <Text size={1} style={{color: 'var(--card-critical-color)'}}>\n {track.error.messages?.[0] || track.error.type || 'Failed to process track'}\n </Text>\n )}\n </Stack>\n {renderActionButtons()}\n </Flex>\n </Card>","track.status === 'errored' ? 'caution' : 'transparent'","_c","useClient","{\n dialogState,\n setDialogState,\n children,\n}: DialogStateProviderProps","{dialogState, setDialogState}","useMemo(() => ({dialogState, setDialogState}), [dialogState, setDialogState])","<DialogStateContext.Provider value={value}>{children}</DialogStateContext.Provider>","DialogStateContext.Provider","_c","{asset}: Props","() => setDialogState(false)","<Stack padding={4}>\n <TextTracksManager asset={asset} />\n </Stack>","<Dialog id={dialogId} header=\"Edit Captions\" onClose={() => setDialogState(false)} width={1}>\n <Stack padding={4}>\n <TextTracksManager asset={asset} />\n </Stack>\n </Dialog>","_c","{asset, currentTime = 0}: Props","currentTime = 0","() =>\n formatSecondsToHHMMSS(currentTime)","{...asset, thumbTime: nextTime}","useMemo(() => ({...asset, thumbTime: nextTime}), [asset, nextTime])","() => {\n setSaving(true)\n client\n .patch(asset._id)\n .set({thumbTime: nextTime})\n .commit({returnDocuments: false})\n .then(() => setDialogState(false))\n .catch(setSaveThumbnailError)\n .finally(() => setSaving(false))\n }","_id","getDevicePixelRatio({maxDpr: 2})","(event: ChangeEvent<HTMLInputElement>) => {\n const value = event.currentTarget.value\n setTimeFormatted(value)\n\n if (isValidTimeFormat(value)) {\n setInputError('')\n const totalSeconds = getSecondsFromTimeFormat(value)\n setNextTime(totalSeconds)\n } else {\n setInputError('Invalid time format')\n }\n }","() => setDialogState(false)","<Stack padding={3}>\n <Button\n key=\"thumbnail\"\n disabled={inputError !== ''}\n mode=\"ghost\"\n tone=\"primary\"\n loading={saving}\n onClick={handleSave}\n text=\"Set new thumbnail\"\n />\n </Stack>","inputError !== ''","<Text size={1} weight=\"semibold\">\n Current:\n </Text>","<Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n Current:\n </Text>\n <VideoThumbnail asset={asset} width={width} staticImage />\n </Stack>","<Text size={1} weight=\"semibold\">\n New:\n </Text>","<Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n New:\n </Text>\n <VideoThumbnail asset={assetWithNewThumbnail} width={width} staticImage />\n </Stack>","<Stack gap={2}>\n <Flex align={'center'} justify={'center'}>\n <Text size={5} weight=\"semibold\">\n Or\n </Text>\n </Flex>\n </Stack>","<Text size={1} weight=\"semibold\">\n Selected time for thumbnail (hh:mm:ss):\n </Text>","<Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n Selected time for thumbnail (hh:mm:ss):\n </Text>\n <TextInput\n size={1}\n value={timeFormatted}\n placeholder=\"hh:mm:ss\"\n onChange={handleInputChange}\n customValidity={inputError}\n />\n </Stack>","<Stack gap={3} padding={3}>\n <Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n Current:\n </Text>\n <VideoThumbnail asset={asset} width={width} staticImage />\n </Stack>\n <Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n New:\n </Text>\n <VideoThumbnail asset={assetWithNewThumbnail} width={width} staticImage />\n </Stack>\n\n <Stack gap={2}>\n <Flex align={'center'} justify={'center'}>\n <Text size={5} weight=\"semibold\">\n Or\n </Text>\n </Flex>\n </Stack>\n\n <Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n Selected time for thumbnail (hh:mm:ss):\n </Text>\n <TextInput\n size={1}\n value={timeFormatted}\n placeholder=\"hh:mm:ss\"\n onChange={handleInputChange}\n customValidity={inputError}\n />\n </Stack>\n </Stack>","<Dialog\n id={dialogId}\n header=\"Edit thumbnail\"\n onClose={() => setDialogState(false)}\n footer={\n <Stack padding={3}>\n <Button\n key=\"thumbnail\"\n disabled={inputError !== ''}\n mode=\"ghost\"\n tone=\"primary\"\n loading={saving}\n onClick={handleSave}\n text=\"Set new thumbnail\"\n />\n </Stack>\n }\n >\n <Stack gap={3} padding={3}>\n <Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n Current:\n </Text>\n <VideoThumbnail asset={asset} width={width} staticImage />\n </Stack>\n <Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n New:\n </Text>\n <VideoThumbnail asset={assetWithNewThumbnail} width={width} staticImage />\n </Stack>\n\n <Stack gap={2}>\n <Flex align={'center'} justify={'center'}>\n <Text size={5} weight=\"semibold\">\n Or\n </Text>\n </Flex>\n </Stack>\n\n <Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n Selected time for thumbnail (hh:mm:ss):\n </Text>\n <TextInput\n size={1}\n value={timeFormatted}\n placeholder=\"hh:mm:ss\"\n onChange={handleInputChange}\n customValidity={inputError}\n />\n </Stack>\n </Stack>\n </Dialog>","_c","useClient","<path\n fill=\"currentColor\"\n style={{opacity: '0.65'}}\n 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\"\n />","<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\" {...props}>\n <path\n fill=\"currentColor\"\n style={{opacity: '0.65'}}\n 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\"\n />\n </svg>","_c","{asset, onClose}: Props","() => {\n onClose?.()\n setDialogState(false)\n }","getMezzanineStatus(asset)","showExplanation && <MezzanineExplanation />","<Mezzanine asset={asset} withExplanation={false} />","<Box padding={4}>\n <Stack gap={4}>\n {showExplanation && <MezzanineExplanation />}\n <Mezzanine asset={asset} withExplanation={false} />\n </Stack>\n </Box>","<Dialog\n id={dialogId}\n header=\"Mezzanine file\"\n onClose={closing}\n zOffset={DIALOGS_Z_INDEX}\n width={1}\n >\n <Box padding={4}>\n <Stack gap={4}>\n {showExplanation && <MezzanineExplanation />}\n <Mezzanine asset={asset} withExplanation={false} />\n </Stack>\n </Box>\n </Dialog>","_c","useClient","_Fragment","getUnknownTypeFallback(value._id, value._type)","_id","_type","<SanityDefaultPreview {...getUnknownTypeFallback(value._id, value._type)} layout={layout} />","_c","{time}: TimeAgoProps","{useTemporalPhrase: true}","<span title={timeAgo}>{timeAgo}</span>","_c","<Box padding={2}>\n <Text size={1}>\n {document ? (\n <>Edited {updatedAt && <TimeAgo time={updatedAt} />}</>\n ) : (\n <>No unpublished edits</>\n )}\n </Text>\n </Box>","<EditIcon />","<TextWithTone tone=\"caution\" dimmed={!document} muted={!document} size={1}>\n <EditIcon />\n </TextWithTone>","!document","<Tooltip\n animate\n portal\n content={\n <Box padding={2}>\n <Text size={1}>\n {document ? (\n <>Edited {updatedAt && <TimeAgo time={updatedAt} />}</>\n ) : (\n <>No unpublished edits</>\n )}\n </Text>\n </Box>\n }\n >\n <TextWithTone tone=\"caution\" dimmed={!document} muted={!document} size={1}>\n <EditIcon />\n </TextWithTone>\n </Tooltip>","_c","_Fragment","<Box padding={2}>\n <Text size={1}>\n {document ? (\n <>Published {updatedAt && <TimeAgo time={updatedAt} />}</>\n ) : (\n <>Not published</>\n )}\n </Text>\n </Box>","<PublishIcon />","<TextWithTone tone=\"positive\" dimmed={!document} muted={!document} size={1}>\n <PublishIcon />\n </TextWithTone>","!document","<Tooltip\n animate\n portal\n content={\n <Box padding={2}>\n <Text size={1}>\n {document ? (\n <>Published {updatedAt && <TimeAgo time={updatedAt} />}</>\n ) : (\n <>Not published</>\n )}\n </Text>\n </Box>\n }\n >\n <TextWithTone tone=\"positive\" dimmed={!document} muted={!document} size={1}>\n <PublishIcon />\n </TextWithTone>\n </Tooltip>","_c","_Fragment","getPreviewStateObservable(props.documentPreviewStore, schemaType, value._id)","documentPreviewStore","_id","useMemo(\n () => getPreviewStateObservable(props.documentPreviewStore, schemaType, value._id),\n [props.documentPreviewStore, schemaType, value._id],\n )","isLoading ? null : (\n <Inline gap={4}>\n {presence && presence.length > 0 && <DocumentPreviewPresence presence={presence} />}\n <PublishedStatus document={original} />\n <DraftStatus document={snapshot} />\n </Inline>\n )","getPreviewValueWithFallback({snapshot, original, fallback: {title}})","<SanityDefaultPreview\n {...(getPreviewValueWithFallback({snapshot, original, fallback: {title}}) as any)}\n isPlaceholder={isLoading}\n icon={icon}\n layout={layout}\n status={status}\n />","getPreviewValueWithFallback({snapshot, original, fallback: {title}}) as any","_c","previewStateObservable","useMemo(() => {\n if (!doc) return null\n\n if (!schemaType || !hasSchemaType) {\n return <MissingSchemaType value={doc} />\n }\n\n return (\n <PaneItemPreview\n documentPreviewStore={documentPreviewStore}\n icon={getIconWithFallback(undefined, schemaType, DocumentIcon)}\n schemaType={schemaType}\n layout=\"default\"\n value={doc}\n presence={documentPresence}\n />\n )\n }, [hasSchemaType, schemaType, documentPresence, doc, documentPreviewStore])","<MissingSchemaType value={doc} />","getIconWithFallback(undefined, schemaType, DocumentIcon)","<PaneItemPreview\n documentPreviewStore={documentPreviewStore}\n icon={getIconWithFallback(undefined, schemaType, DocumentIcon)}\n schemaType={schemaType}\n layout=\"default\"\n value={doc}\n presence={documentPresence}\n />","{id: props.documentPair.id}","id","<PreviewCard\n __unstable_focusRing\n as={IntentLink}\n intent=\"edit\"\n params={{id: props.documentPair.id}}\n data-as=\"a\"\n data-ui=\"PaneItem\"\n padding={2}\n radius={2}\n tone=\"inherit\"\n >\n {children}\n </PreviewCard>","_c","<SpinnerBox />","<Card border radius={3} padding={3}>\n <Text size={2}>No documents are using this video</Text>\n </Card>","Container","documentPairs?.map((documentPair) => {\n const schemaType = schema.get(documentPair.type)\n\n return (\n <Card\n key={documentPair.id}\n marginBottom={2}\n padding={2}\n radius={2}\n shadow={1}\n style={{overflow: 'hidden'}}\n >\n <Box>\n <DocumentPreview documentPair={documentPair} schemaType={schemaType} />\n </Box>\n </Card>\n )\n })","references","props.references || []","<Container>\n {documentPairs?.map((documentPair) => {\n const schemaType = schema.get(documentPair.type)\n\n return (\n <Card\n key={documentPair.id}\n marginBottom={2}\n padding={2}\n radius={2}\n shadow={1}\n style={{overflow: 'hidden'}}\n >\n <Box>\n <DocumentPreview documentPair={documentPair} schemaType={schemaType} />\n </Box>\n </Card>\n )\n })}\n </Container>","_c","{\n asset,\n references,\n referencesLoading,\n cancelDelete,\n succeededDeleting,\n}: {\n asset: VideoAssetDocument\n references?: SanityDocument[]\n referencesLoading: boolean\n cancelDelete: () => void\n succeededDeleting: () => void\n}","() => {\n if (state !== 'checkingReferences' || referencesLoading) return\n\n // oxlint-disable-next-line react/set-state-in-effect\n setState(references?.length ? 'cantDelete' : 'confirm')\n }","length","[state, references, referencesLoading]","async function confirmDelete() {\n if (state !== 'confirm') return\n\n setState('processing_deletion')\n const worked = await deleteAsset({client, asset, deleteOnMux})\n if (worked === true) {\n toast.push({title: 'Successfully deleted video', status: 'success'})\n succeededDeleting()\n } else if (worked === 'failed-mux') {\n toast.push({\n title: 'Deleted video in Sanity',\n description: \"But it wasn't deleted in Mux\",\n status: 'warning',\n })\n succeededDeleting()\n } else {\n toast.push({title: 'Failed deleting video', status: 'error'})\n\n setState('error_deleting')\n }\n }","{\n minHeight: '150px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }","state === 'checkingReferences' && (\n <>\n <Heading size={2}>Checking if video can be deleted</Heading>\n <SpinnerBox />\n </>\n )","state === 'cantDelete' && (\n <>\n <Heading size={2}>Video can't be deleted</Heading>\n <Text size={2} style={{marginBottom: '2rem'}}>\n There are {references?.length} document{references && references.length > 0 && 's'}{' '}\n pointing to this video. Remove their references to this file or delete them before\n proceeding.\n </Text>\n <VideoReferences references={references} isLoaded={!referencesLoading} />\n </>\n )","references?.length","state === 'confirm' && (\n <>\n <Heading size={2}>Are you sure you want to delete this video?</Heading>\n <Text size={2}>This action is irreversible</Text>\n <Stack gap={4} marginY={4}>\n <Flex align=\"center\" as=\"label\">\n <Checkbox\n checked={deleteOnMux}\n onChange={() => setDeleteOnMux((prev) => !prev)}\n />\n <Text style={{margin: '0 10px'}}>Delete asset on Mux</Text>\n </Flex>\n <Flex align=\"center\" as=\"label\">\n <Checkbox disabled checked />\n <Text style={{margin: '0 10px'}}>Delete video from dataset</Text>\n </Flex>\n <Box>\n <Button\n icon={TrashIcon}\n fontSize={2}\n padding={3}\n text=\"Delete video\"\n tone=\"critical\"\n onClick={confirmDelete}\n disabled={['processing_deletion', 'checkingReferences', 'cantDelete'].some(\n (s) => s === state,\n )}\n />\n </Box>\n </Stack>\n </>\n )","(prev) => !prev","state === 'processing_deletion' && (\n <>\n <Heading size={2}>Deleting video...</Heading>\n <SpinnerBox />\n </>\n )","state === 'error_deleting' && (\n <>\n <Heading size={2}>Something went wrong!</Heading>\n <Text size={2}>Try deleting the video again by clicking the button below</Text>\n </>\n )","<Card\n padding={3}\n style={{\n minHeight: '150px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <Stack gap={3}>\n {state === 'checkingReferences' && (\n <>\n <Heading size={2}>Checking if video can be deleted</Heading>\n <SpinnerBox />\n </>\n )}\n {state === 'cantDelete' && (\n <>\n <Heading size={2}>Video can't be deleted</Heading>\n <Text size={2} style={{marginBottom: '2rem'}}>\n There are {references?.length} document{references && references.length > 0 && 's'}{' '}\n pointing to this video. Remove their references to this file or delete them before\n proceeding.\n </Text>\n <VideoReferences references={references} isLoaded={!referencesLoading} />\n </>\n )}\n {state === 'confirm' && (\n <>\n <Heading size={2}>Are you sure you want to delete this video?</Heading>\n <Text size={2}>This action is irreversible</Text>\n <Stack gap={4} marginY={4}>\n <Flex align=\"center\" as=\"label\">\n <Checkbox\n checked={deleteOnMux}\n onChange={() => setDeleteOnMux((prev) => !prev)}\n />\n <Text style={{margin: '0 10px'}}>Delete asset on Mux</Text>\n </Flex>\n <Flex align=\"center\" as=\"label\">\n <Checkbox disabled checked />\n <Text style={{margin: '0 10px'}}>Delete video from dataset</Text>\n </Flex>\n <Box>\n <Button\n icon={TrashIcon}\n fontSize={2}\n padding={3}\n text=\"Delete video\"\n tone=\"critical\"\n onClick={confirmDelete}\n disabled={['processing_deletion', 'checkingReferences', 'cantDelete'].some(\n (s) => s === state,\n )}\n />\n </Box>\n </Stack>\n </>\n )}\n {state === 'processing_deletion' && (\n <>\n <Heading size={2}>Deleting video...</Heading>\n <SpinnerBox />\n </>\n )}\n {state === 'error_deleting' && (\n <>\n <Heading size={2}>Something went wrong!</Heading>\n <Text size={2}>Try deleting the video again by clicking the button below</Text>\n </>\n )}\n </Stack>\n </Card>","<Dialog\n animate\n header={'Delete video'}\n zOffset={DIALOGS_Z_INDEX}\n id=\"deleting-video-details-dialog\"\n onClose={cancelDelete}\n onClickOutside={cancelDelete}\n width={1}\n position=\"fixed\"\n >\n <Card\n padding={3}\n style={{\n minHeight: '150px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <Stack gap={3}>\n {state === 'checkingReferences' && (\n <>\n <Heading size={2}>Checking if video can be deleted</Heading>\n <SpinnerBox />\n </>\n )}\n {state === 'cantDelete' && (\n <>\n <Heading size={2}>Video can't be deleted</Heading>\n <Text size={2} style={{marginBottom: '2rem'}}>\n There are {references?.length} document{references && references.length > 0 && 's'}{' '}\n pointing to this video. Remove their references to this file or delete them before\n proceeding.\n </Text>\n <VideoReferences references={references} isLoaded={!referencesLoading} />\n </>\n )}\n {state === 'confirm' && (\n <>\n <Heading size={2}>Are you sure you want to delete this video?</Heading>\n <Text size={2}>This action is irreversible</Text>\n <Stack gap={4} marginY={4}>\n <Flex align=\"center\" as=\"label\">\n <Checkbox\n checked={deleteOnMux}\n onChange={() => setDeleteOnMux((prev) => !prev)}\n />\n <Text style={{margin: '0 10px'}}>Delete asset on Mux</Text>\n </Flex>\n <Flex align=\"center\" as=\"label\">\n <Checkbox disabled checked />\n <Text style={{margin: '0 10px'}}>Delete video from dataset</Text>\n </Flex>\n <Box>\n <Button\n icon={TrashIcon}\n fontSize={2}\n padding={3}\n text=\"Delete video\"\n tone=\"critical\"\n onClick={confirmDelete}\n disabled={['processing_deletion', 'checkingReferences', 'cantDelete'].some(\n (s) => s === state,\n )}\n />\n </Box>\n </Stack>\n </>\n )}\n {state === 'processing_deletion' && (\n <>\n <Heading size={2}>Deleting video...</Heading>\n <SpinnerBox />\n </>\n )}\n {state === 'error_deleting' && (\n <>\n <Heading size={2}>Something went wrong!</Heading>\n <Text size={2}>Try deleting the video again by clicking the button below</Text>\n </>\n )}\n </Stack>\n </Card>\n </Dialog>","_c","useClient","_Fragment","_temp","{documentStore, id: props.asset._id}","_id","useMemo(() => ({documentStore, id: props.asset._id}), [documentStore, props.asset._id])","() => props.asset","asset","getVideoMetadata({...props.asset, filename})","{showToast: true}","async function handleResync() {\n if (state !== 'idle') return\n setState('resyncing')\n await resyncAsset(props.asset)\n setState('idle')\n }","function handleClose() {\n if (state !== 'idle') return\n\n if (modified) {\n setState('closing')\n return\n }\n\n props.closeDialog()\n }","function confirmClose(shouldClose: boolean) {\n if (state !== 'closing') return\n\n if (shouldClose) props.closeDialog()\n\n setState('idle')\n }","async function saveChanges() {\n if (state !== 'idle') return\n setState('saving')\n\n try {\n await client.patch(props.asset._id).set({filename}).commit()\n setOriginalAsset((prev) => ({...prev, filename}))\n toast.push({\n title: 'Video title updated',\n description: `New title: ${filename}`,\n status: 'success',\n })\n props.closeDialog()\n } catch (error) {\n toast.push({\n title: 'Failed updating file name',\n status: 'error',\n description: typeof error === 'string' ? error : 'Please try again',\n })\n setFilename(originalAsset.filename)\n }\n\n setState('idle')\n }","filename","props.asset._id","error","{\n references,\n referencesLoading,\n modified,\n filename,\n setFilename,\n displayInfo,\n state,\n setState,\n handleClose,\n confirmClose,\n saveChanges,\n handleResync,\n isResyncing,\n }","_c","useClient","<TextInput\n id={props.label}\n value={props.value}\n placeholder={props.placeholder}\n onInput={props.onInput}\n disabled={props.disabled}\n />","disabled","label","onInput","placeholder","value","<FormField title={props.label} description={props.description} inputId={props.label}>\n <TextInput\n id={props.label}\n value={props.value}\n placeholder={props.placeholder}\n onInput={props.onInput}\n disabled={props.disabled}\n />\n </FormField>","description","() => {\n if (!contentsRef.current || !('getBoundingClientRect' in contentsRef.current)) return\n\n setContainerHeight(contentsRef.current.getBoundingClientRect().height)\n }","[]","() => setState('deleting')","<Button\n icon={TrashIcon}\n fontSize={2}\n padding={3}\n mode=\"bleed\"\n text=\"Delete\"\n tone=\"critical\"\n onClick={() => setState('deleting')}\n disabled={isSaving || isResyncing}\n />","isSaving || isResyncing","<Button\n icon={SyncIcon}\n fontSize={2}\n padding={3}\n mode=\"bleed\"\n text=\"Resync\"\n tone=\"primary\"\n onClick={handleResync}\n disabled={isSaving || isResyncing}\n iconRight={isResyncing && Spinner}\n />","isResyncing && Spinner","<Flex gap={2}>\n <Button\n icon={TrashIcon}\n fontSize={2}\n padding={3}\n mode=\"bleed\"\n text=\"Delete\"\n tone=\"critical\"\n onClick={() => setState('deleting')}\n disabled={isSaving || isResyncing}\n />\n <Button\n icon={SyncIcon}\n fontSize={2}\n padding={3}\n mode=\"bleed\"\n text=\"Resync\"\n tone=\"primary\"\n onClick={handleResync}\n disabled={isSaving || isResyncing}\n iconRight={isResyncing && Spinner}\n />\n </Flex>","modified && (\n <Button\n icon={CheckmarkIcon}\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Save and close\"\n tone=\"positive\"\n onClick={saveChanges}\n iconRight={isSaving && Spinner}\n disabled={isSaving || isResyncing}\n />\n )","<Card padding={3}>\n <Flex justify=\"space-between\" align=\"center\">\n <Flex gap={2}>\n <Button\n icon={TrashIcon}\n fontSize={2}\n padding={3}\n mode=\"bleed\"\n text=\"Delete\"\n tone=\"critical\"\n onClick={() => setState('deleting')}\n disabled={isSaving || isResyncing}\n />\n <Button\n icon={SyncIcon}\n fontSize={2}\n padding={3}\n mode=\"bleed\"\n text=\"Resync\"\n tone=\"primary\"\n onClick={handleResync}\n disabled={isSaving || isResyncing}\n iconRight={isResyncing && Spinner}\n />\n </Flex>\n {modified && (\n <Button\n icon={CheckmarkIcon}\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Save and close\"\n tone=\"positive\"\n onClick={saveChanges}\n iconRight={isSaving && Spinner}\n disabled={isSaving || isResyncing}\n />\n )}\n </Flex>\n </Card>","state === 'deleting' && (\n <DeleteDialog\n asset={props.asset}\n cancelDelete={() => setState('idle')}\n referencesLoading={referencesLoading}\n references={references}\n succeededDeleting={() => {\n props.closeDialog()\n }}\n />\n )","state === 'closing' && (\n <Dialog\n animate\n header={'You have unsaved changes'}\n zOffset={DIALOGS_Z_INDEX}\n id=\"closing-video-details-dialog\"\n onClose={() => confirmClose(false)}\n onClickOutside={() => confirmClose(false)}\n width={1}\n position=\"fixed\"\n footer={\n <Card padding={3}>\n <Flex justify=\"space-between\" align=\"center\">\n <Button\n icon={ErrorOutlineIcon}\n fontSize={2}\n padding={3}\n text=\"Discard changes\"\n tone=\"critical\"\n onClick={() => confirmClose(true)}\n />\n {modified && (\n <Button\n icon={RevertIcon}\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Keep editing\"\n tone=\"primary\"\n onClick={() => confirmClose(false)}\n />\n )}\n </Flex>\n </Card>\n }\n >\n <Card padding={5}>\n <Stack style={{textAlign: 'center'}} gap={3}>\n <Heading size={2}>Unsaved changes will be lost</Heading>\n <Text size={2}>Are you sure you want to discard them?</Text>\n </Stack>\n </Card>\n </Dialog>\n )","{\n containerType: 'inline-size',\n }","['column', 'column', 'row']","typeof containerHeight === 'number'\n ? {\n minHeight: containerHeight,\n }\n : undefined","<VideoPlayer asset={props.asset} autoPlay={props.asset.autoPlay || false} />","asset","props.asset.autoPlay || false","tab === 'details' && (\n <>\n <TextTracksManager\n asset={props.asset}\n iconOnly\n collapseTracks\n tracks={\n displayInfo?.text_tracks ||\n props.asset.data?.tracks?.filter(\n (track): track is MuxTextTrack => track.type === 'text',\n ) ||\n []\n }\n />\n <Mezzanine asset={props.asset} />\n </>\n )","text_tracks","(track): track is MuxTextTrack => track.type === 'text'","<Stack gap={4} flex={1} sizing=\"border\">\n <VideoPlayer asset={props.asset} autoPlay={props.asset.autoPlay || false} />\n {tab === 'details' && (\n <>\n <TextTracksManager\n asset={props.asset}\n iconOnly\n collapseTracks\n tracks={\n displayInfo?.text_tracks ||\n props.asset.data?.tracks?.filter(\n (track): track is MuxTextTrack => track.type === 'text',\n ) ||\n []\n }\n />\n <Mezzanine asset={props.asset} />\n </>\n )}\n </Stack>","() => setTab('details')","<Tab\n aria-controls=\"details-panel\"\n icon={EditIcon}\n id=\"details-tab\"\n label=\"Details\"\n onClick={() => setTab('details')}\n selected={tab === 'details'}\n />","tab === 'details'","() => setTab('references')","<Tab\n aria-controls=\"references-panel\"\n icon={SearchIcon}\n id=\"references-tab\"\n label={`Used by ${references ? `(${references.length})` : ''}`}\n onClick={() => setTab('references')}\n selected={tab === 'references'}\n />","`Used by ${references ? `(${references.length})` : ''}`","tab === 'references'","<TabList gap={2}>\n <Tab\n aria-controls=\"details-panel\"\n icon={EditIcon}\n id=\"details-tab\"\n label=\"Details\"\n onClick={() => setTab('details')}\n selected={tab === 'details'}\n />\n <Tab\n aria-controls=\"references-panel\"\n icon={SearchIcon}\n id=\"references-tab\"\n label={`Used by ${references ? `(${references.length})` : ''}`}\n onClick={() => setTab('references')}\n selected={tab === 'references'}\n />\n </TabList>","{wordBreak: 'break-word'}","(e) => setFilename(e.currentTarget.value)","<AssetInput\n label=\"Video title or file name\"\n description=\"Not visible to users. Useful for finding videos later.\"\n value={filename || ''}\n onInput={(e) => setFilename(e.currentTarget.value)}\n disabled={state !== 'idle'}\n />","filename || ''","state !== 'idle'","displayInfo?.duration && (\n <IconInfo\n text={`Duration: ${displayInfo.duration}`}\n icon={ClockIcon}\n size={2}\n />\n )","duration","displayInfo?.max_stored_resolution && (\n <IconInfo\n text={`Max Resolution: ${displayInfo.max_stored_resolution}`}\n icon={ResolutionIcon}\n size={2}\n />\n )","max_stored_resolution","displayInfo?.max_stored_frame_rate && (\n <IconInfo\n text={`Frame rate: ${displayInfo.max_stored_frame_rate}`}\n icon={StopWatchIcon}\n size={2}\n />\n )","max_stored_frame_rate","displayInfo?.aspect_ratio && (\n <IconInfo\n text={`Aspect Ratio: ${displayInfo.aspect_ratio}`}\n icon={CropIcon}\n size={2}\n />\n )","aspect_ratio","displayInfo.createdAt.toLocaleDateString('en', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })","createdAt","<IconInfo\n text={`Uploaded on: ${displayInfo.createdAt.toLocaleDateString('en', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })}`}\n icon={CalendarIcon}\n size={2}\n />","`Uploaded on: ${displayInfo.createdAt.toLocaleDateString('en', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })}`","<IconInfo text={`Mux ID: \\n${displayInfo.id}`} icon={TagIcon} size={2} />","`Mux ID: \\n${displayInfo.id}`","<PlaybackIds playback_ids={displayInfo.playback_ids} />","playback_ids","<Stack gap={3}>\n {displayInfo?.duration && (\n <IconInfo\n text={`Duration: ${displayInfo.duration}`}\n icon={ClockIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_resolution && (\n <IconInfo\n text={`Max Resolution: ${displayInfo.max_stored_resolution}`}\n icon={ResolutionIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_frame_rate && (\n <IconInfo\n text={`Frame rate: ${displayInfo.max_stored_frame_rate}`}\n icon={StopWatchIcon}\n size={2}\n />\n )}\n {displayInfo?.aspect_ratio && (\n <IconInfo\n text={`Aspect Ratio: ${displayInfo.aspect_ratio}`}\n icon={CropIcon}\n size={2}\n />\n )}\n <IconInfo\n text={`Uploaded on: ${displayInfo.createdAt.toLocaleDateString('en', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })}`}\n icon={CalendarIcon}\n size={2}\n />\n <IconInfo text={`Mux ID: \\n${displayInfo.id}`} icon={TagIcon} size={2} />\n <PlaybackIds playback_ids={displayInfo.playback_ids} />\n </Stack>","<Stack gap={4}>\n <AssetInput\n label=\"Video title or file name\"\n description=\"Not visible to users. Useful for finding videos later.\"\n value={filename || ''}\n onInput={(e) => setFilename(e.currentTarget.value)}\n disabled={state !== 'idle'}\n />\n <Stack gap={3}>\n {displayInfo?.duration && (\n <IconInfo\n text={`Duration: ${displayInfo.duration}`}\n icon={ClockIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_resolution && (\n <IconInfo\n text={`Max Resolution: ${displayInfo.max_stored_resolution}`}\n icon={ResolutionIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_frame_rate && (\n <IconInfo\n text={`Frame rate: ${displayInfo.max_stored_frame_rate}`}\n icon={StopWatchIcon}\n size={2}\n />\n )}\n {displayInfo?.aspect_ratio && (\n <IconInfo\n text={`Aspect Ratio: ${displayInfo.aspect_ratio}`}\n icon={CropIcon}\n size={2}\n />\n )}\n <IconInfo\n text={`Uploaded on: ${displayInfo.createdAt.toLocaleDateString('en', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })}`}\n icon={CalendarIcon}\n size={2}\n />\n <IconInfo text={`Mux ID: \\n${displayInfo.id}`} icon={TagIcon} size={2} />\n <PlaybackIds playback_ids={displayInfo.playback_ids} />\n </Stack>\n </Stack>","<TabPanel\n aria-labelledby=\"details-tab\"\n id=\"details-panel\"\n hidden={tab !== 'details'}\n style={{wordBreak: 'break-word'}}\n >\n <Stack gap={4}>\n <AssetInput\n label=\"Video title or file name\"\n description=\"Not visible to users. Useful for finding videos later.\"\n value={filename || ''}\n onInput={(e) => setFilename(e.currentTarget.value)}\n disabled={state !== 'idle'}\n />\n <Stack gap={3}>\n {displayInfo?.duration && (\n <IconInfo\n text={`Duration: ${displayInfo.duration}`}\n icon={ClockIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_resolution && (\n <IconInfo\n text={`Max Resolution: ${displayInfo.max_stored_resolution}`}\n icon={ResolutionIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_frame_rate && (\n <IconInfo\n text={`Frame rate: ${displayInfo.max_stored_frame_rate}`}\n icon={StopWatchIcon}\n size={2}\n />\n )}\n {displayInfo?.aspect_ratio && (\n <IconInfo\n text={`Aspect Ratio: ${displayInfo.aspect_ratio}`}\n icon={CropIcon}\n size={2}\n />\n )}\n <IconInfo\n text={`Uploaded on: ${displayInfo.createdAt.toLocaleDateString('en', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })}`}\n icon={CalendarIcon}\n size={2}\n />\n <IconInfo text={`Mux ID: \\n${displayInfo.id}`} icon={TagIcon} size={2} />\n <PlaybackIds playback_ids={displayInfo.playback_ids} />\n </Stack>\n </Stack>\n </TabPanel>","tab !== 'details'","<VideoReferences references={references} isLoaded={!referencesLoading} />","!referencesLoading","<TabPanel\n aria-labelledby=\"references-tab\"\n id=\"references-panel\"\n hidden={tab !== 'references'}\n >\n <VideoReferences references={references} isLoaded={!referencesLoading} />\n </TabPanel>","tab !== 'references'","<Stack gap={4} flex={1} sizing=\"border\">\n <TabList gap={2}>\n <Tab\n aria-controls=\"details-panel\"\n icon={EditIcon}\n id=\"details-tab\"\n label=\"Details\"\n onClick={() => setTab('details')}\n selected={tab === 'details'}\n />\n <Tab\n aria-controls=\"references-panel\"\n icon={SearchIcon}\n id=\"references-tab\"\n label={`Used by ${references ? `(${references.length})` : ''}`}\n onClick={() => setTab('references')}\n selected={tab === 'references'}\n />\n </TabList>\n <TabPanel\n aria-labelledby=\"details-tab\"\n id=\"details-panel\"\n hidden={tab !== 'details'}\n style={{wordBreak: 'break-word'}}\n >\n <Stack gap={4}>\n <AssetInput\n label=\"Video title or file name\"\n description=\"Not visible to users. Useful for finding videos later.\"\n value={filename || ''}\n onInput={(e) => setFilename(e.currentTarget.value)}\n disabled={state !== 'idle'}\n />\n <Stack gap={3}>\n {displayInfo?.duration && (\n <IconInfo\n text={`Duration: ${displayInfo.duration}`}\n icon={ClockIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_resolution && (\n <IconInfo\n text={`Max Resolution: ${displayInfo.max_stored_resolution}`}\n icon={ResolutionIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_frame_rate && (\n <IconInfo\n text={`Frame rate: ${displayInfo.max_stored_frame_rate}`}\n icon={StopWatchIcon}\n size={2}\n />\n )}\n {displayInfo?.aspect_ratio && (\n <IconInfo\n text={`Aspect Ratio: ${displayInfo.aspect_ratio}`}\n icon={CropIcon}\n size={2}\n />\n )}\n <IconInfo\n text={`Uploaded on: ${displayInfo.createdAt.toLocaleDateString('en', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })}`}\n icon={CalendarIcon}\n size={2}\n />\n <IconInfo text={`Mux ID: \\n${displayInfo.id}`} icon={TagIcon} size={2} />\n <PlaybackIds playback_ids={displayInfo.playback_ids} />\n </Stack>\n </Stack>\n </TabPanel>\n <TabPanel\n aria-labelledby=\"references-tab\"\n id=\"references-panel\"\n hidden={tab !== 'references'}\n >\n <VideoReferences references={references} isLoaded={!referencesLoading} />\n </TabPanel>\n </Stack>","<Card\n padding={4}\n sizing=\"border\"\n style={{\n containerType: 'inline-size',\n }}\n >\n <Flex\n sizing=\"border\"\n gap={4}\n direction={['column', 'column', 'row']}\n align=\"flex-start\"\n ref={contentsRef}\n style={\n typeof containerHeight === 'number'\n ? {\n minHeight: containerHeight,\n }\n : undefined\n }\n >\n <Stack gap={4} flex={1} sizing=\"border\">\n <VideoPlayer asset={props.asset} autoPlay={props.asset.autoPlay || false} />\n {tab === 'details' && (\n <>\n <TextTracksManager\n asset={props.asset}\n iconOnly\n collapseTracks\n tracks={\n displayInfo?.text_tracks ||\n props.asset.data?.tracks?.filter(\n (track): track is MuxTextTrack => track.type === 'text',\n ) ||\n []\n }\n />\n <Mezzanine asset={props.asset} />\n </>\n )}\n </Stack>\n <Stack gap={4} flex={1} sizing=\"border\">\n <TabList gap={2}>\n <Tab\n aria-controls=\"details-panel\"\n icon={EditIcon}\n id=\"details-tab\"\n label=\"Details\"\n onClick={() => setTab('details')}\n selected={tab === 'details'}\n />\n <Tab\n aria-controls=\"references-panel\"\n icon={SearchIcon}\n id=\"references-tab\"\n label={`Used by ${references ? `(${references.length})` : ''}`}\n onClick={() => setTab('references')}\n selected={tab === 'references'}\n />\n </TabList>\n <TabPanel\n aria-labelledby=\"details-tab\"\n id=\"details-panel\"\n hidden={tab !== 'details'}\n style={{wordBreak: 'break-word'}}\n >\n <Stack gap={4}>\n <AssetInput\n label=\"Video title or file name\"\n description=\"Not visible to users. Useful for finding videos later.\"\n value={filename || ''}\n onInput={(e) => setFilename(e.currentTarget.value)}\n disabled={state !== 'idle'}\n />\n <Stack gap={3}>\n {displayInfo?.duration && (\n <IconInfo\n text={`Duration: ${displayInfo.duration}`}\n icon={ClockIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_resolution && (\n <IconInfo\n text={`Max Resolution: ${displayInfo.max_stored_resolution}`}\n icon={ResolutionIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_frame_rate && (\n <IconInfo\n text={`Frame rate: ${displayInfo.max_stored_frame_rate}`}\n icon={StopWatchIcon}\n size={2}\n />\n )}\n {displayInfo?.aspect_ratio && (\n <IconInfo\n text={`Aspect Ratio: ${displayInfo.aspect_ratio}`}\n icon={CropIcon}\n size={2}\n />\n )}\n <IconInfo\n text={`Uploaded on: ${displayInfo.createdAt.toLocaleDateString('en', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })}`}\n icon={CalendarIcon}\n size={2}\n />\n <IconInfo text={`Mux ID: \\n${displayInfo.id}`} icon={TagIcon} size={2} />\n <PlaybackIds playback_ids={displayInfo.playback_ids} />\n </Stack>\n </Stack>\n </TabPanel>\n <TabPanel\n aria-labelledby=\"references-tab\"\n id=\"references-panel\"\n hidden={tab !== 'references'}\n >\n <VideoReferences references={references} isLoaded={!referencesLoading} />\n </TabPanel>\n </Stack>\n </Flex>\n </Card>","<Dialog\n animate\n header={displayInfo.title}\n zOffset={DIALOGS_Z_INDEX}\n id=\"video-details-dialog\"\n onClose={handleClose}\n onClickOutside={handleClose}\n width={2}\n position=\"fixed\"\n footer={\n <Card padding={3}>\n <Flex justify=\"space-between\" align=\"center\">\n <Flex gap={2}>\n <Button\n icon={TrashIcon}\n fontSize={2}\n padding={3}\n mode=\"bleed\"\n text=\"Delete\"\n tone=\"critical\"\n onClick={() => setState('deleting')}\n disabled={isSaving || isResyncing}\n />\n <Button\n icon={SyncIcon}\n fontSize={2}\n padding={3}\n mode=\"bleed\"\n text=\"Resync\"\n tone=\"primary\"\n onClick={handleResync}\n disabled={isSaving || isResyncing}\n iconRight={isResyncing && Spinner}\n />\n </Flex>\n {modified && (\n <Button\n icon={CheckmarkIcon}\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Save and close\"\n tone=\"positive\"\n onClick={saveChanges}\n iconRight={isSaving && Spinner}\n disabled={isSaving || isResyncing}\n />\n )}\n </Flex>\n </Card>\n }\n >\n {/* DELETION DIALOG */}\n {state === 'deleting' && (\n <DeleteDialog\n asset={props.asset}\n cancelDelete={() => setState('idle')}\n referencesLoading={referencesLoading}\n references={references}\n succeededDeleting={() => {\n props.closeDialog()\n }}\n />\n )}\n\n {/* CONFIRM CLOSING DIALOG */}\n {state === 'closing' && (\n <Dialog\n animate\n header={'You have unsaved changes'}\n zOffset={DIALOGS_Z_INDEX}\n id=\"closing-video-details-dialog\"\n onClose={() => confirmClose(false)}\n onClickOutside={() => confirmClose(false)}\n width={1}\n position=\"fixed\"\n footer={\n <Card padding={3}>\n <Flex justify=\"space-between\" align=\"center\">\n <Button\n icon={ErrorOutlineIcon}\n fontSize={2}\n padding={3}\n text=\"Discard changes\"\n tone=\"critical\"\n onClick={() => confirmClose(true)}\n />\n {modified && (\n <Button\n icon={RevertIcon}\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Keep editing\"\n tone=\"primary\"\n onClick={() => confirmClose(false)}\n />\n )}\n </Flex>\n </Card>\n }\n >\n <Card padding={5}>\n <Stack style={{textAlign: 'center'}} gap={3}>\n <Heading size={2}>Unsaved changes will be lost</Heading>\n <Text size={2}>Are you sure you want to discard them?</Text>\n </Stack>\n </Card>\n </Dialog>\n )}\n <Card\n padding={4}\n sizing=\"border\"\n style={{\n containerType: 'inline-size',\n }}\n >\n <Flex\n sizing=\"border\"\n gap={4}\n direction={['column', 'column', 'row']}\n align=\"flex-start\"\n ref={contentsRef}\n style={\n typeof containerHeight === 'number'\n ? {\n minHeight: containerHeight,\n }\n : undefined\n }\n >\n <Stack gap={4} flex={1} sizing=\"border\">\n <VideoPlayer asset={props.asset} autoPlay={props.asset.autoPlay || false} />\n {tab === 'details' && (\n <>\n <TextTracksManager\n asset={props.asset}\n iconOnly\n collapseTracks\n tracks={\n displayInfo?.text_tracks ||\n props.asset.data?.tracks?.filter(\n (track): track is MuxTextTrack => track.type === 'text',\n ) ||\n []\n }\n />\n <Mezzanine asset={props.asset} />\n </>\n )}\n </Stack>\n <Stack gap={4} flex={1} sizing=\"border\">\n <TabList gap={2}>\n <Tab\n aria-controls=\"details-panel\"\n icon={EditIcon}\n id=\"details-tab\"\n label=\"Details\"\n onClick={() => setTab('details')}\n selected={tab === 'details'}\n />\n <Tab\n aria-controls=\"references-panel\"\n icon={SearchIcon}\n id=\"references-tab\"\n label={`Used by ${references ? `(${references.length})` : ''}`}\n onClick={() => setTab('references')}\n selected={tab === 'references'}\n />\n </TabList>\n <TabPanel\n aria-labelledby=\"details-tab\"\n id=\"details-panel\"\n hidden={tab !== 'details'}\n style={{wordBreak: 'break-word'}}\n >\n <Stack gap={4}>\n <AssetInput\n label=\"Video title or file name\"\n description=\"Not visible to users. Useful for finding videos later.\"\n value={filename || ''}\n onInput={(e) => setFilename(e.currentTarget.value)}\n disabled={state !== 'idle'}\n />\n <Stack gap={3}>\n {displayInfo?.duration && (\n <IconInfo\n text={`Duration: ${displayInfo.duration}`}\n icon={ClockIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_resolution && (\n <IconInfo\n text={`Max Resolution: ${displayInfo.max_stored_resolution}`}\n icon={ResolutionIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_frame_rate && (\n <IconInfo\n text={`Frame rate: ${displayInfo.max_stored_frame_rate}`}\n icon={StopWatchIcon}\n size={2}\n />\n )}\n {displayInfo?.aspect_ratio && (\n <IconInfo\n text={`Aspect Ratio: ${displayInfo.aspect_ratio}`}\n icon={CropIcon}\n size={2}\n />\n )}\n <IconInfo\n text={`Uploaded on: ${displayInfo.createdAt.toLocaleDateString('en', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })}`}\n icon={CalendarIcon}\n size={2}\n />\n <IconInfo text={`Mux ID: \\n${displayInfo.id}`} icon={TagIcon} size={2} />\n <PlaybackIds playback_ids={displayInfo.playback_ids} />\n </Stack>\n </Stack>\n </TabPanel>\n <TabPanel\n aria-labelledby=\"references-tab\"\n id=\"references-panel\"\n hidden={tab !== 'references'}\n >\n <VideoReferences references={references} isLoaded={!referencesLoading} />\n </TabPanel>\n </Stack>\n </Flex>\n </Card>\n </Dialog>","title","displayInfo.title","{playback_ids}: {playback_ids?: MuxPlaybackId[]}","playback_ids.map((entry) => (\n <IconInfo\n key={entry.id}\n text={`Playback ID [${policyToText(entry.policy)}]: ${entry.id}`}\n icon={TagIcon}\n size={2}\n />\n ))","(entry) => (\n <IconInfo\n key={entry.id}\n text={`Playback ID [${policyToText(entry.policy)}]: ${entry.id}`}\n icon={TagIcon}\n size={2}\n />\n )","<IconInfo text={'No Playback ID'} icon={TagIcon} size={2} />","_c","FormField","_Fragment","_temp","_temp2","Inline","Stack","3","displayInfo?.duration && (\n <IconInfo text={displayInfo.duration} icon={ClockIcon} size={1} muted />\n )","<IconInfo\n text={displayInfo.createdAt.toISOString().split('T')[0]!}\n icon={CalendarIcon}\n size={1}\n muted\n />","displayInfo.title != displayInfo.id.slice(0, 12) && (\n <IconInfo text={displayInfo.id.slice(0, 12)} icon={TagIcon} size={1} muted />\n )","2","displayInfo.title && (\n <Text\n size={1}\n weight=\"semibold\"\n style={{\n wordWrap: 'break-word',\n }}\n >\n {displayInfo.title}\n </Text>\n )","asset","<Inline gap={3}>\n {displayInfo?.duration && (\n <IconInfo text={displayInfo.duration} icon={ClockIcon} size={1} muted />\n )}\n <IconInfo\n text={displayInfo.createdAt.toISOString().split('T')[0]!}\n icon={CalendarIcon}\n size={1}\n muted\n />\n {displayInfo.title != displayInfo.id.slice(0, 12) && (\n <IconInfo text={displayInfo.id.slice(0, 12)} icon={TagIcon} size={1} muted />\n )}\n </Inline>","<Stack gap={2}>\n {displayInfo.title && (\n <Text\n size={1}\n weight=\"semibold\"\n style={{\n wordWrap: 'break-word',\n }}\n >\n {displayInfo.title}\n </Text>\n )}\n <Inline gap={3}>\n {displayInfo?.duration && (\n <IconInfo text={displayInfo.duration} icon={ClockIcon} size={1} muted />\n )}\n <IconInfo\n text={displayInfo.createdAt.toISOString().split('T')[0]!}\n icon={CalendarIcon}\n size={1}\n muted\n />\n {displayInfo.title != displayInfo.id.slice(0, 12) && (\n <IconInfo text={displayInfo.id.slice(0, 12)} icon={TagIcon} size={1} muted />\n )}\n </Inline>\n </Stack>","_c","{\n onSelect,\n onEdit,\n asset,\n}: {\n onSelect?: (asset: VideoAssetDocument) => void\n onEdit?: (asset: VideoAssetDocument) => void\n asset: VideoAssetDocument\n}","() => onSelect?.(asset)","useCallback(() => onSelect?.(asset), [onSelect, asset])","() => onEdit?.(asset)","useCallback(() => onEdit?.(asset), [onEdit, asset])","getPlaybackPolicy(asset)","() => {\n if (playbackPolicy?.policy === 'drm' && !hasShownWarning) {\n setRenderVideo('pre-render-warn')\n } else {\n setRenderVideo('render-video')\n }\n }","policy","{\n position: 'relative',\n }","playbackPolicy?.policy === 'signed' && (\n <Tooltip\n animate\n content={\n <Card padding={2} radius={2}>\n <IconInfo icon={LockIcon} text=\"Signed playback policy\" size={2} />\n </Card>\n }\n placement=\"right\"\n fallbackPlacements={['top', 'bottom']}\n portal\n >\n <Card\n tone=\"caution\"\n style={{\n borderRadius: '100%',\n position: 'absolute',\n left: '1em',\n top: '1em',\n zIndex: 11,\n }}\n padding={2}\n border\n >\n <Text muted size={1}>\n <LockIcon />\n </Text>\n </Card>\n </Tooltip>\n )","playbackPolicy?.policy === 'drm' && (\n <Tooltip\n animate\n content={\n <Card padding={2} radius={2}>\n <IconInfo icon={LockIcon} text=\"DRM playback policy\" size={2} />\n </Card>\n }\n placement=\"right\"\n fallbackPlacements={['top', 'bottom']}\n portal\n >\n <Card\n tone=\"caution\"\n style={{\n borderRadius: '0.25rem',\n position: 'absolute',\n left: '1em',\n top: '1em',\n zIndex: 11,\n }}\n padding={2}\n border\n >\n <Text muted size={1} weight=\"semibold\" style={{color: 'var(--card-icon-color)'}}>\n DRM\n </Text>\n </Card>\n </Tooltip>\n )","{\n gridTemplateRows: 'min-content min-content 1fr',\n }","renderVideo === 'pre-render-warn' && (\n <DRMWarningDialog\n onClose={() => {\n setRenderVideo('render-video')\n }}\n />\n )","renderVideo === 'render-video' ? (\n <VideoPlayer asset={asset} autoPlay forceAspectRatio={THUMBNAIL_ASPECT_RATIO} />\n ) : (\n <PlayButton onClick={onClickPlay}>\n <div data-play>\n <PlayIcon />\n </div>\n {assetIsAudio(asset) ? (\n <div\n style={{\n aspectRatio: THUMBNAIL_ASPECT_RATIO,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <AudioIcon width=\"3em\" height=\"3em\" />\n </div>\n ) : (\n <VideoThumbnail asset={asset} />\n )}\n </PlayButton>\n )","<VideoMetadata asset={asset} />","{\n display: 'flex',\n width: '100%',\n alignItems: 'flex-end',\n justifyContent: 'flex-start',\n gap: '.35rem',\n }","onSelect && (\n <Button\n icon={CheckmarkIcon}\n fontSize={2}\n padding={2}\n mode=\"ghost\"\n text=\"Select\"\n style={{flex: 1}}\n tone=\"positive\"\n onClick={select}\n />\n )","{flex: 1}","<Button\n icon={EditIcon}\n fontSize={2}\n padding={2}\n mode=\"ghost\"\n text=\"Details\"\n style={{flex: 1}}\n onClick={edit}\n />","<div\n style={{\n display: 'flex',\n width: '100%',\n alignItems: 'flex-end',\n justifyContent: 'flex-start',\n gap: '.35rem',\n }}\n >\n {onSelect && (\n <Button\n icon={CheckmarkIcon}\n fontSize={2}\n padding={2}\n mode=\"ghost\"\n text=\"Select\"\n style={{flex: 1}}\n tone=\"positive\"\n onClick={select}\n />\n )}\n <Button\n icon={EditIcon}\n fontSize={2}\n padding={2}\n mode=\"ghost\"\n text=\"Details\"\n style={{flex: 1}}\n onClick={edit}\n />\n </div>","<Stack\n gap={3}\n height=\"fill\"\n style={{\n gridTemplateRows: 'min-content min-content 1fr',\n }}\n >\n {renderVideo === 'pre-render-warn' && (\n <DRMWarningDialog\n onClose={() => {\n setRenderVideo('render-video')\n }}\n />\n )}\n {renderVideo === 'render-video' ? (\n <VideoPlayer asset={asset} autoPlay forceAspectRatio={THUMBNAIL_ASPECT_RATIO} />\n ) : (\n <PlayButton onClick={onClickPlay}>\n <div data-play>\n <PlayIcon />\n </div>\n {assetIsAudio(asset) ? (\n <div\n style={{\n aspectRatio: THUMBNAIL_ASPECT_RATIO,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <AudioIcon width=\"3em\" height=\"3em\" />\n </div>\n ) : (\n <VideoThumbnail asset={asset} />\n )}\n </PlayButton>\n )}\n <VideoMetadata asset={asset} />\n <div\n style={{\n display: 'flex',\n width: '100%',\n alignItems: 'flex-end',\n justifyContent: 'flex-start',\n gap: '.35rem',\n }}\n >\n {onSelect && (\n <Button\n icon={CheckmarkIcon}\n fontSize={2}\n padding={2}\n mode=\"ghost\"\n text=\"Select\"\n style={{flex: 1}}\n tone=\"positive\"\n onClick={select}\n />\n )}\n <Button\n icon={EditIcon}\n fontSize={2}\n padding={2}\n mode=\"ghost\"\n text=\"Details\"\n style={{flex: 1}}\n onClick={edit}\n />\n </div>\n </Stack>","<Card\n border\n padding={2}\n sizing=\"border\"\n radius={2}\n style={{\n position: 'relative',\n }}\n >\n {playbackPolicy?.policy === 'signed' && (\n <Tooltip\n animate\n content={\n <Card padding={2} radius={2}>\n <IconInfo icon={LockIcon} text=\"Signed playback policy\" size={2} />\n </Card>\n }\n placement=\"right\"\n fallbackPlacements={['top', 'bottom']}\n portal\n >\n <Card\n tone=\"caution\"\n style={{\n borderRadius: '100%',\n position: 'absolute',\n left: '1em',\n top: '1em',\n zIndex: 11,\n }}\n padding={2}\n border\n >\n <Text muted size={1}>\n <LockIcon />\n </Text>\n </Card>\n </Tooltip>\n )}\n {playbackPolicy?.policy === 'drm' && (\n <Tooltip\n animate\n content={\n <Card padding={2} radius={2}>\n <IconInfo icon={LockIcon} text=\"DRM playback policy\" size={2} />\n </Card>\n }\n placement=\"right\"\n fallbackPlacements={['top', 'bottom']}\n portal\n >\n <Card\n tone=\"caution\"\n style={{\n borderRadius: '0.25rem',\n position: 'absolute',\n left: '1em',\n top: '1em',\n zIndex: 11,\n }}\n padding={2}\n border\n >\n <Text muted size={1} weight=\"semibold\" style={{color: 'var(--card-icon-color)'}}>\n DRM\n </Text>\n </Card>\n </Tooltip>\n )}\n <Stack\n gap={3}\n height=\"fill\"\n style={{\n gridTemplateRows: 'min-content min-content 1fr',\n }}\n >\n {renderVideo === 'pre-render-warn' && (\n <DRMWarningDialog\n onClose={() => {\n setRenderVideo('render-video')\n }}\n />\n )}\n {renderVideo === 'render-video' ? (\n <VideoPlayer asset={asset} autoPlay forceAspectRatio={THUMBNAIL_ASPECT_RATIO} />\n ) : (\n <PlayButton onClick={onClickPlay}>\n <div data-play>\n <PlayIcon />\n </div>\n {assetIsAudio(asset) ? (\n <div\n style={{\n aspectRatio: THUMBNAIL_ASPECT_RATIO,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <AudioIcon width=\"3em\" height=\"3em\" />\n </div>\n ) : (\n <VideoThumbnail asset={asset} />\n )}\n </PlayButton>\n )}\n <VideoMetadata asset={asset} />\n <div\n style={{\n display: 'flex',\n width: '100%',\n alignItems: 'flex-end',\n justifyContent: 'flex-start',\n gap: '.35rem',\n }}\n >\n {onSelect && (\n <Button\n icon={CheckmarkIcon}\n fontSize={2}\n padding={2}\n mode=\"ghost\"\n text=\"Select\"\n style={{flex: 1}}\n tone=\"positive\"\n onClick={select}\n />\n )}\n <Button\n icon={EditIcon}\n fontSize={2}\n padding={2}\n mode=\"ghost\"\n text=\"Details\"\n style={{flex: 1}}\n onClick={edit}\n />\n </div>\n </Stack>\n </Card>","_c","{onSelect, config}: VideosBrowserProps","assets.find((a) => a._id === editedAsset?._id) || editedAsset","editedAsset?._id","useMemo(\n () => assets.find((a) => a._id === editedAsset?._id) || editedAsset,\n [editedAsset, assets],\n )","{minHeight: '50vh'}","(e: InputEvent<HTMLInputElement>) => setSearchQuery(e.currentTarget.value)","<TextInput\n value={searchQuery}\n icon={SearchIcon}\n onInput={(e: InputEvent<HTMLInputElement>) => setSearchQuery(e.currentTarget.value)}\n placeholder=\"Search videos\"\n />","<SelectSortOptions setSort={setSort} sort={sort} />","<PageSelector page={page} setPage={setPage} total={pageTotal} />","<Flex align=\"center\" gap={3}>\n <TextInput\n value={searchQuery}\n icon={SearchIcon}\n onInput={(e: InputEvent<HTMLInputElement>) => setSearchQuery(e.currentTarget.value)}\n placeholder=\"Search videos\"\n />\n <SelectSortOptions setSort={setSort} sort={sort} />\n <PageSelector page={page} setPage={setPage} total={pageTotal} />\n </Flex>","placement === 'tool' && (\n <Inline gap={2}>\n <ImportVideosFromMux />\n <ResyncMetadata />\n <ConfigureApi />\n </Inline>\n )","<Flex justify=\"space-between\" align=\"center\">\n <Flex align=\"center\" gap={3}>\n <TextInput\n value={searchQuery}\n icon={SearchIcon}\n onInput={(e: InputEvent<HTMLInputElement>) => setSearchQuery(e.currentTarget.value)}\n placeholder=\"Search videos\"\n />\n <SelectSortOptions setSort={setSort} sort={sort} />\n <PageSelector page={page} setPage={setPage} total={pageTotal} />\n </Flex>\n {placement === 'tool' && (\n <Inline gap={2}>\n <ImportVideosFromMux />\n <ResyncMetadata />\n <ConfigureApi />\n </Inline>\n )}\n </Flex>","assets?.length > 0 && (\n <Label muted>\n {assets.length} video{assets.length > 1 ? 's' : null}{' '}\n {searchQuery ? `matching \"${searchQuery}\"` : 'found'}\n </Label>\n )","length","{\n gridTemplateColumns: 'repeat(auto-fill, minmax(250px, 1fr))',\n }","assets.slice(pageStart, pageEnd).map((asset) => (\n <VideoInBrowser\n key={asset._id}\n asset={asset}\n onEdit={setEditedAsset}\n onSelect={onSelect}\n />\n ))","(asset) => (\n <VideoInBrowser\n key={asset._id}\n asset={asset}\n onEdit={setEditedAsset}\n onSelect={onSelect}\n />\n )","<Grid\n gap={2}\n style={{\n gridTemplateColumns: 'repeat(auto-fill, minmax(250px, 1fr))',\n }}\n >\n {assets.slice(pageStart, pageEnd).map((asset) => (\n <VideoInBrowser\n key={asset._id}\n asset={asset}\n onEdit={setEditedAsset}\n onSelect={onSelect}\n />\n ))}\n </Grid>","<Stack gap={3}>\n {assets?.length > 0 && (\n <Label muted>\n {assets.length} video{assets.length > 1 ? 's' : null}{' '}\n {searchQuery ? `matching \"${searchQuery}\"` : 'found'}\n </Label>\n )}\n <Grid\n gap={2}\n style={{\n gridTemplateColumns: 'repeat(auto-fill, minmax(250px, 1fr))',\n }}\n >\n {assets.slice(pageStart, pageEnd).map((asset) => (\n <VideoInBrowser\n key={asset._id}\n asset={asset}\n onEdit={setEditedAsset}\n onSelect={onSelect}\n />\n ))}\n </Grid>\n </Stack>","isLoading && <SpinnerBox />","!isLoading && assets.length === 0 && (\n <Card marginY={4} paddingX={4} paddingY={6} border radius={2} tone=\"transparent\">\n <Text align=\"center\" muted size={3}>\n {searchQuery ? `No videos found for \"${searchQuery}\"` : 'No videos in this dataset'}\n </Text>\n </Card>\n )","<Stack padding={4} gap={4} style={{minHeight: '50vh'}}>\n <Flex justify=\"space-between\" align=\"center\">\n <Flex align=\"center\" gap={3}>\n <TextInput\n value={searchQuery}\n icon={SearchIcon}\n onInput={(e: InputEvent<HTMLInputElement>) => setSearchQuery(e.currentTarget.value)}\n placeholder=\"Search videos\"\n />\n <SelectSortOptions setSort={setSort} sort={sort} />\n <PageSelector page={page} setPage={setPage} total={pageTotal} />\n </Flex>\n {placement === 'tool' && (\n <Inline gap={2}>\n <ImportVideosFromMux />\n <ResyncMetadata />\n <ConfigureApi />\n </Inline>\n )}\n </Flex>\n <Stack gap={3}>\n {assets?.length > 0 && (\n <Label muted>\n {assets.length} video{assets.length > 1 ? 's' : null}{' '}\n {searchQuery ? `matching \"${searchQuery}\"` : 'found'}\n </Label>\n )}\n <Grid\n gap={2}\n style={{\n gridTemplateColumns: 'repeat(auto-fill, minmax(250px, 1fr))',\n }}\n >\n {assets.slice(pageStart, pageEnd).map((asset) => (\n <VideoInBrowser\n key={asset._id}\n asset={asset}\n onEdit={setEditedAsset}\n onSelect={onSelect}\n />\n ))}\n </Grid>\n </Stack>\n {isLoading && <SpinnerBox />}\n\n {!isLoading && assets.length === 0 && (\n <Card marginY={4} paddingX={4} paddingY={6} border radius={2} tone=\"transparent\">\n <Text align=\"center\" muted size={3}>\n {searchQuery ? `No videos found for \"${searchQuery}\"` : 'No videos in this dataset'}\n </Text>\n </Card>\n )}\n </Stack>","freshEditedAsset && (\n <VideoDetails closeDialog={() => setEditedAsset(null)} asset={freshEditedAsset} />\n )","<DrmPlaybackWarningContextProvider config={config}>\n <Stack padding={4} gap={4} style={{minHeight: '50vh'}}>\n <Flex justify=\"space-between\" align=\"center\">\n <Flex align=\"center\" gap={3}>\n <TextInput\n value={searchQuery}\n icon={SearchIcon}\n onInput={(e: InputEvent<HTMLInputElement>) => setSearchQuery(e.currentTarget.value)}\n placeholder=\"Search videos\"\n />\n <SelectSortOptions setSort={setSort} sort={sort} />\n <PageSelector page={page} setPage={setPage} total={pageTotal} />\n </Flex>\n {placement === 'tool' && (\n <Inline gap={2}>\n <ImportVideosFromMux />\n <ResyncMetadata />\n <ConfigureApi />\n </Inline>\n )}\n </Flex>\n <Stack gap={3}>\n {assets?.length > 0 && (\n <Label muted>\n {assets.length} video{assets.length > 1 ? 's' : null}{' '}\n {searchQuery ? `matching \"${searchQuery}\"` : 'found'}\n </Label>\n )}\n <Grid\n gap={2}\n style={{\n gridTemplateColumns: 'repeat(auto-fill, minmax(250px, 1fr))',\n }}\n >\n {assets.slice(pageStart, pageEnd).map((asset) => (\n <VideoInBrowser\n key={asset._id}\n asset={asset}\n onEdit={setEditedAsset}\n onSelect={onSelect}\n />\n ))}\n </Grid>\n </Stack>\n {isLoading && <SpinnerBox />}\n\n {!isLoading && assets.length === 0 && (\n <Card marginY={4} paddingX={4} paddingY={6} border radius={2} tone=\"transparent\">\n <Text align=\"center\" muted size={3}>\n {searchQuery ? `No videos found for \"${searchQuery}\"` : 'No videos in this dataset'}\n </Text>\n </Card>\n )}\n </Stack>\n {freshEditedAsset && (\n <VideoDetails closeDialog={() => setEditedAsset(null)} asset={freshEditedAsset} />\n )}\n </DrmPlaybackWarningContextProvider>","_c","<VideosBrowser config={config} />","<MuxApiHostProvider muxApiHost={config.muxApiHost}>\n <VideosBrowser config={config} />\n </MuxApiHostProvider>","muxApiHost","_c","!config?.allowedRolesForConfiguration?.length ||\n user?.roles?.some((role) => config.allowedRolesForConfiguration.includes(role.name))","config?.allowedRolesForConfiguration?.length","roles","{hasConfigAccess}","_c","useMemo(() => {\n // Legacy: If static_renditions has a status field, it was created with mp4_support (deprecated)\n // We don't process this old format, just return false\n // Note: 'disabled' status is valid in the new format when no renditions were requested\n if (\n asset?.data?.static_renditions?.status &&\n asset?.data?.static_renditions?.status !== 'disabled'\n ) {\n return false\n }\n\n const files = asset?.data?.static_renditions?.files\n if (!files || files.length === 0) {\n return false\n }\n return files.some((file) => file.status === 'preparing')\n }, [asset?.data?.static_renditions?.status, asset?.data?.static_renditions?.files])","(file) => file.status === 'preparing'","async () => {\n try {\n const {data} = await getMuxAddonClient(client).request<{data: MuxAsset}>({\n url: `/addons/mux/assets/${dataset}/data/${asset!.assetId}`,\n withCredentials: true,\n method: 'GET',\n query: PLUGIN_VERSION_QUERY,\n })\n if (!asset?._id || !data) return\n await client\n .patch(asset._id)\n .set({status: data.status, data: addKeysToMuxData(data)})\n .commit({returnDocuments: false})\n errorLoggedRef.current = false\n } catch (error) {\n // Input re-throws `poll.error`, so a background polling failure would\n // crash the whole field. Swallow it instead.\n if (!errorLoggedRef.current) {\n errorLoggedRef.current = true\n console.error('[sanity-plugin-mux-input] Mux polling failed', {\n assetId: asset?.assetId,\n documentId: asset?._id,\n error,\n })\n }\n }\n }","asset!.assetId","error","{refreshInterval: 2000, refreshWhenHidden: true, dedupingInterval: 1000}","_c","useClient","_temp","{\n // oxlint-disable-next-line no-unstable-nested-components\n onDidCatch: (err, errorInfo) => {\n console.group(err.toString())\n console.groupCollapsed('console.error')\n console.error(err)\n console.groupEnd()\n if (err.stack) {\n console.groupCollapsed('error.stack')\n console.log(err.stack)\n console.groupEnd()\n }\n if (errorInfo?.componentStack) {\n console.groupCollapsed('errorInfo.componentStack')\n console.log(errorInfo.componentStack)\n console.groupEnd()\n }\n console.groupEnd()\n pushToast({\n status: 'error',\n title: 'Plugin crashed',\n description: (\n <Flex align=\"center\">\n <Inline gap={1}>\n An error happened while rendering\n <Button\n padding={1}\n fontSize={1}\n style={{transform: 'translateY(1px)'}}\n mode=\"ghost\"\n text={schemaType.title}\n onClick={() => {\n if (errorRef.current) {\n scrollIntoView(errorRef.current, {\n behavior: 'smooth',\n scrollMode: 'if-needed',\n block: 'center',\n })\n }\n }}\n />\n </Inline>\n </Flex>\n ),\n })\n },\n }","schemaType.title","() => {\n // Purge request cache before retrying, otherwise the cached errors will rethrow\n clear([name])\n\n reset()\n }","useCallback(() => {\n // Purge request cache before retrying, otherwise the cached errors will rethrow\n clear([name])\n\n reset()\n }, [reset])","[2, 3, 4, 4]","<Heading as=\"h1\">\n The <code>{name}</code> plugin crashed\n </Heading>","error?.message && (\n <Card padding={3} tone=\"critical\" shadow={1} radius={2}>\n <Text>{error.message}</Text>\n </Card>\n )","error?.message","<Inline>\n <Button onClick={handleRetry} text=\"Retry\" />\n </Inline>","<Card ref={errorRef} paddingX={[2, 3, 4, 4]} height=\"fill\" shadow={1} overflow=\"auto\">\n <Flex justify=\"flex-start\" align=\"center\" height=\"fill\">\n <Grid gridTemplateColumns={1} gap={[2, 3, 4, 4]}>\n <Heading as=\"h1\">\n The <code>{name}</code> plugin crashed\n </Heading>\n {error?.message && (\n <Card padding={3} tone=\"critical\" shadow={1} radius={2}>\n <Text>{error.message}</Text>\n </Card>\n )}\n <Inline>\n <Button onClick={handleRetry} text=\"Retry\" />\n </Inline>\n </Grid>\n </Flex>\n </Card>","<ErrorBoundary>{children}</ErrorBoundary>","_c","{padding: 1}","{aspectRatio: '16/9', width: '100%', borderRadius: '1px'}","<Spinner muted />","<div style={{padding: 1}}>\n <Card\n shadow={1}\n sizing=\"border\"\n style={{aspectRatio: '16/9', width: '100%', borderRadius: '1px'}}\n >\n <Flex align=\"center\" direction=\"column\" height=\"fill\" justify=\"center\">\n <Spinner muted />\n <Box marginTop={3}>\n <Text align=\"center\" muted size={1}>\n Loading…\n </Text>\n </Box>\n </Flex>\n </Card>\n </div>","_c","() => setDialogState('secrets')","useCallback(() => setDialogState('secrets'), [setDialogState])","{padding: 2}","{\n aspectRatio: '16/9',\n width: '100%',\n boxShadow: 'var(--card-bg-color) 0 0 0 2px',\n }","[2, 3, 4, 4]","<Inline paddingY={1}>\n <div style={{height: '32px'}}>\n <MuxLogo />\n </div>\n </Inline>","<Inline paddingY={1}>\n <Heading size={[0, 1, 2, 2]}>\n Upload and preview videos directly from your studio.\n </Heading>\n </Inline>","<>\n <div style={{padding: 2}}>\n <Card\n display=\"flex\"\n sizing=\"border\"\n style={{\n aspectRatio: '16/9',\n width: '100%',\n boxShadow: 'var(--card-bg-color) 0 0 0 2px',\n }}\n paddingX={[2, 3, 4, 4]}\n radius={1}\n tone=\"transparent\"\n >\n <Flex justify=\"flex-start\" align=\"center\">\n <Grid gridTemplateColumns={1} gap={[2, 3, 4, 4]}>\n <Inline paddingY={1}>\n <div style={{height: '32px'}}>\n <MuxLogo />\n </div>\n </Inline>\n <Inline paddingY={1}>\n <Heading size={[0, 1, 2, 2]}>\n Upload and preview videos directly from your studio.\n </Heading>\n </Inline>\n <Inline paddingY={1}>\n {hasConfigAccess ? (\n <Button mode=\"ghost\" icon={PlugIcon} text=\"Configure API\" onClick={handleOpen} />\n ) : (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"critical\">\n <Text>\n You do not have access to configure the Mux API. Please contact your\n administrator.\n </Text>\n </Card>\n )}\n </Inline>\n </Grid>\n </Flex>\n </Card>\n </div>\n </>","_c","_Fragment","uuid","generateUuid","{\n asset: selectedAsset,\n onChange,\n setDialogState,\n config,\n}: Props","(chosenAsset) => {\n if (!chosenAsset?._id) {\n onChange(PatchEvent.from([unset(['asset'])]))\n }\n if (chosenAsset._id !== selectedAsset?._id) {\n onChange(\n PatchEvent.from([\n setIfMissing({asset: {}, _type: 'mux.video'}),\n set({_type: 'reference', _weak: true, _ref: chosenAsset._id}, ['asset']),\n ]),\n )\n }\n setDialogState(false)\n }","_id","useCallback<Required<VideosBrowserProps>['onSelect']>(\n (chosenAsset) => {\n if (!chosenAsset?._id) {\n onChange(PatchEvent.from([unset(['asset'])]))\n }\n if (chosenAsset._id !== selectedAsset?._id) {\n onChange(\n PatchEvent.from([\n setIfMissing({asset: {}, _type: 'mux.video'}),\n set({_type: 'reference', _weak: true, _ref: chosenAsset._id}, ['asset']),\n ]),\n )\n }\n setDialogState(false)\n },\n [onChange, setDialogState, selectedAsset],\n )","<VideosBrowser onSelect={handleSelect} config={config} />","_c","{\n setDialogState,\n asset,\n onChange,\n config,\n}: Pick<SelectAssetProps, 'onChange' | 'asset' | 'config'> & {\n setDialogState: SetDialogState\n}","() => setDialogState(false)","useCallback(() => setDialogState(false), [setDialogState])","<SelectAsset\n config={config}\n asset={asset}\n onChange={onChange}\n setDialogState={setDialogState}\n />","<StyledDialog\n __unstable_autoFocus\n header=\"Select video\"\n id={id}\n onClose={handleClose}\n width={2}\n >\n <SelectAsset\n config={config}\n asset={asset}\n onChange={onChange}\n setDialogState={setDialogState}\n />\n </StyledDialog>","_c","SelectAsset","() => {\n if (!asset) {\n return\n }\n onChange(PatchEvent.from(unset()))\n if (asset.assetId) {\n void deleteAssetOnMux(client, asset.assetId)\n }\n if (asset._id) {\n void client.delete(asset._id)\n }\n }","useCallback(() => {\n if (!asset) {\n return\n }\n onChange(PatchEvent.from(unset()))\n if (asset.assetId) {\n void deleteAssetOnMux(client, asset.assetId)\n }\n if (asset._id) {\n void client.delete(asset._id)\n }\n }, [asset, client, onChange])","_c","useClient","{\n progress = 100,\n onCancel,\n filename,\n text = 'Uploading',\n}: {\n progress: number\n filename?: React.ReactNode\n onCancel?: React.MouseEventHandler<HTMLButtonElement>\n text?: React.ReactNode\n}","progress = 100","text = 'Uploading'","[3, 3, 2, 2]","['column', 'column', 'row']","<CodeWrapper size={1}>{filename ? filename : '...'}</CodeWrapper>","filename ? filename : '...'","<Flex justify=\"center\" gap={[3, 3, 2, 2]} direction={['column', 'column', 'row']}>\n <Text size={1}>\n <Inline gap={2}>\n {text}\n <CodeWrapper size={1}>{filename ? filename : '...'}</CodeWrapper>\n </Inline>\n </Text>\n </Flex>","<Card marginTop={3} radius={5} shadow={1}>\n <LinearProgress value={progress} />\n </Card>","<LeftSection>\n <Flex justify=\"center\" gap={[3, 3, 2, 2]} direction={['column', 'column', 'row']}>\n <Text size={1}>\n <Inline gap={2}>\n {text}\n <CodeWrapper size={1}>{filename ? filename : '...'}</CodeWrapper>\n </Inline>\n </Text>\n </Flex>\n\n <Card marginTop={3} radius={5} shadow={1}>\n <LinearProgress value={progress} />\n </Card>\n </LeftSection>","onCancel ? (\n <Button\n fontSize={2}\n text=\"Cancel upload\"\n mode=\"ghost\"\n tone=\"critical\"\n onClick={onCancel}\n disabled={isCancelDisabled}\n />\n ) : null","<CardWrapper tone=\"primary\" padding={4} border height=\"fill\">\n <FlexWrapper align=\"center\" justify=\"space-between\" height=\"fill\" direction=\"row\" gap={2}>\n <LeftSection>\n <Flex justify=\"center\" gap={[3, 3, 2, 2]} direction={['column', 'column', 'row']}>\n <Text size={1}>\n <Inline gap={2}>\n {text}\n <CodeWrapper size={1}>{filename ? filename : '...'}</CodeWrapper>\n </Inline>\n </Text>\n </Flex>\n\n <Card marginTop={3} radius={5} shadow={1}>\n <LinearProgress value={progress} />\n </Card>\n </LeftSection>\n\n {onCancel ? (\n <Button\n fontSize={2}\n text=\"Cancel upload\"\n mode=\"ghost\"\n tone=\"critical\"\n onClick={onCancel}\n disabled={isCancelDisabled}\n />\n ) : null}\n </FlexWrapper>\n </CardWrapper>","_c","gap = 3","(event: React.ChangeEvent<HTMLInputElement>) => {\n if (onSelect && event.target.files) {\n onSelect(Array.from(event.target.files))\n }\n }","useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n if (onSelect && event.target.files) {\n onSelect(Array.from(event.target.files))\n }\n },\n [onSelect],\n )","Icon && (\n <Box marginRight={text ? gap : undefined}>\n <Text size={fontSize}>\n {isValidElement(Icon) && Icon}\n {isValidElementType(Icon) && <Icon />}\n </Text>\n </Box>\n )","text && (\n <Text align={textAlign} size={fontSize} textOverflow=\"ellipsis\">\n {text}\n </Text>\n )","<Flex align=\"center\" justify=\"flex-start\">\n {/* Icon */}\n {Icon && (\n <Box marginRight={text ? gap : undefined}>\n <Text size={fontSize}>\n {isValidElement(Icon) && Icon}\n {isValidElementType(Icon) && <Icon />}\n </Text>\n </Box>\n )}\n\n {/* Text */}\n {text && (\n <Text align={textAlign} size={fontSize} textOverflow=\"ellipsis\">\n {text}\n </Text>\n )}\n </Flex>","<input\n data-testid=\"file-button-input\"\n accept={accept}\n capture={capture}\n id={id}\n multiple={multiple}\n onChange={handleChange}\n type=\"file\"\n value=\"\"\n disabled={disabled}\n />","<FileButton {...rest} htmlFor={id} disabled={disabled} ref={ref}>\n {content}\n\n {/* Visibly hidden input */}\n <input\n data-testid=\"file-button-input\"\n accept={accept}\n capture={capture}\n id={id}\n multiple={multiple}\n onChange={handleChange}\n type=\"file\"\n value=\"\"\n disabled={disabled}\n />\n </FileButton>","_c","{showToast: true}","() => onChange(PatchEvent.from(unset([])))","useCallback(() => onChange(PatchEvent.from(unset([]))), [onChange])","async () => {\n setOpen(false)\n await resyncAsset(asset)\n }","useCallback(async () => {\n setOpen(false)\n await resyncAsset(asset)\n }, [resyncAsset, asset])","() => {\n if (open && dialogState) {\n // oxlint-disable-next-line react/set-state-in-effect\n setOpen(false)\n }\n }","[dialogState, open]","() => setOpen(false)","() => [menuElement]","isSigned && (\n <Tooltip\n animate\n content={\n <Box padding={2}>\n <Text muted size={1}>\n Signed playback policy\n </Text>\n </Box>\n }\n placement=\"right\"\n portal\n >\n <LockCard radius={2} margin={2} scheme=\"dark\" tone=\"positive\">\n <LockButton icon={LockIcon} mode=\"bleed\" tone=\"positive\" />\n </LockCard>\n </Tooltip>\n )","<Box padding={2}>\n <Label muted size={1}>\n Replace\n </Label>\n </Box>","<FileInputMenuItem\n accept={accept}\n icon={UploadIcon}\n onSelect={onSelect}\n text=\"Upload\"\n disabled={readOnly}\n fontSize={1}\n />","<MenuItem\n icon={SearchIcon}\n text=\"Browse\"\n onClick={() => setDialogState('select-video')}\n />","isVideoAsset(asset) && (\n <>\n <MenuItem\n icon={ImageIcon}\n text=\"Thumbnail\"\n onClick={() => setDialogState('edit-thumbnail')}\n />\n <MenuItem\n icon={TranslateIcon}\n text=\"Captions\"\n onClick={() => setDialogState('edit-captions')}\n />\n <MenuItem\n icon={SyncIcon}\n text=\"Resync from Mux\"\n onClick={handleResync}\n disabled={readOnly || isResyncing}\n />\n </>\n )","<MenuDivider />","<MenuItem\n icon={DownloadIcon}\n text=\"Mezzanine\"\n onClick={() => setDialogState('mezzanine')}\n />","hasConfigAccess && (\n <>\n <MenuItem\n icon={PlugIcon}\n text=\"Configure API\"\n onClick={() => setDialogState('secrets')}\n />\n <MenuDivider />\n </>\n )","<MenuItem\n tone=\"critical\"\n icon={ResetIcon}\n text=\"Clear field\"\n onClick={onReset}\n disabled={readOnly}\n />","<Menu ref={setMenuRef}>\n <Box padding={2}>\n <Label muted size={1}>\n Replace\n </Label>\n </Box>\n <FileInputMenuItem\n accept={accept}\n icon={UploadIcon}\n onSelect={onSelect}\n text=\"Upload\"\n disabled={readOnly}\n fontSize={1}\n />\n <MenuItem\n icon={SearchIcon}\n text=\"Browse\"\n onClick={() => setDialogState('select-video')}\n />\n {isVideoAsset(asset) && (\n <>\n <MenuItem\n icon={ImageIcon}\n text=\"Thumbnail\"\n onClick={() => setDialogState('edit-thumbnail')}\n />\n <MenuItem\n icon={TranslateIcon}\n text=\"Captions\"\n onClick={() => setDialogState('edit-captions')}\n />\n <MenuItem\n icon={SyncIcon}\n text=\"Resync from Mux\"\n onClick={handleResync}\n disabled={readOnly || isResyncing}\n />\n </>\n )}\n <MenuDivider />\n <MenuItem\n icon={DownloadIcon}\n text=\"Mezzanine\"\n onClick={() => setDialogState('mezzanine')}\n />\n <MenuDivider />\n {hasConfigAccess && (\n <>\n <MenuItem\n icon={PlugIcon}\n text=\"Configure API\"\n onClick={() => setDialogState('secrets')}\n />\n <MenuDivider />\n </>\n )}\n <MenuItem\n tone=\"critical\"\n icon={ResetIcon}\n text=\"Clear field\"\n onClick={onReset}\n disabled={readOnly}\n />\n </Menu>","<Button\n icon={EllipsisHorizontalIcon}\n mode=\"ghost\"\n fontSize={1}\n onClick={() => {\n setDialogState(false)\n setOpen(true)\n }}\n />","<Popover\n animate\n content={\n <Menu ref={setMenuRef}>\n <Box padding={2}>\n <Label muted size={1}>\n Replace\n </Label>\n </Box>\n <FileInputMenuItem\n accept={accept}\n icon={UploadIcon}\n onSelect={onSelect}\n text=\"Upload\"\n disabled={readOnly}\n fontSize={1}\n />\n <MenuItem\n icon={SearchIcon}\n text=\"Browse\"\n onClick={() => setDialogState('select-video')}\n />\n {isVideoAsset(asset) && (\n <>\n <MenuItem\n icon={ImageIcon}\n text=\"Thumbnail\"\n onClick={() => setDialogState('edit-thumbnail')}\n />\n <MenuItem\n icon={TranslateIcon}\n text=\"Captions\"\n onClick={() => setDialogState('edit-captions')}\n />\n <MenuItem\n icon={SyncIcon}\n text=\"Resync from Mux\"\n onClick={handleResync}\n disabled={readOnly || isResyncing}\n />\n </>\n )}\n <MenuDivider />\n <MenuItem\n icon={DownloadIcon}\n text=\"Mezzanine\"\n onClick={() => setDialogState('mezzanine')}\n />\n <MenuDivider />\n {hasConfigAccess && (\n <>\n <MenuItem\n icon={PlugIcon}\n text=\"Configure API\"\n onClick={() => setDialogState('secrets')}\n />\n <MenuDivider />\n </>\n )}\n <MenuItem\n tone=\"critical\"\n icon={ResetIcon}\n text=\"Clear field\"\n onClick={onReset}\n disabled={readOnly}\n />\n </Menu>\n }\n portal\n open={open}\n >\n <Button\n icon={EllipsisHorizontalIcon}\n mode=\"ghost\"\n fontSize={1}\n onClick={() => {\n setDialogState(false)\n setOpen(true)\n }}\n />\n </Popover>","<Inline gap={1} padding={2}>\n {isSigned && (\n <Tooltip\n animate\n content={\n <Box padding={2}>\n <Text muted size={1}>\n Signed playback policy\n </Text>\n </Box>\n }\n placement=\"right\"\n portal\n >\n <LockCard radius={2} margin={2} scheme=\"dark\" tone=\"positive\">\n <LockButton icon={LockIcon} mode=\"bleed\" tone=\"positive\" />\n </LockCard>\n </Tooltip>\n )}\n <Popover\n animate\n content={\n <Menu ref={setMenuRef}>\n <Box padding={2}>\n <Label muted size={1}>\n Replace\n </Label>\n </Box>\n <FileInputMenuItem\n accept={accept}\n icon={UploadIcon}\n onSelect={onSelect}\n text=\"Upload\"\n disabled={readOnly}\n fontSize={1}\n />\n <MenuItem\n icon={SearchIcon}\n text=\"Browse\"\n onClick={() => setDialogState('select-video')}\n />\n {isVideoAsset(asset) && (\n <>\n <MenuItem\n icon={ImageIcon}\n text=\"Thumbnail\"\n onClick={() => setDialogState('edit-thumbnail')}\n />\n <MenuItem\n icon={TranslateIcon}\n text=\"Captions\"\n onClick={() => setDialogState('edit-captions')}\n />\n <MenuItem\n icon={SyncIcon}\n text=\"Resync from Mux\"\n onClick={handleResync}\n disabled={readOnly || isResyncing}\n />\n </>\n )}\n <MenuDivider />\n <MenuItem\n icon={DownloadIcon}\n text=\"Mezzanine\"\n onClick={() => setDialogState('mezzanine')}\n />\n <MenuDivider />\n {hasConfigAccess && (\n <>\n <MenuItem\n icon={PlugIcon}\n text=\"Configure API\"\n onClick={() => setDialogState('secrets')}\n />\n <MenuDivider />\n </>\n )}\n <MenuItem\n tone=\"critical\"\n icon={ResetIcon}\n text=\"Clear field\"\n onClick={onReset}\n disabled={readOnly}\n />\n </Menu>\n }\n portal\n open={open}\n >\n <Button\n icon={EllipsisHorizontalIcon}\n mode=\"ghost\"\n fontSize={1}\n onClick={() => {\n setDialogState(false)\n setOpen(true)\n }}\n />\n </Popover>\n </Inline>","_c","_Fragment","() => {\n // Fetch URL Upload file size\n if (stagedUpload.type === 'url') {\n // oxlint-disable-next-line react/set-state-in-effect\n setIsLoadingFileSize(false)\n setCanSkipFileSizeValidation(false)\n setFileSize(null)\n const url = stagedUpload.url\n\n // Get file size from URL\n const fetchFileSize = async () => {\n setIsLoadingFileSize(true)\n try {\n const response = await fetch(url, {method: 'HEAD'})\n const contentLength = response.headers.get('content-length')\n const newFileSize = contentLength ? parseInt(contentLength, 10) : null\n\n setIsLoadingFileSize(false)\n if (newFileSize) {\n setFileSize(newFileSize)\n }\n if (newFileSize === null && maxFileSize !== undefined) {\n // Size unknown but size limit is configured - skip file size validation\n setCanSkipFileSizeValidation(true)\n }\n } catch {\n console.warn('Could not validate file size from URL')\n // Skip validation of file size, but still validate duration\n setCanSkipFileSizeValidation(true)\n setIsLoadingFileSize(false)\n }\n }\n\n void fetchFileSize()\n }\n if (stagedUpload.type === 'file') {\n setFileSize(stagedUpload.files[0]!.size)\n }\n }","files","type","url","[maxFileSize, stagedUpload, stagedUpload.type]","{\n fileSize,\n isLoadingFileSize,\n canSkipFileSizeValidation,\n }","_c","() => {\n let videoSrc = null\n // Validate file uploads\n if (stagedUpload.type === 'file') {\n const file = stagedUpload.files[0]\n videoSrc = URL.createObjectURL(file!)\n }\n\n // Validate URL uploads\n if (stagedUpload.type === 'url') {\n videoSrc = stagedUpload.url\n }\n\n // oxlint-disable-next-line react/set-state-in-effect\n setVideoAssetMetadata((old) => ({\n ...old,\n duration: undefined,\n width: undefined,\n height: undefined,\n }))\n\n if (!videoSrc) return () => null\n\n setIsLoadingMetadata(true)\n const videoElement = document.createElement('video')\n videoElement.preload = 'metadata'\n\n const metadataListeners = [\n () => {\n setIsLoadingMetadata(false)\n },\n () => {\n const duration = videoElement.duration\n const width = videoElement.videoWidth\n const height = videoElement.videoHeight\n const isAudioOnly = width <= 0 && height <= 0\n const aspectRatio = width / height\n setVideoAssetMetadata((old) => {\n return {\n ...old,\n duration: duration,\n width: width,\n height: height,\n isAudioOnly: isAudioOnly,\n aspectRatio: aspectRatio,\n }\n })\n },\n ]\n\n const cleanupVideo = (videoEl: HTMLVideoElement) => {\n const currentVideoSrc = videoEl?.src\n if (videoEl) {\n metadataListeners.forEach((listener) =>\n videoEl.removeEventListener('loadedmetadata', listener),\n )\n videoEl.onerror = null\n videoEl.src = ''\n videoEl.load()\n }\n if (currentVideoSrc?.startsWith('blob:')) {\n URL.revokeObjectURL(currentVideoSrc)\n }\n }\n metadataListeners.push(() => setTimeout(() => cleanupVideo(videoElement), 0))\n\n videoElement.onerror = () => {\n setIsLoadingMetadata(false)\n console.warn('Could not read video metadata for validation')\n cleanupVideo(videoElement)\n }\n\n metadataListeners.forEach((listener) =>\n videoElement.addEventListener('loadedmetadata', listener),\n )\n videoElement.src = videoSrc\n\n return () => {\n cleanupVideo(videoElement)\n }\n }","files","type","url","(old) => ({\n ...old,\n duration: undefined,\n width: undefined,\n height: undefined,\n })","() => null","old","listener","[stagedUpload.type, stagedUpload]","stagedUpload.type","{\n videoAssetMetadata,\n setVideoAssetMetadata,\n isLoadingMetadata,\n }","_c","_temp","_temp2","_Fragment","{\n tracks,\n dispatch,\n defaultLang,\n}: {\n /**\n * Although the schema for tracks is an array, which we'll eventually support to allow uploading\n * multiple custom subtitles, for now we only support a single auto-generated track.\n */\n tracks: (Partial<UploadTextTrack> & {_id: string})[]\n dispatch: Dispatch<TrackAction>\n defaultLang: PluginConfig['defaultAutogeneratedSubtitleLang']\n}","[]","{display: 'block'}","() => {\n if (track) {\n dispatch({action: 'track', id: track._id, subAction: 'delete'})\n } else {\n dispatch({\n action: 'track',\n id: uuid(),\n subAction: 'add',\n value: {\n type: 'autogenerated',\n name: defaultLang || undefined,\n language_code: defaultLang || undefined,\n },\n })\n }\n }","<Checkbox\n id=\"include-autogenerated-track\"\n style={{display: 'block'}}\n checked={!!track?.language_code}\n onChange={() => {\n if (track) {\n dispatch({action: 'track', id: track._id, subAction: 'delete'})\n } else {\n dispatch({\n action: 'track',\n id: uuid(),\n subAction: 'add',\n value: {\n type: 'autogenerated',\n name: defaultLang || undefined,\n language_code: defaultLang || undefined,\n },\n })\n }\n }}\n />","!!track?.language_code","<Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor=\"checkbox\">Generate captions</label>\n </Text>\n </Box>","<Flex align=\"center\">\n <Checkbox\n id=\"include-autogenerated-track\"\n style={{display: 'block'}}\n checked={!!track?.language_code}\n onChange={() => {\n if (track) {\n dispatch({action: 'track', id: track._id, subAction: 'delete'})\n } else {\n dispatch({\n action: 'track',\n id: uuid(),\n subAction: 'add',\n value: {\n type: 'autogenerated',\n name: defaultLang || undefined,\n language_code: defaultLang || undefined,\n },\n })\n }\n }}\n />\n <Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor=\"checkbox\">Generate captions</label>\n </Text>\n </Box>\n </Flex>","track && (\n <Autocomplete\n id={`text-tract-editor--language`}\n value={track.language_code}\n onChange={(newValue) =>\n dispatch({\n action: 'track',\n id: track._id,\n subAction: 'update',\n value: {\n language_code: newValue,\n name: LanguagesList.getNativeName(newValue),\n },\n })\n }\n options={SUBTITLE_LANGUAGES[track.type!]}\n icon={TranslateIcon}\n placeholder=\"Select language\"\n filterOption={(query, option) =>\n option.label.toLowerCase().indexOf(query.toLowerCase()) > -1 ||\n option.value.toLowerCase().indexOf(query.toLowerCase()) > -1\n }\n openButton\n renderValue={(value) =>\n SUBTITLE_LANGUAGES[track.type!].find((l) => l.value === value)?.label || value\n }\n renderOption={(option) => (\n <Card data-as=\"button\" padding={3} radius={2} tone=\"inherit\">\n <Text size={2} textOverflow=\"ellipsis\">\n {option.label} ({option.value})\n </Text>\n </Card>\n )}\n />\n )","(query, option) =>\n option.label.toLowerCase().indexOf(query.toLowerCase()) > -1 ||\n option.value.toLowerCase().indexOf(query.toLowerCase()) > -1","(option) => (\n <Card data-as=\"button\" padding={3} radius={2} tone=\"inherit\">\n <Text size={2} textOverflow=\"ellipsis\">\n {option.label} ({option.value})\n </Text>\n </Card>\n )","<FormField title=\"Auto-generated subtitle or caption\" path={[]}>\n <Stack gap={2}>\n <Flex align=\"center\">\n <Checkbox\n id=\"include-autogenerated-track\"\n style={{display: 'block'}}\n checked={!!track?.language_code}\n onChange={() => {\n if (track) {\n dispatch({action: 'track', id: track._id, subAction: 'delete'})\n } else {\n dispatch({\n action: 'track',\n id: uuid(),\n subAction: 'add',\n value: {\n type: 'autogenerated',\n name: defaultLang || undefined,\n language_code: defaultLang || undefined,\n },\n })\n }\n }}\n />\n <Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor=\"checkbox\">Generate captions</label>\n </Text>\n </Box>\n </Flex>\n {track && (\n <Autocomplete\n id={`text-tract-editor--language`}\n value={track.language_code}\n onChange={(newValue) =>\n dispatch({\n action: 'track',\n id: track._id,\n subAction: 'update',\n value: {\n language_code: newValue,\n name: LanguagesList.getNativeName(newValue),\n },\n })\n }\n options={SUBTITLE_LANGUAGES[track.type!]}\n icon={TranslateIcon}\n placeholder=\"Select language\"\n filterOption={(query, option) =>\n option.label.toLowerCase().indexOf(query.toLowerCase()) > -1 ||\n option.value.toLowerCase().indexOf(query.toLowerCase()) > -1\n }\n openButton\n renderValue={(value) =>\n SUBTITLE_LANGUAGES[track.type!].find((l) => l.value === value)?.label || value\n }\n renderOption={(option) => (\n <Card data-as=\"button\" padding={3} radius={2} tone=\"inherit\">\n <Text size={2} textOverflow=\"ellipsis\">\n {option.label} ({option.value})\n </Text>\n </Card>\n )}\n />\n )}\n </Stack>\n </FormField>","option","_c","_temp","_temp2","{\n id,\n checked,\n optionName,\n description,\n dispatch,\n action,\n disabled,\n}: {\n id: string\n checked: boolean\n optionName: string\n description: string | ReactNode\n dispatch: ActionDispatch<[action: UploadConfigurationStateAction]>\n action?: 'public_policy' | 'signed_policy' | 'drm_policy'\n disabled?: boolean\n}","{\n outline: '0.01rem solid grey',\n transform: `scale(${scale})`,\n transition: 'transform 0.1s ease-in-out',\n cursor: disabled ? 'not-allowed' : 'pointer',\n borderRadius: '0.25rem',\n }","`scale(${scale})`","disabled ? 'not-allowed' : 'pointer'","() => {\n setScale(0.98)\n setTimeout(() => {\n setScale(1)\n }, 100)\n }","() => {\n if (!action) return\n triggerAnimation()\n dispatch({\n action,\n value: !checked,\n })\n }","typeof description === 'string' ? (\n <Text size={2} muted>\n {description}\n </Text>\n ) : (\n description\n )","<Checkbox\n id={id}\n required\n checked={checked}\n onChange={handleBoxClick}\n disabled={disabled}\n />","<Text size={3} weight=\"bold\">\n {optionName}\n </Text>","<Grid gap={3}>\n <Text size={3} weight=\"bold\">\n {optionName}\n </Text>\n {descriptionJsx}\n </Grid>","<label>\n <Flex gap={3} padding={3} style={boxStyle}>\n <Checkbox\n id={id}\n required\n checked={checked}\n onChange={handleBoxClick}\n disabled={disabled}\n />\n <Grid gap={3}>\n <Text size={3} weight=\"bold\">\n {optionName}\n </Text>\n {descriptionJsx}\n </Grid>\n </Flex>\n </label>","_c","{\n color: '#13141A',\n fontWeight: 500,\n }","{\n outline: '0.01rem solid grey',\n backgroundColor: '#979cb0',\n borderRadius: '0.5rem',\n width: 'max-content',\n color: '#13141A',\n }","<Box padding={2} style={boxStyle}>\n <Flex align=\"center\" gap={2}>\n <WarningFilledIcon />\n <Text size={1} style={textStyle}>\n Please select at least one Playback Policy\n </Text>\n </Flex>\n </Box>","_c","{\n id,\n config,\n secrets,\n dispatch,\n}: {\n id: string\n config: UploadConfig\n secrets: Secrets\n dispatch: ActionDispatch<[action: UploadConfigurationStateAction]>\n}","<Text weight=\"bold\">Advanced Playback Policies</Text>","<>\n <Text size={2} muted>\n Playback IDs are accessible by constructing an HLS URL like\n </Text>\n <Code>{'https://stream.mux.com/{PLAYBACK_ID}'}</Code>\n </>","<PlaybackPolicyOption\n id={`${id}--public`}\n checked={config.public_policy}\n optionName=\"Public\"\n description={\n <>\n <Text size={2} muted>\n Playback IDs are accessible by constructing an HLS URL like\n </Text>\n <Code>{'https://stream.mux.com/{PLAYBACK_ID}'}</Code>\n </>\n }\n dispatch={dispatch}\n action=\"public_policy\"\n />","public_policy","`${id}--public`","secrets.enableSignedUrls && (\n <PlaybackPolicyOption\n id={`${id}--signed`}\n checked={config.signed_policy}\n optionName=\"Signed\"\n description={\n <>\n <Text size={2} muted>\n Playback IDs should be used with tokens\n </Text>\n <Code>{'https://stream.mux.com/{PLAYBACK_ID}?token={TOKEN}'}</Code>\n <Text size={2} muted>\n See{' '}\n <a\n href=\"https://www.mux.com/docs/guides/secure-video-playback\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Secure video playback\n </a>{' '}\n for details about creating tokens.\n </Text>\n </>\n }\n // See Secure video playback for details about creating tokens.\"\n dispatch={dispatch}\n action=\"signed_policy\"\n />\n )","signed_policy","enableSignedUrls","drmPolicyDisabled ? (\n <PlaybackPolicyOption\n id={`${id}--drm`}\n checked={false}\n optionName=\"DRM - Disabled\"\n description={\n <>\n <Text size={2} muted>\n To enable DRM add your DRM Configuration Id to your plugin configuration in the API\n Credentials view.{' '}\n <a\n href=\"https://www.mux.com/support/human\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Contact us\n </a>{' '}\n to get started using DRM.\n </Text>\n </>\n }\n dispatch={dispatch}\n disabled\n />\n ) : (\n <PlaybackPolicyOption\n id={`${id}--drm`}\n checked={config.drm_policy}\n optionName=\"DRM\"\n description={\n <>\n <Text size={2} muted>\n Playback IDs should be used with tokens as with Signed playback, but require extra\n configuration.\n </Text>\n <Code>{'https://stream.mux.com/{PLAYBACK_ID}?token={TOKEN}'}</Code>\n <Text size={2} muted>\n See{' '}\n <a\n href=\"https://www.mux.com/docs/guides/protect-videos-with-drm#play-drm-protected-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Protect videos with DRM\n </a>{' '}\n for details about configuring your player for DRM playback and{' '}\n <a\n href=\"https://www.mux.com/docs/guides/secure-video-playback\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Secure video playback\n </a>{' '}\n for details about creating tokens.\n </Text>\n </>\n }\n dispatch={dispatch}\n action=\"drm_policy\"\n />\n )","drm_policy","noPolicySelected && <PlaybackPolicyWarning />","<Grid gap={3}>\n <Text weight=\"bold\">Advanced Playback Policies</Text>\n <PlaybackPolicyOption\n id={`${id}--public`}\n checked={config.public_policy}\n optionName=\"Public\"\n description={\n <>\n <Text size={2} muted>\n Playback IDs are accessible by constructing an HLS URL like\n </Text>\n <Code>{'https://stream.mux.com/{PLAYBACK_ID}'}</Code>\n </>\n }\n dispatch={dispatch}\n action=\"public_policy\"\n />\n {secrets.enableSignedUrls && (\n <PlaybackPolicyOption\n id={`${id}--signed`}\n checked={config.signed_policy}\n optionName=\"Signed\"\n description={\n <>\n <Text size={2} muted>\n Playback IDs should be used with tokens\n </Text>\n <Code>{'https://stream.mux.com/{PLAYBACK_ID}?token={TOKEN}'}</Code>\n <Text size={2} muted>\n See{' '}\n <a\n href=\"https://www.mux.com/docs/guides/secure-video-playback\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Secure video playback\n </a>{' '}\n for details about creating tokens.\n </Text>\n </>\n }\n // See Secure video playback for details about creating tokens.\"\n dispatch={dispatch}\n action=\"signed_policy\"\n />\n )}\n {drmPolicyDisabled ? (\n <PlaybackPolicyOption\n id={`${id}--drm`}\n checked={false}\n optionName=\"DRM - Disabled\"\n description={\n <>\n <Text size={2} muted>\n To enable DRM add your DRM Configuration Id to your plugin configuration in the API\n Credentials view.{' '}\n <a\n href=\"https://www.mux.com/support/human\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Contact us\n </a>{' '}\n to get started using DRM.\n </Text>\n </>\n }\n dispatch={dispatch}\n disabled\n />\n ) : (\n <PlaybackPolicyOption\n id={`${id}--drm`}\n checked={config.drm_policy}\n optionName=\"DRM\"\n description={\n <>\n <Text size={2} muted>\n Playback IDs should be used with tokens as with Signed playback, but require extra\n configuration.\n </Text>\n <Code>{'https://stream.mux.com/{PLAYBACK_ID}?token={TOKEN}'}</Code>\n <Text size={2} muted>\n See{' '}\n <a\n href=\"https://www.mux.com/docs/guides/protect-videos-with-drm#play-drm-protected-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Protect videos with DRM\n </a>{' '}\n for details about configuring your player for DRM playback and{' '}\n <a\n href=\"https://www.mux.com/docs/guides/secure-video-playback\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Secure video playback\n </a>{' '}\n for details about creating tokens.\n </Text>\n </>\n }\n dispatch={dispatch}\n action=\"drm_policy\"\n />\n )}\n {noPolicySelected && <PlaybackPolicyWarning />}\n </Grid>","_c","_Fragment","{\n id,\n config,\n dispatch,\n maxSupportedResolution,\n}: {\n id: string\n config: UploadConfig\n dispatch: ActionDispatch<[action: UploadConfigurationStateAction]>\n maxSupportedResolution: number\n}","[]","<>\n The maximum{' '}\n <a\n href=\"https://docs.mux.com/api-reference#video/operation/create-direct-upload\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n resolution_tier\n </a>{' '}\n your asset is encoded, stored, and streamed at.\n </>","RESOLUTION_TIERS.map(({value, label}, index) => {\n const inputId = `${id}--type-${value}`\n\n if (index > maxSupportedResolution) return null\n\n return (\n <Flex key={value} align=\"center\" gap={2}>\n <Radio\n checked={config.max_resolution_tier === value}\n name=\"asset-resolutiontier\"\n onChange={(e) =>\n dispatch({\n action: 'max_resolution_tier',\n value: e.currentTarget.value as UploadConfig['max_resolution_tier'],\n })\n }\n value={value}\n id={inputId}\n />\n <Text as=\"label\" htmlFor={inputId}>\n {label}\n </Text>\n </Flex>\n )\n })","config.max_resolution_tier","{value, label}","<FormField\n path={[]}\n title=\"Resolution Tier\"\n description={\n <>\n The maximum{' '}\n <a\n href=\"https://docs.mux.com/api-reference#video/operation/create-direct-upload\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n resolution_tier\n </a>{' '}\n your asset is encoded, stored, and streamed at.\n </>\n }\n >\n <Flex gap={3} wrap={'wrap'}>\n {RESOLUTION_TIERS.map(({value, label}, index) => {\n const inputId = `${id}--type-${value}`\n\n if (index > maxSupportedResolution) return null\n\n return (\n <Flex key={value} align=\"center\" gap={2}>\n <Radio\n checked={config.max_resolution_tier === value}\n name=\"asset-resolutiontier\"\n onChange={(e) =>\n dispatch({\n action: 'max_resolution_tier',\n value: e.currentTarget.value as UploadConfig['max_resolution_tier'],\n })\n }\n value={value}\n id={inputId}\n />\n <Text as=\"label\" htmlFor={inputId}>\n {label}\n </Text>\n </Flex>\n )\n })}\n </Flex>\n </FormField>","_c","_Fragment","{\n id,\n config,\n dispatch,\n}: {\n id: string\n config: UploadConfig\n dispatch: ActionDispatch<[action: UploadConfigurationStateAction]>\n}","(r) => r !== 'highest' && r !== 'audio-only'","(rendition: StaticRenditionResolution) => {\n const current = config.static_renditions\n const hasRendition = current.includes(rendition)\n\n if (hasRendition) {\n dispatch({\n action: 'static_renditions',\n value: current.filter((r) => r !== rendition),\n })\n } else {\n dispatch({\n action: 'static_renditions',\n value: [...current, rendition],\n })\n }\n }","static_renditions","r","(mode: 'standard' | 'advanced') => {\n setRenditionMode(mode)\n if (mode === 'standard') {\n // Remove specific resolutions, keep only highest and audio-only\n dispatch({\n action: 'static_renditions',\n value: config.static_renditions.filter((r) => r === 'highest' || r === 'audio-only'),\n })\n } else {\n // Remove highest, keep specific resolutions and audio-only\n dispatch({\n action: 'static_renditions',\n value: config.static_renditions.filter((r) => r !== 'highest'),\n })\n }\n }","(r) => r === 'highest' || r === 'audio-only'","(r) => r !== 'highest'","[]","() => handleModeChange('standard')","<Radio\n checked={renditionMode === 'standard'}\n name=\"rendition-mode\"\n onChange={() => handleModeChange('standard')}\n value=\"standard\"\n id={`${id}--mode-standard`}\n />","renditionMode === 'standard'","`${id}--mode-standard`","<Text as=\"label\" htmlFor={`${id}--mode-standard`}>\n Standard\n </Text>","<Flex align=\"center\" gap={2}>\n <Radio\n checked={renditionMode === 'standard'}\n name=\"rendition-mode\"\n onChange={() => handleModeChange('standard')}\n value=\"standard\"\n id={`${id}--mode-standard`}\n />\n <Text as=\"label\" htmlFor={`${id}--mode-standard`}>\n Standard\n </Text>\n </Flex>","() => handleModeChange('advanced')","<Radio\n checked={renditionMode === 'advanced'}\n name=\"rendition-mode\"\n onChange={() => handleModeChange('advanced')}\n value=\"advanced\"\n id={`${id}--mode-advanced`}\n />","renditionMode === 'advanced'","`${id}--mode-advanced`","<Text as=\"label\" htmlFor={`${id}--mode-advanced`}>\n Advanced\n </Text>","<Flex align=\"center\" gap={2}>\n <Radio\n checked={renditionMode === 'advanced'}\n name=\"rendition-mode\"\n onChange={() => handleModeChange('advanced')}\n value=\"advanced\"\n id={`${id}--mode-advanced`}\n />\n <Text as=\"label\" htmlFor={`${id}--mode-advanced`}>\n Advanced\n </Text>\n </Flex>","<Flex gap={3}>\n <Flex align=\"center\" gap={2}>\n <Radio\n checked={renditionMode === 'standard'}\n name=\"rendition-mode\"\n onChange={() => handleModeChange('standard')}\n value=\"standard\"\n id={`${id}--mode-standard`}\n />\n <Text as=\"label\" htmlFor={`${id}--mode-standard`}>\n Standard\n </Text>\n </Flex>\n <Flex align=\"center\" gap={2}>\n <Radio\n checked={renditionMode === 'advanced'}\n name=\"rendition-mode\"\n onChange={() => handleModeChange('advanced')}\n value=\"advanced\"\n id={`${id}--mode-advanced`}\n />\n <Text as=\"label\" htmlFor={`${id}--mode-advanced`}>\n Advanced\n </Text>\n </Flex>\n </Flex>","renditionMode === 'standard' && (\n <Stack gap={2}>\n <Flex align=\"center\" gap={2} padding={[0, 2]}>\n <Checkbox\n id={`${id}--highest`}\n style={{display: 'block'}}\n checked={config.static_renditions.includes('highest')}\n onChange={() => toggleRendition('highest')}\n />\n <Text as=\"label\" htmlFor={`${id}--highest`}>\n Highest Resolution (up to 4K)\n </Text>\n </Flex>\n <Flex align=\"center\" gap={2} padding={[0, 2]}>\n <Checkbox\n id={`${id}--audio-only-standard`}\n style={{display: 'block'}}\n checked={config.static_renditions.includes('audio-only')}\n onChange={() => toggleRendition('audio-only')}\n />\n <Text as=\"label\" htmlFor={`${id}--audio-only-standard`}>\n Audio Only (M4A)\n </Text>\n </Flex>\n </Stack>\n )","renditionMode === 'advanced' && (\n <Stack gap={2}>\n <Label size={1} muted>\n Select specific resolutions:\n </Label>\n <Flex gap={2} wrap=\"wrap\">\n {ADVANCED_RESOLUTIONS.map(({value, label}) => {\n const inputId = `${id}--resolution-${value}`\n return (\n <Flex key={value} align=\"center\" gap={2}>\n <Checkbox\n id={inputId}\n style={{display: 'block'}}\n checked={config.static_renditions.includes(value)}\n onChange={() => toggleRendition(value)}\n />\n <Text as=\"label\" htmlFor={inputId} size={1}>\n {label}\n </Text>\n </Flex>\n )\n })}\n </Flex>\n <Flex align=\"center\" gap={2} padding={[2, 2, 0, 2]}>\n <Checkbox\n id={`${id}--audio-only-advanced`}\n style={{display: 'block'}}\n checked={config.static_renditions.includes('audio-only')}\n onChange={() => toggleRendition('audio-only')}\n />\n <Text as=\"label\" htmlFor={`${id}--audio-only-advanced`}>\n Audio Only (M4A)\n </Text>\n </Flex>\n </Stack>\n )","{value, label}","<Stack gap={3}>\n <FormField\n path={[]}\n title=\"Static Renditions\"\n description=\"Generate downloadable MP4 or M4A files. Note: Mux will not upscale to produce MP4 renditions - renditions that would cause upscaling are skipped.\"\n >\n <Stack gap={3}>\n {/* Mode Selector */}\n <Flex gap={3}>\n <Flex align=\"center\" gap={2}>\n <Radio\n checked={renditionMode === 'standard'}\n name=\"rendition-mode\"\n onChange={() => handleModeChange('standard')}\n value=\"standard\"\n id={`${id}--mode-standard`}\n />\n <Text as=\"label\" htmlFor={`${id}--mode-standard`}>\n Standard\n </Text>\n </Flex>\n <Flex align=\"center\" gap={2}>\n <Radio\n checked={renditionMode === 'advanced'}\n name=\"rendition-mode\"\n onChange={() => handleModeChange('advanced')}\n value=\"advanced\"\n id={`${id}--mode-advanced`}\n />\n <Text as=\"label\" htmlFor={`${id}--mode-advanced`}>\n Advanced\n </Text>\n </Flex>\n </Flex>\n\n {/* Standard Mode Options */}\n {renditionMode === 'standard' && (\n <Stack gap={2}>\n <Flex align=\"center\" gap={2} padding={[0, 2]}>\n <Checkbox\n id={`${id}--highest`}\n style={{display: 'block'}}\n checked={config.static_renditions.includes('highest')}\n onChange={() => toggleRendition('highest')}\n />\n <Text as=\"label\" htmlFor={`${id}--highest`}>\n Highest Resolution (up to 4K)\n </Text>\n </Flex>\n <Flex align=\"center\" gap={2} padding={[0, 2]}>\n <Checkbox\n id={`${id}--audio-only-standard`}\n style={{display: 'block'}}\n checked={config.static_renditions.includes('audio-only')}\n onChange={() => toggleRendition('audio-only')}\n />\n <Text as=\"label\" htmlFor={`${id}--audio-only-standard`}>\n Audio Only (M4A)\n </Text>\n </Flex>\n </Stack>\n )}\n\n {/* Advanced Mode Options */}\n {renditionMode === 'advanced' && (\n <Stack gap={2}>\n <Label size={1} muted>\n Select specific resolutions:\n </Label>\n <Flex gap={2} wrap=\"wrap\">\n {ADVANCED_RESOLUTIONS.map(({value, label}) => {\n const inputId = `${id}--resolution-${value}`\n return (\n <Flex key={value} align=\"center\" gap={2}>\n <Checkbox\n id={inputId}\n style={{display: 'block'}}\n checked={config.static_renditions.includes(value)}\n onChange={() => toggleRendition(value)}\n />\n <Text as=\"label\" htmlFor={inputId} size={1}>\n {label}\n </Text>\n </Flex>\n )\n })}\n </Flex>\n <Flex align=\"center\" gap={2} padding={[2, 2, 0, 2]}>\n <Checkbox\n id={`${id}--audio-only-advanced`}\n style={{display: 'block'}}\n checked={config.static_renditions.includes('audio-only')}\n onChange={() => toggleRendition('audio-only')}\n />\n <Text as=\"label\" htmlFor={`${id}--audio-only-advanced`}>\n Audio Only (M4A)\n </Text>\n </Flex>\n </Stack>\n )}\n </Stack>\n </FormField>\n </Stack>","_c","{\n config,\n dispatch,\n stagedUpload,\n videoAssetMetadata,\n watermarkPreviewContainerRef,\n watermarkPreviewVideoRef,\n onValidationChange,\n}: {\n config: UploadConfig\n dispatch: (action: UploadConfigurationStateAction) => void\n stagedUpload: StagedUpload\n videoAssetMetadata: VideoAssetMetadata | null\n watermarkPreviewContainerRef: React.RefObject<HTMLDivElement | null>\n watermarkPreviewVideoRef: React.RefObject<HTMLVideoElement | null>\n onValidationChange: (error: string | null) => void\n}","[]","<>\n Add a watermark overlay to your video using Mux's native watermark support.{' '}\n <a\n href=\"https://www.mux.com/docs/guides/add-watermarks-to-your-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Learn more about Mux watermarks.\n </a>\n </>","config.watermark || {enabled: false}","watermark","(watermark) => {\n dispatch({action: 'watermark', value: watermark})\n }","<WatermarkControls\n watermark={config.watermark || {enabled: false}}\n onChange={(watermark) => {\n dispatch({action: 'watermark', value: watermark})\n }}\n onValidationChange={onValidationChange}\n previewContainerRef={watermarkPreviewContainerRef}\n previewVideoRef={watermarkPreviewVideoRef}\n />","config.watermark?.imageUrl &&\n stagedUpload.type === 'file' &&\n // Canvas preview is only shown in \"Canvas\" mode (no explicit overlay_settings)\n !config.watermark.overlay_settings && (\n <WatermarkPreview\n stagedUpload={stagedUpload}\n watermark={config.watermark}\n videoAspectRatio={videoAssetMetadata.aspectRatio}\n onWatermarkChange={(watermark) => {\n dispatch({action: 'watermark', value: watermark})\n }}\n previewContainerRef={watermarkPreviewContainerRef}\n videoRef={watermarkPreviewVideoRef}\n />\n )","stagedUpload.type","videoAssetMetadata.aspectRatio","<FormField\n path={[]}\n title=\"Watermark\"\n description={\n <>\n Add a watermark overlay to your video using Mux's native watermark support.{' '}\n <a\n href=\"https://www.mux.com/docs/guides/add-watermarks-to-your-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Learn more about Mux watermarks.\n </a>\n </>\n }\n >\n <Stack gap={3}>\n <WatermarkControls\n watermark={config.watermark || {enabled: false}}\n onChange={(watermark) => {\n dispatch({action: 'watermark', value: watermark})\n }}\n onValidationChange={onValidationChange}\n previewContainerRef={watermarkPreviewContainerRef}\n previewVideoRef={watermarkPreviewVideoRef}\n />\n {config.watermark?.imageUrl &&\n stagedUpload.type === 'file' &&\n // Canvas preview is only shown in \"Canvas\" mode (no explicit overlay_settings)\n !config.watermark.overlay_settings && (\n <WatermarkPreview\n stagedUpload={stagedUpload}\n watermark={config.watermark}\n videoAspectRatio={videoAssetMetadata.aspectRatio}\n onWatermarkChange={(watermark) => {\n dispatch({action: 'watermark', value: watermark})\n }}\n previewContainerRef={watermarkPreviewContainerRef}\n videoRef={watermarkPreviewVideoRef}\n />\n )}\n </Stack>\n </FormField>","{\n stagedUpload,\n watermark,\n onWatermarkChange,\n videoAspectRatio,\n previewContainerRef,\n videoRef,\n}: {\n stagedUpload: StagedUpload\n watermark: WatermarkConfig\n onWatermarkChange: (watermark: WatermarkConfig) => void\n videoAspectRatio?: number | null\n previewContainerRef: React.RefObject<HTMLDivElement | null>\n videoRef: React.RefObject<HTMLVideoElement | null>\n}","() => {\n if (videoRef.current && stagedUpload.type === 'file') {\n const file = stagedUpload.files[0]\n const url = URL.createObjectURL(file!)\n videoRef.current.src = url\n\n return () => {\n URL.revokeObjectURL(url)\n }\n }\n return undefined\n }","[stagedUpload, videoRef]","videoRef.current","{\n overflow: 'hidden',\n // For vertical videos, center the preview and limit its width\n display: 'flex',\n justifyContent: 'center',\n }","isVertical ? {height: '400px', maxHeight: '50vh'} : {minHeight: '200px'}","{\n position: 'relative',\n // For vertical videos: limit width so the preview doesn't get too tall\n // For horizontal videos: use full width\n width: isVertical ? 'auto' : '100%',\n aspectRatio: videoAspectRatio ? String(videoAspectRatio) : '16/9',\n ...(isVertical ? {height: '400px', maxHeight: '50vh'} : {minHeight: '200px'}),\n overflow: 'hidden',\n }","isVertical ? 'auto' : '100%'","videoAspectRatio ? String(videoAspectRatio) : '16/9'","{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n objectFit: 'fill',\n display: 'block',\n }","<video\n ref={videoRef}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n objectFit: 'fill',\n display: 'block',\n }}\n />","<DraggableWatermark\n watermark={watermark}\n onChange={onWatermarkChange}\n containerRef={previewContainerRef as React.RefObject<HTMLDivElement>}\n videoElementRef={videoRef as React.RefObject<HTMLVideoElement>}\n />","previewContainerRef as React.RefObject<HTMLDivElement>","videoRef as React.RefObject<HTMLVideoElement>","<Card\n tone=\"transparent\"\n border\n style={{\n overflow: 'hidden',\n // For vertical videos, center the preview and limit its width\n display: 'flex',\n justifyContent: 'center',\n }}\n >\n {/* Inner container that exactly matches the video aspect ratio - no padding, no letterbox */}\n <div\n ref={previewContainerRef}\n style={{\n position: 'relative',\n // For vertical videos: limit width so the preview doesn't get too tall\n // For horizontal videos: use full width\n width: isVertical ? 'auto' : '100%',\n aspectRatio: videoAspectRatio ? String(videoAspectRatio) : '16/9',\n ...(isVertical ? {height: '400px', maxHeight: '50vh'} : {minHeight: '200px'}),\n overflow: 'hidden',\n }}\n >\n <video\n ref={videoRef}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n objectFit: 'fill',\n display: 'block',\n }}\n />\n <DraggableWatermark\n watermark={watermark}\n onChange={onWatermarkChange}\n containerRef={previewContainerRef as React.RefObject<HTMLDivElement>}\n videoElementRef={videoRef as React.RefObject<HTMLVideoElement>}\n />\n </div>\n </Card>","_Fragment","_c","{\n children,\n tone,\n onPaste,\n onDrop,\n onDragEnter,\n onDragLeave,\n onDragOver,\n ref,\n}: UploadCardProps & {ref?: React.Ref<HTMLDivElement>}","(event) => {\n const target = event.target as HTMLElement\n\n // Don't steal focus when pasting into the VTT input\n if (target.closest('#vtt-url')) {\n return\n }\n\n if ((event.ctrlKey || event.metaKey) && event.key === 'v') {\n inputRef.current!.focus()\n }\n }","useCallback<React.KeyboardEventHandler<HTMLDivElement>>((event) => {\n const target = event.target as HTMLElement\n\n // Don't steal focus when pasting into the VTT input\n if (target.closest('#vtt-url')) {\n return\n }\n\n if ((event.ctrlKey || event.metaKey) && event.key === 'v') {\n inputRef.current!.focus()\n }\n }, [])","<HiddenInput ref={inputRef} />","<UploadCardWithFocusRing\n tone={tone}\n ref={ref}\n padding={0}\n radius={2}\n shadow={0}\n tabIndex={0}\n onKeyDown={handleKeyDown}\n onPaste={onPaste}\n onDrop={onDrop}\n onDragEnter={onDragEnter}\n onDragLeave={onDragLeave}\n onDragOver={onDragOver}\n >\n <HiddenInput ref={inputRef} />\n {children}\n </UploadCardWithFocusRing>","_c","HiddenInput","{onSelect, accept, ...props}: FileInputButtonProps","(event) => {\n if (onSelect) {\n onSelect(event.target.files!)\n }\n }","useCallback<React.ChangeEventHandler<HTMLInputElement>>(\n (event) => {\n if (onSelect) {\n onSelect(event.target.files!)\n }\n },\n [onSelect],\n )","() => inputRef.current?.click()","useCallback(() => inputRef.current?.click(), [])","<HiddenInput\n accept={accept}\n ref={inputRef}\n tabIndex={0}\n type=\"file\"\n id={inputId}\n onChange={handleSelect}\n value=\"\"\n />","{width: '100%'}","<Button\n onClick={handleButtonClick}\n mode=\"default\"\n tone=\"primary\"\n style={{width: '100%'}}\n {...props}\n />","<Label htmlFor={inputId}>\n <HiddenInput\n accept={accept}\n ref={inputRef}\n tabIndex={0}\n type=\"file\"\n id={inputId}\n onChange={handleSelect}\n value=\"\"\n />\n <Button\n onClick={handleButtonClick}\n mode=\"default\"\n tone=\"primary\"\n style={{width: '100%'}}\n {...props}\n />\n </Label>","Label","_c","() => setDialogState('select-video')","useCallback(() => setDialogState('select-video'), [setDialogState])","() => setDialogState('secrets')","useCallback(() => setDialogState('secrets'), [setDialogState])","hovering ? {borderColor: 'transparent'} : undefined","['column', 'column', 'row']","<Flex justify=\"center\">\n <Text muted>\n <DocumentVideoIcon />\n </Text>\n </Flex>","formatAcceptString(accept)","<Flex align=\"center\" justify=\"flex-start\" gap={2} flex={1}>\n <Flex justify=\"center\">\n <Text muted>\n <DocumentVideoIcon />\n </Text>\n </Flex>\n <Flex justify=\"center\">\n <Text size={1} muted>\n Drag {formatAcceptString(accept)} file or paste URL here\n </Text>\n </Flex>\n </Flex>","<FileInputButton\n accept={accept}\n mode=\"bleed\"\n tone=\"default\"\n icon={UploadIcon}\n text=\"Upload\"\n onSelect={onSelect}\n />","<Button mode=\"bleed\" icon={SearchIcon} text=\"Select\" onClick={handleBrowse} />","hasConfigAccess && (\n <Button\n padding={3}\n radius={3}\n tone={needsSetup ? 'critical' : undefined}\n onClick={handleConfigureApi}\n icon={PlugIcon}\n mode=\"bleed\"\n title=\"Configure plugin credentials\"\n />\n )","<Inline gap={2}>\n <FileInputButton\n accept={accept}\n mode=\"bleed\"\n tone=\"default\"\n icon={UploadIcon}\n text=\"Upload\"\n onSelect={onSelect}\n />\n <Button mode=\"bleed\" icon={SearchIcon} text=\"Select\" onClick={handleBrowse} />\n\n {hasConfigAccess && (\n <Button\n padding={3}\n radius={3}\n tone={needsSetup ? 'critical' : undefined}\n onClick={handleConfigureApi}\n icon={PlugIcon}\n mode=\"bleed\"\n title=\"Configure plugin credentials\"\n />\n )}\n </Inline>","<Flex\n align=\"center\"\n justify=\"space-between\"\n gap={4}\n direction={['column', 'column', 'row']}\n paddingY={2}\n sizing=\"border\"\n >\n <Flex align=\"center\" justify=\"flex-start\" gap={2} flex={1}>\n <Flex justify=\"center\">\n <Text muted>\n <DocumentVideoIcon />\n </Text>\n </Flex>\n <Flex justify=\"center\">\n <Text size={1} muted>\n Drag {formatAcceptString(accept)} file or paste URL here\n </Text>\n </Flex>\n </Flex>\n <Inline gap={2}>\n <FileInputButton\n accept={accept}\n mode=\"bleed\"\n tone=\"default\"\n icon={UploadIcon}\n text=\"Upload\"\n onSelect={onSelect}\n />\n <Button mode=\"bleed\" icon={SearchIcon} text=\"Select\" onClick={handleBrowse} />\n\n {hasConfigAccess && (\n <Button\n padding={3}\n radius={3}\n tone={needsSetup ? 'critical' : undefined}\n onClick={handleConfigureApi}\n icon={PlugIcon}\n mode=\"bleed\"\n title=\"Configure plugin credentials\"\n />\n )}\n </Inline>\n </Flex>","<Card\n sizing=\"border\"\n tone={readOnly ? 'transparent' : 'inherit'}\n border\n radius={2}\n paddingX={3}\n paddingY={1}\n style={hovering ? {borderColor: 'transparent'} : undefined}\n >\n <Flex\n align=\"center\"\n justify=\"space-between\"\n gap={4}\n direction={['column', 'column', 'row']}\n paddingY={2}\n sizing=\"border\"\n >\n <Flex align=\"center\" justify=\"flex-start\" gap={2} flex={1}>\n <Flex justify=\"center\">\n <Text muted>\n <DocumentVideoIcon />\n </Text>\n </Flex>\n <Flex justify=\"center\">\n <Text size={1} muted>\n Drag {formatAcceptString(accept)} file or paste URL here\n </Text>\n </Flex>\n </Flex>\n <Inline gap={2}>\n <FileInputButton\n accept={accept}\n mode=\"bleed\"\n tone=\"default\"\n icon={UploadIcon}\n text=\"Upload\"\n onSelect={onSelect}\n />\n <Button mode=\"bleed\" icon={SearchIcon} text=\"Select\" onClick={handleBrowse} />\n\n {hasConfigAccess && (\n <Button\n padding={3}\n radius={3}\n tone={needsSetup ? 'critical' : undefined}\n onClick={handleConfigureApi}\n icon={PlugIcon}\n mode=\"bleed\"\n title=\"Configure plugin credentials\"\n />\n )}\n </Inline>\n </Flex>\n </Card>","readOnly ? 'transparent' : 'inherit'","_c","_Fragment","PlayerActionsMenu","<InputFallback />","<Suspense fallback={<InputFallback />}>\n {isLoading ? (\n <InputFallback />\n ) : (\n <>\n {secretDocumentValues.value.needsSetup && !assetDocumentValues.value ? (\n <Onboard setDialogState={setDialogState} config={props.config} />\n ) : (\n <Uploader\n {...props}\n config={props.config}\n onChange={props.onChange}\n client={client}\n secrets={secretDocumentValues.value.secrets}\n asset={assetDocumentValues.value}\n dialogState={dialogState}\n setDialogState={setDialogState}\n needsSetup={secretDocumentValues.value.needsSetup}\n />\n )}\n\n {dialogState === 'secrets' && hasConfigAccess && (\n <ConfigureApiDialog\n setDialogState={setDialogState}\n secrets={secretDocumentValues.value.secrets}\n />\n )}\n </>\n )}\n </Suspense>","assetDocumentValues.value","props.config","value","<Card>\n <ErrorBoundaryCard schemaType={props.schemaType}>\n <Suspense fallback={<InputFallback />}>\n {isLoading ? (\n <InputFallback />\n ) : (\n <>\n {secretDocumentValues.value.needsSetup && !assetDocumentValues.value ? (\n <Onboard setDialogState={setDialogState} config={props.config} />\n ) : (\n <Uploader\n {...props}\n config={props.config}\n onChange={props.onChange}\n client={client}\n secrets={secretDocumentValues.value.secrets}\n asset={assetDocumentValues.value}\n dialogState={dialogState}\n setDialogState={setDialogState}\n needsSetup={secretDocumentValues.value.needsSetup}\n />\n )}\n\n {dialogState === 'secrets' && hasConfigAccess && (\n <ConfigureApiDialog\n setDialogState={setDialogState}\n secrets={secretDocumentValues.value.secrets}\n />\n )}\n </>\n )}\n </Suspense>\n </ErrorBoundaryCard>\n </Card>","schemaType","_c","useClient","_Fragment","ErrorBoundaryCard","Input","\"title\"","\"horizontal_margin\"","\"vertical_margin\"","\"width\"","\"filename\""],"sources":["../src/context/MuxApiHostContext.tsx","../src/components/icons/ToolIcon.tsx","../src/context/DrmPlaybackWarningContext.tsx","../src/util/muxAddonClient.ts","../src/hooks/useClient.ts","../src/util/createSearchFilter.ts","../src/hooks/useAssets.ts","../src/hooks/useDialogState.ts","../src/constants.ts","../src/util/pluginVersion.ts","../src/actions/secrets.ts","../src/hooks/useSaveSecrets.ts","../src/util/constants.ts","../src/hooks/useSecretsDocumentValues.ts","../src/hooks/useSecretsFormState.ts","../src/util/readSecrets.ts","../src/components/MuxLogo.tsx","../src/components/ConfigureApi.styled.tsx","../src/components/FormField.tsx","../src/components/ConfigureApi.tsx","../src/util/assetTitlePlaceholder.ts","../src/util/parsers.ts","../src/actions/assets.ts","../src/hooks/useMuxAssets.ts","../src/hooks/useImportMuxAssets.ts","../src/hooks/useInView.ts","../src/util/getPlaybackPolicy.ts","../src/util/generateJwt.ts","../src/util/createUrlParamsObject.ts","../src/util/getAnimatedPosterSrc.ts","../src/util/getPosterSrc.ts","../src/util/tryWithSuspend.ts","../src/components/VideoThumbnail.tsx","../src/components/ImportVideosFromMux.tsx","../src/components/PageSelector.tsx","../src/util/addKeysToMuxData.ts","../src/hooks/useResyncMuxMetadata.ts","../src/components/ResyncMetadata.tsx","../src/components/SelectSortOptions.tsx","../src/components/SpinnerBox.tsx","../src/components/IconInfo.tsx","../src/components/icons/Resolution.tsx","../src/components/icons/StopWatch.tsx","../src/hooks/useMezzanine.ts","../src/components/MezzanineExplanation.tsx","../src/components/Mezzanine.tsx","../src/hooks/useResyncAsset.ts","../src/util/textTracks.ts","../src/util/types.ts","../src/components/AddCaptionDialog.tsx","../src/components/EditCaptionDialog.tsx","../src/components/TextTracksManager.tsx","../src/context/DialogStateContext.tsx","../src/util/getVideoSrc.ts","../src/components/CaptionsDialog.tsx","../src/util/formatSeconds.ts","../src/components/EditThumbnailDialog.tsx","../src/components/icons/Audio.tsx","../src/components/MezzanineDialog.tsx","../src/components/VideoPlayer.tsx","../src/components/documentPreview/MissingSchemaType.tsx","../src/components/documentPreview/TimeAgo.tsx","../src/components/documentPreview/DraftStatus.tsx","../src/components/documentPreview/PublishedStatus.tsx","../src/components/documentPreview/PaneItemPreview.tsx","../src/components/documentPreview/DocumentPreview.tsx","../src/components/VideoDetails/VideoReferences.tsx","../src/components/VideoDetails/DeleteDialog.tsx","../src/hooks/useDocReferences.ts","../src/util/getVideoMetadata.ts","../src/components/VideoDetails/useVideoDetails.ts","../src/components/VideoDetails/VideoDetails.tsx","../src/components/VideoMetadata.tsx","../src/components/VideoInBrowser.tsx","../src/components/VideosBrowser.tsx","../src/components/StudioTool.tsx","../src/hooks/useAccessControl.ts","../src/hooks/useAssetDocumentValues.ts","../src/hooks/useMuxPolling.ts","../src/components/ErrorBoundaryCard.tsx","../src/components/Input.styled.tsx","../src/components/Onboard.tsx","../src/clients/upChunkObservable.ts","../src/util/formatDriveShareLink.ts","../src/util/roundPxString.ts","../src/actions/upload.ts","../src/util/asserters.ts","../src/util/extractFiles.ts","../src/components/SelectAsset.tsx","../src/components/InputBrowser.tsx","../src/hooks/useCancelUpload.ts","../src/components/Player.styled.tsx","../src/components/UploadProgress.tsx","../src/components/Player.tsx","../src/components/withFocusRing/helpers.ts","../src/components/FileInputMenuItem.styled.tsx","../src/components/FileInputMenuItem.tsx","../src/components/PlayerActionsMenu.tsx","../src/hooks/useFetchFileSize.ts","../src/hooks/useMediaMetadata.ts","../src/util/convertWatermarkToMux.ts","../src/util/formatBytes.ts","../src/components/DraggableWatermark.tsx","../src/components/TextTracksEditor.tsx","../src/components/uploadConfiguration/PlaybackPolicyOption.tsx","../src/components/uploadConfiguration/PlaybackPolicyWarning.tsx","../src/components/uploadConfiguration/PlaybackPolicy.tsx","../src/components/uploadConfiguration/ResolutionTierSelector.tsx","../src/components/uploadConfiguration/StaticRenditionSelector.tsx","../src/components/UploadConfiguration.tsx","../src/components/withFocusRing/withFocusRing.ts","../src/components/Uploader.styled.tsx","../src/components/FileInputButton.tsx","../src/components/UploadPlaceholder.tsx","../src/components/Uploader.tsx","../src/components/Input.tsx","../src/plugin.tsx","../src/schema.ts","../src/_exports/index.ts"],"sourcesContent":["import {createContext, useContext} from 'react'\n\nconst MuxApiHostContext = createContext<string | undefined>(undefined)\n\nexport function MuxApiHostProvider({\n muxApiHost,\n children,\n}: {\n muxApiHost: string | undefined\n children: React.ReactNode\n}) {\n return <MuxApiHostContext.Provider value={muxApiHost}>{children}</MuxApiHostContext.Provider>\n}\n\nexport function useMuxApiHost() {\n return useContext(MuxApiHostContext)\n}\n","/**\n * Icon of a monitor with a play button.\n * Credits: material design icons & react-icons\n */\nconst ToolIcon = () => (\n <svg\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 24 24\"\n height=\"1em\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M21 3H3c-1.11 0-2 .89-2 2v12c0 1.1.89 2 2 2h5v2h8v-2h5c1.1 0 1.99-.9 1.99-2L23 5c0-1.11-.9-2-2-2zm0 14H3V5h18v12zm-5-6l-7 4V7z\" />\n </svg>\n)\n\nexport default ToolIcon\n","import {Button, Card, Dialog, Stack, Text} from '@sanity/ui'\nimport {createContext, useCallback, useContext, useMemo, useState} from 'react'\n\nimport {type PluginConfig} from '../util/types'\n\nconst LOCAL_STORAGE_HAS_SHOWN_WARNING_KEY = 'mux-plugin-has-shown-drm-playback-warning'\n\ntype DrmPlaybackWarningContextContextProps = {\n hasShownWarning: boolean\n setHasWarnedAboutDrmPlayback: (b: boolean) => void\n}\n\nconst DrmPlaybackWarningContext = createContext<DrmPlaybackWarningContextContextProps>({\n hasShownWarning: false,\n setHasWarnedAboutDrmPlayback: () => {\n return null\n },\n})\n\ninterface DrmPlaybackWarningContextProviderProps {\n config?: PluginConfig\n children: React.ReactNode\n}\n\nexport const DrmPlaybackWarningContextProvider = ({\n config,\n children,\n}: DrmPlaybackWarningContextProviderProps) => {\n const warningDisabled = config?.disableDrmPlaybackWarning ?? false\n const hasWarned: boolean =\n warningDisabled || window.localStorage.getItem(LOCAL_STORAGE_HAS_SHOWN_WARNING_KEY) === 'true'\n const [hasWarnedAboutDrmPlayback, setHasWarnedAboutDrmPlayback] = useState(hasWarned)\n\n const setHasShownWarning = useCallback((b: boolean) => {\n window.localStorage.setItem(LOCAL_STORAGE_HAS_SHOWN_WARNING_KEY, b.toString())\n setHasWarnedAboutDrmPlayback(b)\n }, [])\n\n const value = useMemo(\n () => ({\n hasShownWarning: hasWarnedAboutDrmPlayback,\n setHasWarnedAboutDrmPlayback: setHasShownWarning,\n }),\n [hasWarnedAboutDrmPlayback, setHasShownWarning],\n )\n\n return (\n <DrmPlaybackWarningContext.Provider value={value}>\n {children}\n </DrmPlaybackWarningContext.Provider>\n )\n}\n\nexport const useDrmPlaybackWarningContext = () => {\n const context = useContext(DrmPlaybackWarningContext)\n return context\n}\n\nexport const DRMWarningDialog = ({onClose}: {onClose: () => void}) => {\n const {setHasWarnedAboutDrmPlayback} = useDrmPlaybackWarningContext()\n const _onClose = () => {\n setHasWarnedAboutDrmPlayback(true)\n onClose()\n }\n return (\n <Dialog\n open\n id=\"drm-playback-warn\"\n onClose={_onClose}\n header=\"DRM Playback Warning\"\n footer={\n <Stack padding={3}>\n <Button mode=\"ghost\" tone=\"primary\" onClick={_onClose} text=\"Ok\" />\n </Stack>\n }\n >\n <Stack gap={3} padding={3}>\n <Card padding={[3, 3, 3]} radius={2}>\n <Stack gap={3}>\n <Text size={1} weight=\"semibold\">\n DRM-protected playback will generate a license with a small associated cost. The\n plugin will attempt to play signed or public playback IDs instead whenever possible.\n </Text>\n </Stack>\n </Card>\n <Card padding={[3, 3, 3]} radius={2} tone=\"suggest\">\n <Stack gap={3}>\n <Text size={1} weight=\"semibold\">\n This is a one time warning. If it persists, you can disable it from your plugin\n configuration.\n </Text>\n </Stack>\n </Card>\n </Stack>\n </Dialog>\n )\n}\n","import type {SanityClient} from 'sanity'\n\n/**\n * Maps a Studio client handed out by the plugin's `useClient` hook to the client that\n * sends Mux addon (`/addons/mux/...`) requests. Only populated when `muxApiHost` is set.\n */\nconst muxAddonClients = new WeakMap<SanityClient, SanityClient>()\n\n/**\n * Validates `muxApiHost` and strips trailing slashes, so it can be used as `apiHost`.\n * Throws if it is not an absolute `http(s)` URL without a path, query or hash.\n */\nexport function normalizeMuxApiHost(muxApiHost: string): string {\n let url: URL\n try {\n url = new URL(muxApiHost)\n } catch {\n throw new Error(\n `[sanity-plugin-mux-input] \\`muxApiHost\\` must be an absolute URL, like \"http://127.0.0.1:8080\". Got: \"${muxApiHost}\"`,\n )\n }\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n throw new Error(\n `[sanity-plugin-mux-input] \\`muxApiHost\\` must use http or https. Got: \"${muxApiHost}\"`,\n )\n }\n if ((url.pathname && url.pathname !== '/') || url.search || url.hash) {\n throw new Error(\n `[sanity-plugin-mux-input] \\`muxApiHost\\` must not have a path, query or hash. The plugin adds \"/v<apiVersion>/addons/mux/...\". Got: \"${muxApiHost}\"`,\n )\n }\n return url.origin\n}\n\n/**\n * Creates the client for Mux addon requests from a Studio client.\n *\n * The host is used as-is: no project id is prepended (`useProjectHostname: false`).\n * `@sanity/client` then sends the project id in a request header.\n * Auth config (`token`, `withCredentials`) is copied from the Studio client.\n */\nfunction createMuxAddonClient(client: SanityClient, muxApiHost: string): SanityClient {\n return client.withConfig({\n apiHost: normalizeMuxApiHost(muxApiHost),\n // oxlint-disable-next-line no-deprecated -- only way to keep the project id out of the hostname\n useProjectHostname: false,\n useCdn: false,\n })\n}\n\n/**\n * Returns a copy of the Studio client that is linked to a Mux addon client on `muxApiHost`.\n * Content Lake requests on the returned client still use the Studio API host.\n */\nexport function withMuxApiHost(client: SanityClient, muxApiHost: string): SanityClient {\n const studioClient = client.withConfig({})\n muxAddonClients.set(studioClient, createMuxAddonClient(client, muxApiHost))\n return studioClient\n}\n\n/**\n * Returns the client to use for Mux addon requests.\n * Without a `muxApiHost` override, this is the same client that was passed in.\n */\nexport function getMuxAddonClient(client: SanityClient): SanityClient {\n return muxAddonClients.get(client) ?? client\n}\n","// As it's required to specify the API Version this custom hook ensures it's all using the same version\nimport {useMemo} from 'react'\nimport {useClient as useSanityClient} from 'sanity'\n\nimport {useMuxApiHost} from '../context/MuxApiHostContext'\nimport {withMuxApiHost} from '../util/muxAddonClient'\n\nexport const SANITY_API_VERSION = '2024-03-05'\n\nexport function useClient() {\n const client = useSanityClient({apiVersion: SANITY_API_VERSION})\n const muxApiHost = useMuxApiHost()\n // Without `muxApiHost`, return the Studio client unchanged.\n // With it, Mux addon requests made via `getMuxAddonClient(client)` go to that host.\n return useMemo(\n () => (muxApiHost ? withMuxApiHost(client, muxApiHost) : client),\n [client, muxApiHost],\n )\n}\n","// Adaptation of Sanity's createSearchQuery for our limited use case:\n// https://github.com/sanity-io/sanity/blob/next/packages/sanity/src/core/search/weighted/createSearchQuery.ts\nimport {compact, toLower, trim, uniq, words} from 'lodash'\n\nconst SPECIAL_CHARS = /([^!@#$%^&*(),\\\\/?\";:{}|[\\]+<>\\s-])+/g\nconst STRIP_EDGE_CHARS = /(^[.]+)|([.]+$)/\n\nfunction tokenize(string: string): string[] {\n return (string.match(SPECIAL_CHARS) || []).map((token) => token.replace(STRIP_EDGE_CHARS, ''))\n}\n\nfunction toGroqParams(terms: string[]): Record<string, string> {\n const params: Record<string, string> = {}\n return terms.reduce((acc, term, i) => {\n acc[`t${i}`] = `*${term}*` // \"t\" is short for term\n return acc\n }, params)\n}\n\n/**\n * Convert a string into an array of tokenized terms.\n *\n * Any (multi word) text wrapped in double quotes will be treated as \"phrases\", or separate tokens that\n * will not have its special characters removed.\n * E.g.`\"the\" \"fantastic mr\" fox fox book` =\\> [\"the\", `\"fantastic mr\"`, \"fox\", \"book\"]\n *\n * Phrases wrapped in quotes are assigned relevance scoring differently from regular words.\n *\n * @internal\n */\nfunction extractTermsFromQuery(query: string): string[] {\n const quotedQueries = [] as string[]\n const unquotedQuery = query.replace(/(\"[^\"]*\")/g, (match) => {\n if (words(match).length > 1) {\n quotedQueries.push(match)\n return ''\n }\n return match\n })\n\n // Lowercase and trim quoted queries\n const quotedTerms = quotedQueries.map((str) => trim(toLower(str)))\n\n /**\n * Convert (remaining) search query into an array of deduped, sanitized tokens.\n * All white space and special characters are removed.\n * e.g. \"The saint of Saint-Germain-des-Prés\" =\\> ['the', 'saint', 'of', 'germain', 'des', 'pres']\n */\n const remainingTerms = uniq(compact(tokenize(toLower(unquotedQuery))))\n\n return [...quotedTerms, ...remainingTerms]\n}\n\n/**\n * Create GROQ constraints, given search terms and the full spec of available document types and fields.\n * Essentially a large list of all possible fields (joined by logical OR) to match our search terms against.\n */\nfunction createConstraints(terms: string[], includeAssetId: boolean) {\n const searchPaths = includeAssetId ? ['filename', 'assetId'] : ['filename']\n const constraints = terms\n .map((_term, i) => searchPaths.map((joinedPath) => `${joinedPath} match $t${i}`))\n .filter((constraint) => constraint.length > 0)\n\n return constraints.map((constraint) => `(${constraint.join(' || ')})`)\n}\n\nexport function createSearchFilter(query: string) {\n const terms = extractTermsFromQuery(query)\n\n return {\n filter: createConstraints(terms, query.length >= 8), // if the search is big enough, include the assetId (mux id) in the results\n params: {\n ...toGroqParams(terms),\n },\n }\n}\n","import {useMemo, useState} from 'react'\nimport {\n collate,\n createHookFromObservableFactory,\n type DocumentStore,\n useDocumentStore,\n} from 'sanity'\n\nimport {SANITY_API_VERSION} from '../hooks/useClient'\nimport {createSearchFilter} from '../util/createSearchFilter'\nimport type {VideoAssetDocument} from '../util/types'\n\nexport const ASSET_SORT_OPTIONS = {\n createdDesc: {groq: '_createdAt desc', label: 'Newest first'},\n createdAsc: {groq: '_createdAt asc', label: 'First created (oldest)'},\n filenameAsc: {groq: 'filename asc', label: 'By filename (A-Z)'},\n filenameDesc: {groq: 'filename desc', label: 'By filename (Z-A)'},\n}\n\nexport type SortOption = keyof typeof ASSET_SORT_OPTIONS\n\nconst useAssetDocuments = createHookFromObservableFactory<\n VideoAssetDocument[],\n {\n documentStore: DocumentStore\n sort: SortOption\n searchQuery: string\n }\n>(({documentStore, sort, searchQuery}) => {\n const search = createSearchFilter(searchQuery)\n const filter = [`_type == \"mux.videoAsset\"`, ...search.filter].filter(Boolean).join(' && ')\n\n const sortFragment = ASSET_SORT_OPTIONS[sort].groq\n return documentStore.listenQuery(\n /* groq */ `*[${filter}] | order(${sortFragment})`,\n search.params,\n {\n apiVersion: SANITY_API_VERSION,\n },\n )\n})\n\nexport default function useAssets() {\n const documentStore = useDocumentStore()\n const [sort, setSort] = useState<SortOption>('createdDesc')\n const [searchQuery, setSearchQuery] = useState('')\n\n const [assetDocuments = [], isLoading] = useAssetDocuments(\n useMemo(() => ({documentStore, sort, searchQuery}), [documentStore, sort, searchQuery]),\n )\n\n const assets = useMemo(\n () =>\n // Avoid displaying both drafts & published assets by collating them together and giving preference to drafts\n collate<VideoAssetDocument>(assetDocuments).map(\n (collated) =>\n ({\n ...(collated.draft || collated.published),\n _id: collated.id,\n }) as VideoAssetDocument,\n ),\n [assetDocuments],\n )\n\n return {\n assets,\n isLoading,\n sort,\n searchQuery,\n setSort,\n setSearchQuery,\n }\n}\n","// Handy little state machine to simplify managing which root level dialog to open\n\nimport {useState} from 'react'\n\nexport type DialogState =\n | 'secrets'\n | 'mezzanine'\n | 'select-video'\n | 'edit-thumbnail'\n | 'edit-captions'\n | false\n\nexport function useDialogState() {\n return useState<DialogState>(false)\n}\n\nexport type SetDialogState = ReturnType<typeof useDialogState>[1]\n","declare global {\n var __PKG_VERSION__: string | undefined\n}\nexport const PLUGIN_VERSION = typeof __PKG_VERSION__ === 'string' ? __PKG_VERSION__ : '0.0.0-dev'\n","import {PLUGIN_VERSION} from '../constants'\n\nexport const PLUGIN_VERSION_QUERY = {\n sanityVersion: PLUGIN_VERSION,\n}\n","import {defer} from 'rxjs'\nimport type {SanityClient} from 'sanity'\n\nimport {getMuxAddonClient} from '../util/muxAddonClient'\nimport {PLUGIN_VERSION_QUERY} from '../util/pluginVersion'\n\ninterface SecretsDocument {\n _id: 'secrets.mux'\n _type: 'mux.apiKey'\n token: string\n secretKey: string\n enableSignedUrls: boolean\n signingKeyId: string\n signingKeyPrivate: string\n drmConfigId: string\n}\nexport function saveSecrets(\n client: SanityClient,\n token: string,\n secretKey: string,\n enableSignedUrls: boolean,\n signingKeyId: string,\n signingKeyPrivate: string,\n drmConfigId: string,\n): Promise<SecretsDocument> {\n const doc: SecretsDocument = {\n _id: 'secrets.mux',\n _type: 'mux.apiKey',\n token,\n secretKey,\n enableSignedUrls,\n signingKeyId,\n signingKeyPrivate,\n drmConfigId,\n }\n doc.signingKeyId = enableSignedUrls ? signingKeyId : ''\n doc.signingKeyPrivate = enableSignedUrls ? signingKeyPrivate : ''\n\n return client.createOrReplace(doc)\n}\n\nexport async function createSigningKeys(client: SanityClient) {\n try {\n const {dataset} = client.config()\n const res = await getMuxAddonClient(client).request<{\n data: {private_key: string; id: string; created_at: string}\n }>({\n url: `/addons/mux/signing-keys/${dataset}`,\n withCredentials: true,\n method: 'POST',\n query: PLUGIN_VERSION_QUERY,\n })\n return res\n } catch (error: any) {\n console.error('Error creating signing keys', error)\n const message =\n error.response?.statusCode === 401\n ? 'Unauthorized - Failed to create the Signing Key. Please ensure that the token has \"System\" permissions'\n : error.message\n throw new Error(message, {cause: error})\n }\n}\n\nexport function testSecrets(client: SanityClient) {\n const {dataset} = client.config()\n return getMuxAddonClient(client).request<{status: boolean}>({\n url: `/addons/mux/secrets/${dataset}/test`,\n withCredentials: true,\n method: 'GET',\n query: PLUGIN_VERSION_QUERY,\n })\n}\n\nexport async function haveValidSigningKeys(\n client: SanityClient,\n signingKeyId: string,\n signingKeyPrivate: string,\n) {\n if (!(signingKeyId && signingKeyPrivate)) {\n return false\n }\n\n const {dataset} = client.config()\n try {\n const res = await getMuxAddonClient(client).request<{data: {id: string; created_at: string}}>({\n url: `/addons/mux/signing-keys/${dataset}/${signingKeyId}`,\n withCredentials: true,\n method: 'GET',\n query: PLUGIN_VERSION_QUERY,\n })\n //\n // if this signing key is valid it will return { data: { id: 'xxxx' } }\n //\n return !!(res.data && res.data.id)\n } catch (e) {\n console.error('Error fetching signingKeyId', signingKeyId, 'assuming it is not valid', e)\n return false\n }\n}\n\nexport function testSecretsObservable(client: SanityClient) {\n const {dataset} = client.config()\n return defer(() =>\n getMuxAddonClient(client).observable.request<{status: boolean}>({\n url: `/addons/mux/secrets/${dataset}/test`,\n withCredentials: true,\n method: 'GET',\n query: PLUGIN_VERSION_QUERY,\n }),\n )\n}\n","import {useCallback} from 'react'\nimport type {SanityClient} from 'sanity'\n\nimport {createSigningKeys, haveValidSigningKeys, saveSecrets, testSecrets} from '../actions/secrets'\nimport type {Secrets} from '../util/types'\n\nexport const useSaveSecrets = (client: SanityClient, secrets: Secrets) => {\n return useCallback(\n async ({\n token,\n secretKey,\n enableSignedUrls,\n drmConfigId,\n }: Pick<\n Secrets,\n 'token' | 'secretKey' | 'enableSignedUrls' | 'drmConfigId'\n >): Promise<Secrets> => {\n let {signingKeyId, signingKeyPrivate} = secrets\n\n try {\n await saveSecrets(\n client,\n token!,\n secretKey!,\n enableSignedUrls,\n signingKeyId!,\n signingKeyPrivate!,\n drmConfigId!,\n )\n const valid = await testSecrets(client)\n if (!valid?.status && token && secretKey) {\n // oxlint-disable-next-line react/todo\n throw new Error('Invalid secrets')\n }\n } catch (err) {\n console.error('Error while trying to save secrets:', err)\n throw err\n }\n\n if (enableSignedUrls) {\n const hasValidSigningKeys = await haveValidSigningKeys(\n client,\n signingKeyId!,\n signingKeyPrivate!,\n )\n\n if (!hasValidSigningKeys) {\n try {\n const {data} = await createSigningKeys(client)\n signingKeyId = data.id\n signingKeyPrivate = data.private_key\n await saveSecrets(\n client,\n token!,\n secretKey!,\n enableSignedUrls,\n signingKeyId,\n signingKeyPrivate,\n drmConfigId ?? '',\n )\n } catch (err: any) {\n // eslint-disable-next-line no-console\n console.log('Error while creating and saving signing key:', err?.message)\n throw err\n }\n }\n }\n return {\n token,\n secretKey,\n enableSignedUrls,\n signingKeyId,\n signingKeyPrivate,\n drmConfigId,\n }\n },\n [client, secrets],\n )\n}\n","export const name = 'mux-input' as const\n\n// Caching namespace, as suspend-react might be in use by other components on the page we must ensure we don't collide\nexport const cacheNs = 'sanity-plugin-mux-input' as const\n\nexport const muxSecretsDocumentId = 'secrets.mux' as const\n\nexport const DIALOGS_Z_INDEX = 60_000\n\n/** Mux guide explaining the mezzanine (\"master access\") file and how it differs from MP4 renditions. */\nexport const MEZZANINE_LEARN_MORE_URL =\n 'https://www.mux.com/docs/guides/download-for-offline-editing#enable-master-access'\n\nexport const THUMBNAIL_ASPECT_RATIO = 16 / 9\n\n/** To prevent excessive height, thumbnails and input should not go beyond to this aspect ratio. */\nexport const MIN_ASPECT_RATIO = 5 / 4\n\nexport const AUDIO_ASPECT_RATIO = 5 / 1\n","import {useMemo} from 'react'\nimport {useDocumentValues} from 'sanity'\n\nimport {muxSecretsDocumentId} from '../util/constants'\nimport type {Secrets} from '../util/types'\n\nconst path = [\n 'token',\n 'secretKey',\n 'enableSignedUrls',\n 'signingKeyId',\n 'signingKeyPrivate',\n 'drmConfigId',\n]\nexport const useSecretsDocumentValues = () => {\n const {error, isLoading, value} = useDocumentValues<Partial<Secrets> | null | undefined>(\n muxSecretsDocumentId,\n path,\n )\n const cache = useMemo(() => {\n const exists = Boolean(value)\n const secrets: Secrets = {\n token: value?.token || null,\n secretKey: value?.secretKey || null,\n enableSignedUrls: value?.enableSignedUrls || false,\n signingKeyId: value?.signingKeyId || null,\n signingKeyPrivate: value?.signingKeyPrivate || null,\n drmConfigId: value?.drmConfigId || null,\n }\n return {\n isInitialSetup: !exists,\n needsSetup: !secrets?.token || !secrets?.secretKey,\n secrets,\n }\n }, [value])\n\n return {error, isLoading, value: cache}\n}\n","import {useReducer} from 'react'\n\nimport type {Secrets} from '../util/types'\n\nexport interface State extends Pick<\n Secrets,\n 'token' | 'secretKey' | 'enableSignedUrls' | 'drmConfigId'\n> {\n submitting: boolean\n error: string | null\n}\nexport type Action =\n | {type: 'submit'}\n | {type: 'error'; payload: string}\n | {type: 'reset'; payload: Secrets}\n | {type: 'change'; payload: {name: 'token'; value: string}}\n | {type: 'change'; payload: {name: 'secretKey'; value: string}}\n | {type: 'change'; payload: {name: 'enableSignedUrls'; value: boolean}}\n | {type: 'change'; payload: {name: 'drmConfigId'; value: string}}\nfunction init({token, secretKey, enableSignedUrls, drmConfigId}: Secrets): State {\n return {\n submitting: false,\n error: null,\n // Form inputs don't set the state back to null when clearing a field, but uses empty strings\n // This ensures the `dirty` check works correctly\n token: token ?? '',\n secretKey: secretKey ?? '',\n enableSignedUrls: enableSignedUrls ?? false,\n drmConfigId: drmConfigId ?? '',\n }\n}\nfunction reducer(state: State, action: Action) {\n switch (action?.type) {\n case 'submit':\n return {...state, submitting: true, error: null}\n case 'error':\n return {...state, submitting: false, error: action.payload}\n case 'reset':\n return init(action.payload)\n case 'change':\n return {...state, [action.payload.name]: action.payload.value}\n default:\n throw new Error(`Unknown action type: ${(action as unknown as Action)?.type}`)\n }\n}\n\nexport const useSecretsFormState = (secrets: Secrets) => useReducer(reducer, secrets, init)\n","// Utils with a readName prefix are suspendable and should only be called in the render body\n// Not inside event callbacks or a useEffect.\n// They may be called dynamically, unlike useEffect\n\n// @TODO rename to readSigningPair\n\nimport type {SanityClient} from 'sanity'\nimport {suspend} from 'suspend-react'\n\nimport {cacheNs} from '../util/constants'\nimport {type Secrets} from '../util/types'\n\nexport const _id = 'secrets.mux' as const\n\nexport function readSecrets(client: SanityClient): Secrets {\n const {projectId, dataset} = client.config()\n return suspend(async () => {\n const data = await client.fetch(\n /* groq */ `*[_id == $_id][0]{\n token,\n secretKey,\n enableSignedUrls,\n signingKeyId,\n signingKeyPrivate,\n drmConfigId\n }`,\n {_id},\n )\n return {\n token: data?.token || null,\n secretKey: data?.secretKey || null,\n enableSignedUrls: Boolean(data?.enableSignedUrls) || false,\n signingKeyId: data?.signingKeyId || null,\n signingKeyPrivate: data?.signingKeyPrivate || null,\n drmConfigId: data?.drmConfigId || null,\n }\n }, [cacheNs, _id, projectId, dataset])\n}\n","import {useTheme_v2} from '@sanity/ui'\nimport {type CSSProperties, useId, useMemo} from 'react'\n\nexport interface Props {\n height?: number\n}\nexport default function MuxLogo({height = 26}: Props) {\n const id = useId()\n const theme = useTheme_v2()\n const fillColor = theme.color._dark ? 'white' : 'black'\n const titleId = useMemo(() => `${id}-title`, [id])\n\n const pathStyle: CSSProperties = {\n fillRule: 'nonzero',\n }\n\n return (\n <svg\n aria-labelledby={titleId}\n style={{height: `${height}px`}}\n viewBox=\"0 0 1600 500\"\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlSpace=\"preserve\"\n >\n <g id=\"Layer-1\" fill={fillColor}>\n <path\n d=\"M994.287,93.486c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m0,-93.486c-34.509,-0 -62.484,27.976 -62.484,62.486l0,187.511c0,68.943 -56.09,125.033 -125.032,125.033c-68.942,-0 -125.03,-56.09 -125.03,-125.033l0,-187.511c0,-34.51 -27.976,-62.486 -62.485,-62.486c-34.509,-0 -62.484,27.976 -62.484,62.486l0,187.511c0,137.853 112.149,250.003 249.999,250.003c137.851,-0 250.001,-112.15 250.001,-250.003l0,-187.511c0,-34.51 -27.976,-62.486 -62.485,-62.486\"\n style={pathStyle}\n />\n <path\n d=\"M1537.51,468.511c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m-275.883,-218.509l-143.33,143.329c-24.402,24.402 -24.402,63.966 0,88.368c24.402,24.402 63.967,24.402 88.369,-0l143.33,-143.329l143.328,143.329c24.402,24.4 63.967,24.402 88.369,-0c24.403,-24.402 24.403,-63.966 0.001,-88.368l-143.33,-143.329l0.001,-0.004l143.329,-143.329c24.402,-24.402 24.402,-63.965 0,-88.367c-24.402,-24.402 -63.967,-24.402 -88.369,-0l-143.329,143.328l-143.329,-143.328c-24.402,-24.401 -63.967,-24.402 -88.369,-0c-24.402,24.402 -24.402,63.965 0,88.367l143.329,143.329l0,0.004Z\"\n style={pathStyle}\n />\n <path\n d=\"M437.511,468.521c-17.121,-0 -31,-13.879 -31,-31c0,-17.121 13.879,-31 31,-31c17.121,-0 31,13.879 31,31c0,17.121 -13.879,31 -31,31m23.915,-463.762c-23.348,-9.672 -50.226,-4.327 -68.096,13.544l-143.331,143.329l-143.33,-143.329c-17.871,-17.871 -44.747,-23.216 -68.096,-13.544c-23.349,9.671 -38.574,32.455 -38.574,57.729l0,375.026c0,34.51 27.977,62.486 62.487,62.486c34.51,-0 62.486,-27.976 62.486,-62.486l0,-224.173l80.843,80.844c24.404,24.402 63.965,24.402 88.369,-0l80.843,-80.844l0,224.173c0,34.51 27.976,62.486 62.486,62.486c34.51,-0 62.486,-27.976 62.486,-62.486l0,-375.026c0,-25.274 -15.224,-48.058 -38.573,-57.729\"\n style={pathStyle}\n />\n </g>\n </svg>\n )\n}\n","import {styled} from 'styled-components'\n\nimport MuxLogo from './MuxLogo'\n\nconst Logo = styled.span`\n display: inline-block;\n height: 0.8em;\n margin-right: 1em;\n transform: translate(0.3em, -0.2em);\n`\n\nexport const Header = () => (\n <>\n <Logo>\n <MuxLogo height={13} />\n </Logo>\n API Credentials\n </>\n)\n","import {Box, Flex, Stack, Text} from '@sanity/ui'\nimport {memo} from 'react'\n\n// @TODO: get rid of this once v3 core is stable\n\nexport interface Props {\n children: React.ReactNode\n title: React.ReactNode\n description?: React.ReactNode\n inputId: string\n}\n\nfunction FormField(props: Props) {\n const {children, title, description, inputId} = props\n\n return (\n <Stack gap={1}>\n <Flex align=\"flex-end\">\n <Box flex={1} paddingY={2}>\n <Stack gap={2}>\n <Text as=\"label\" htmlFor={inputId} weight=\"semibold\" size={1}>\n {title || <em>Untitled</em>}\n </Text>\n\n {description && (\n <Text muted size={1}>\n {description}\n </Text>\n )}\n </Stack>\n </Box>\n </Flex>\n <div>{children}</div>\n </Stack>\n )\n}\n\nexport default memo(FormField)\n","import {Box, Button, Card, Checkbox, Dialog, Flex, Inline, Stack, Text, TextInput} from '@sanity/ui'\nimport {Code} from '@sanity/ui/code'\nimport {\n type ChangeEvent,\n type SubmitEvent,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n} from 'react'\nimport {clear, preload} from 'suspend-react'\n\nimport {useClient} from '../hooks/useClient'\nimport type {SetDialogState} from '../hooks/useDialogState'\nimport {useDialogState} from '../hooks/useDialogState'\nimport {useSaveSecrets} from '../hooks/useSaveSecrets'\nimport {useSecretsDocumentValues} from '../hooks/useSecretsDocumentValues'\nimport {useSecretsFormState} from '../hooks/useSecretsFormState'\nimport {cacheNs, DIALOGS_Z_INDEX} from '../util/constants'\nimport {_id as secretsId} from '../util/readSecrets'\nimport type {Secrets} from '../util/types'\nimport {Header} from './ConfigureApi.styled'\nimport FormField from './FormField'\n\n// Props for the dialog component when used with external state management\nexport interface ConfigureApiDialogProps {\n setDialogState: SetDialogState\n secrets: Secrets\n}\n\nconst fieldNames = ['token', 'secretKey', 'enableSignedUrls', 'drmConfigId'] as const\n\n// Internal dialog component that can be used with external state\nexport function ConfigureApiDialog({secrets, setDialogState}: ConfigureApiDialogProps) {\n const client = useClient()\n const [state, dispatch] = useSecretsFormState(secrets)\n const hasSecretsInitially = useMemo(() => secrets.token && secrets.secretKey, [secrets])\n const handleClose = useCallback(() => setDialogState(false), [setDialogState])\n const dirty = useMemo(\n () =>\n secrets.token !== state.token ||\n secrets.secretKey !== state.secretKey ||\n secrets.enableSignedUrls !== state.enableSignedUrls ||\n secrets.drmConfigId !== state.drmConfigId,\n [secrets, state],\n )\n const id = `ConfigureApi${useId()}`\n const [tokenId, secretKeyId, enableSignedUrlsId, drmConfigIdId] = useMemo<typeof fieldNames>(\n () => fieldNames.map((field) => `${id}-${field}`) as unknown as typeof fieldNames,\n [id],\n )\n const firstField = useRef<HTMLInputElement>(null)\n const handleSaveSecrets = useSaveSecrets(client, secrets)\n const saving = useRef(false)\n\n const handleSubmit = useCallback(\n (event: SubmitEvent<HTMLFormElement>) => {\n event.preventDefault()\n\n if (!saving.current && event.currentTarget.reportValidity()) {\n saving.current = true\n dispatch({type: 'submit'})\n const {token, secretKey, enableSignedUrls, drmConfigId} = state\n handleSaveSecrets({token, secretKey, enableSignedUrls, drmConfigId})\n .then((savedSecrets) => {\n const {projectId, dataset} = client.config()\n clear([cacheNs, secretsId, projectId, dataset])\n preload(() => Promise.resolve(savedSecrets), [cacheNs, secretsId, projectId, dataset])\n setDialogState(false)\n })\n .catch((err) => dispatch({type: 'error', payload: err.message}))\n .finally(() => {\n saving.current = false\n })\n }\n },\n [client, dispatch, handleSaveSecrets, setDialogState, state],\n )\n const handleChangeToken = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'token', value: event.currentTarget.value},\n })\n },\n [dispatch],\n )\n const handleChangeSecretKey = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'secretKey', value: event.currentTarget.value},\n })\n },\n [dispatch],\n )\n const handleChangeEnableSignedUrls = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'enableSignedUrls', value: event.currentTarget.checked},\n })\n },\n [dispatch],\n )\n const handleChangeDrmConfigId = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n dispatch({\n type: 'change',\n payload: {name: 'drmConfigId', value: event.currentTarget.value},\n })\n },\n [dispatch],\n )\n\n useEffect(() => {\n if (firstField.current) {\n firstField.current.focus()\n }\n }, [firstField])\n\n return (\n <Dialog\n animate\n id={id}\n onClose={handleClose}\n onClickOutside={handleClose}\n header={<Header />}\n zOffset={DIALOGS_Z_INDEX}\n position=\"fixed\"\n width={1}\n >\n <Box padding={3}>\n <form onSubmit={handleSubmit} noValidate>\n <Stack gap={4}>\n {!hasSecretsInitially && (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"primary\">\n <Stack gap={3}>\n <Text size={1}>\n To set up a new access token, go to your{' '}\n <a\n href=\"https://dashboard.mux.com/settings/access-tokens\"\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n >\n account on mux.com\n </a>\n .\n </Text>\n <Text size={1}>\n The access token needs permissions: <strong>Mux Video </strong>\n (Full Access) and <strong>Mux Data</strong> (Read)\n <br />\n To use Signed URLs, the token must also have System permissions.\n <br />\n The credentials will be stored safely in a hidden document only available to\n editors.\n </Text>\n </Stack>\n </Card>\n )}\n <FormField title=\"Access Token\" inputId={tokenId}>\n <TextInput\n id={tokenId}\n ref={firstField}\n onChange={handleChangeToken}\n type=\"text\"\n value={state.token ?? ''}\n required={!!state.secretKey || state.enableSignedUrls}\n />\n </FormField>\n <FormField title=\"Secret Key\" inputId={secretKeyId}>\n <TextInput\n id={secretKeyId}\n onChange={handleChangeSecretKey}\n type=\"text\"\n value={state.secretKey ?? ''}\n required={!!state.token || state.enableSignedUrls}\n />\n </FormField>\n\n <Stack gap={4}>\n <Flex align=\"center\">\n <Checkbox\n id={enableSignedUrlsId}\n onChange={handleChangeEnableSignedUrls}\n checked={state.enableSignedUrls}\n style={{display: 'block'}}\n />\n <Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor={enableSignedUrlsId}>Enable Signed Urls</label>\n </Text>\n </Box>\n </Flex>\n {secrets.signingKeyId && state.enableSignedUrls ? (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"caution\">\n <Stack gap={3}>\n <Text size={1}>The signing key ID that Sanity will use is:</Text>\n <Code size={1}>{secrets.signingKeyId}</Code>\n <Text size={1}>\n This key is only used for previewing content in the Sanity UI.\n <br />\n You should generate a different key to use in your application server.\n </Text>\n </Stack>\n </Card>\n ) : null}\n </Stack>\n\n <FormField title=\"DRM Configuration ID\" inputId={drmConfigIdId}>\n <TextInput\n id={drmConfigIdId}\n onChange={handleChangeDrmConfigId}\n type=\"text\"\n value={state.drmConfigId ?? ''}\n required={false}\n />\n </FormField>\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"neutral\">\n <Stack gap={3}>\n <Text size={1}>\n DRM (Digital Rights Management) provides an extra layer of content security for\n video content streamed from Mux. For additional information check out our{' '}\n <a\n href=\"https://www.mux.com/docs/guides/protect-videos-with-drm#play-drm-protected-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n DRM Guide\n </a>\n .\n </Text>\n <Text size={1}>\n <a\n href=\"https://www.mux.com/support/human\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Contact us\n </a>{' '}\n to get started using DRM.\n </Text>\n </Stack>\n </Card>\n\n <Inline gap={2}>\n <Button\n text=\"Save\"\n disabled={!dirty}\n loading={state.submitting}\n tone=\"primary\"\n mode=\"default\"\n type=\"submit\"\n />\n <Button\n disabled={state.submitting}\n text=\"Cancel\"\n mode=\"bleed\"\n onClick={handleClose}\n />\n </Inline>\n {state.error && (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"critical\">\n <Text>{state.error}</Text>\n </Card>\n )}\n </Stack>\n </form>\n </Box>\n </Dialog>\n )\n}\n\n// Wrapper component that manages its own dialog state (used in VideosBrowser)\nexport default function ConfigureApi() {\n const [dialogOpen, setDialogOpen] = useDialogState()\n const secretDocumentValues = useSecretsDocumentValues()\n\n const openDialog = useCallback(() => setDialogOpen('secrets'), [setDialogOpen])\n\n if (dialogOpen === 'secrets') {\n return (\n <ConfigureApiDialog\n secrets={secretDocumentValues.value.secrets}\n setDialogState={setDialogOpen}\n />\n )\n }\n\n return <Button mode=\"bleed\" text=\"Configure plugin\" onClick={openDialog} />\n}\n","import {truncateString} from 'sanity'\n\n/**\n * Generates a placeholder title for a Mux asset when no title is available.\n * This format is used when importing assets that don't have a title in Mux.\n *\n * @param assetId - The Mux asset ID\n * @returns A placeholder title in the format \"Asset #[truncated-id]\"\n */\nexport function generateAssetPlaceholder(assetId: string): string {\n return `Asset #${truncateString(assetId, 15)}`\n}\n\n/**\n * Checks if a filename is empty or has the placeholder format.\n * This is used to determine if a video title should be updated during metadata sync.\n *\n * @param filename - The current filename/title of the video\n * @param assetId - The Mux asset ID to check against\n * @returns true if the filename is empty or matches the placeholder format\n */\nexport function isEmptyOrPlaceholderTitle(filename: string | undefined, assetId: string): boolean {\n // Check if filename is empty/undefined\n if (!filename || filename.trim() === '') {\n return true\n }\n\n // Check if filename matches the placeholder format for this asset\n const placeholder = generateAssetPlaceholder(assetId)\n return filename === placeholder\n}\n","import type {MuxAsset} from './types'\n\nexport function parseMuxDate(date: MuxAsset['created_at']): Date {\n return new Date(Number(date) * 1000)\n}\n","import type {SanityClient} from 'sanity'\n\nimport {getMuxAddonClient} from '../util/muxAddonClient'\nimport {PLUGIN_VERSION_QUERY} from '../util/pluginVersion'\nimport type {MuxAsset, VideoAssetDocument} from '../util/types'\n\nexport function deleteAssetOnMux(client: SanityClient, assetId: string) {\n const {dataset} = client.config()\n return getMuxAddonClient(client).request<void>({\n url: `/addons/mux/assets/${dataset}/${assetId}`,\n withCredentials: true,\n method: 'DELETE',\n query: PLUGIN_VERSION_QUERY,\n })\n}\n\nexport async function deleteAsset({\n client,\n asset,\n deleteOnMux,\n}: {\n client: SanityClient\n asset: VideoAssetDocument\n deleteOnMux: boolean\n}) {\n if (!asset?._id) return true\n\n try {\n await client.delete(asset._id)\n } catch {\n return 'failed-sanity'\n }\n\n if (deleteOnMux && asset?.assetId) {\n try {\n await deleteAssetOnMux(client, asset.assetId)\n } catch {\n return 'failed-mux'\n }\n }\n\n return true\n}\n\nexport function getAsset(client: SanityClient, assetId: string) {\n const {dataset} = client.config()\n return getMuxAddonClient(client).request<{data: MuxAsset}>({\n url: `/addons/mux/assets/${dataset}/data/${assetId}`,\n withCredentials: true,\n method: 'GET',\n query: PLUGIN_VERSION_QUERY,\n })\n}\n\nexport function listAssets(\n client: SanityClient,\n options: {limit?: number; cursor?: string | null},\n) {\n const {dataset} = client.config()\n const query: {limit?: string; cursor?: string} = {}\n\n if (options.limit) {\n query.limit = options.limit.toString()\n }\n if (options.cursor) {\n query.cursor = options.cursor\n }\n\n return getMuxAddonClient(client).request<{data: MuxAsset[]; next_cursor?: string | null}>({\n url: `/addons/mux/assets/${dataset}/data/list`,\n withCredentials: true,\n method: 'GET',\n query: {...query, ...PLUGIN_VERSION_QUERY},\n })\n}\n\n/**\n * Adds a new text track to an existing asset using a VTT file URL\n */\nexport function addTextTrackFromUrl(\n client: SanityClient,\n assetId: string,\n vttUrl: string,\n options: {\n language_code: string\n name: string\n text_type?: 'subtitles'\n },\n) {\n const {dataset} = client.config()\n\n return getMuxAddonClient(client).request<{data: MuxAsset}>({\n url: `/addons/mux/assets/${dataset}/${assetId}/tracks`,\n withCredentials: true,\n method: 'POST',\n body: {\n url: vttUrl,\n type: 'text',\n language_code: options.language_code,\n name: options.name,\n text_type: options.text_type || 'subtitles',\n },\n headers: {\n 'Content-Type': 'application/json',\n },\n query: PLUGIN_VERSION_QUERY,\n })\n}\n\n/**\n * Generates subtitles automatically for an audio track\n */\nexport function generateSubtitles(\n client: SanityClient,\n assetId: string,\n audioTrackId: string,\n options: {\n language_code: string\n name: string\n },\n) {\n const {dataset} = client.config()\n return getMuxAddonClient(client).request<{data: MuxAsset}>({\n url: `/addons/mux/assets/${dataset}/${assetId}/tracks/${audioTrackId}/generate-subtitles`,\n withCredentials: true,\n method: 'POST',\n body: {\n generated_subtitles: [\n {\n language_code: options.language_code,\n name: options.name,\n },\n ],\n },\n headers: {\n 'Content-Type': 'application/json',\n },\n query: PLUGIN_VERSION_QUERY,\n })\n}\n\n/**\n * Deletes a text track from an asset\n */\nexport function deleteTextTrack(client: SanityClient, assetId: string, trackId: string) {\n const {dataset} = client.config()\n return getMuxAddonClient(client).request<{data: MuxAsset}>({\n url: `/addons/mux/assets/${dataset}/${assetId}/tracks/${trackId}`,\n withCredentials: true,\n method: 'DELETE',\n query: PLUGIN_VERSION_QUERY,\n })\n}\n\n/**\n * Updates master access (the \"mezzanine\" file in Mux's docs) on a Mux asset, via the addon proxy.\n * @see {@link https://docs.mux.com/api-reference/video/assets/update-asset-master-access}\n */\nexport function updateMasterAccess(\n client: SanityClient,\n assetId: string,\n masterAccess: 'temporary' | 'none',\n) {\n const {dataset} = client.config()\n return getMuxAddonClient(client).request<{data: MuxAsset}>({\n url: `/addons/mux/assets/${dataset}/${assetId}/master-access`,\n withCredentials: true,\n method: 'PUT',\n body: {master_access: masterAccess},\n headers: {\n 'Content-Type': 'application/json',\n },\n query: PLUGIN_VERSION_QUERY,\n })\n}\n","import {useEffect, useState} from 'react'\nimport {defer, of, timer} from 'rxjs'\nimport {concatMap, expand, tap} from 'rxjs/operators'\nimport type {SanityClient} from 'sanity'\n\nimport {listAssets} from '../actions/assets'\nimport type {MuxAsset} from '../util/types'\n\nconst ASSETS_PER_PAGE = 100\n\ntype MuxAssetsState = {\n cursor: string | null\n loading: boolean\n data?: MuxAsset[]\n error?: FetchError\n hasSkippedAssetsWithoutPlayback?: boolean\n}\n\ntype FetchError =\n | {\n _tag: 'FetchError'\n }\n | {_tag: 'MuxError'; error: unknown}\n\ntype PageResult = (\n | {\n data: MuxAsset[]\n next_cursor: string | null\n }\n | {\n error: FetchError\n }\n) & {\n cursor: string | null\n}\n\n/**\n * @docs {@link https://docs.mux.com/api-reference#video/operation/list-assets}\n */\nasync function fetchMuxAssetsPage(\n client: SanityClient,\n cursor: string | null,\n): Promise<PageResult> {\n try {\n const response = await listAssets(client, {\n limit: ASSETS_PER_PAGE,\n cursor,\n })\n\n return {\n cursor,\n data: response.data,\n next_cursor: response.next_cursor || null,\n }\n } catch {\n return {\n cursor,\n error: {_tag: 'FetchError'},\n }\n }\n}\n\nfunction accumulateIntermediateState(\n currentState: MuxAssetsState,\n pageResult: PageResult,\n): MuxAssetsState {\n const currentData = ('data' in currentState && currentState.data) || []\n const newAssets = ('data' in pageResult && pageResult.data) || []\n\n // Filter assets and check for skipped items\n const {validAssets, skippedInThisPage} = newAssets.reduce<{\n validAssets: MuxAsset[]\n skippedInThisPage: boolean\n }>(\n (acc, asset) => {\n const hasPlaybackIds = asset.playback_ids && asset.playback_ids.length > 0\n const isDuplicate = currentData.some((a) => a.id === asset.id)\n\n if (!hasPlaybackIds) {\n acc.skippedInThisPage = true\n }\n\n if (hasPlaybackIds && !isDuplicate) {\n acc.validAssets.push(asset)\n }\n\n return acc\n },\n {validAssets: [], skippedInThisPage: false},\n )\n\n return {\n ...currentState,\n data: [...currentData, ...validAssets],\n error:\n 'error' in pageResult\n ? pageResult.error\n : // Reset error if current page is successful\n undefined,\n cursor: 'next_cursor' in pageResult ? pageResult.next_cursor : pageResult.cursor,\n loading: true,\n hasSkippedAssetsWithoutPlayback:\n currentState.hasSkippedAssetsWithoutPlayback || skippedInThisPage,\n }\n}\n\nfunction hasMorePages(pageResult: PageResult) {\n return (\n typeof pageResult === 'object' && 'next_cursor' in pageResult && pageResult.next_cursor !== null\n )\n}\n\n/**\n * Fetches all assets from a Mux environment. Rules:\n * - One page at a time\n * - Uses cursor-based pagination\n * - We've finished fetching when `next_cursor` is null\n * - Rate limiting to one request per 2 seconds\n * - Update state while still fetching to give feedback to users\n */\nexport default function useMuxAssets({client, enabled}: {client: SanityClient; enabled: boolean}) {\n const [state, setState] = useState<MuxAssetsState>({loading: true, cursor: null})\n\n useEffect(() => {\n if (!enabled) return\n\n const subscription = defer(() =>\n fetchMuxAssetsPage(\n client,\n // When we've already successfully loaded before (fully or partially), we start from the next cursor to avoid re-fetching\n 'data' in state && state.data && state.data.length > 0 && !state.error\n ? state.cursor\n : null,\n ),\n )\n .pipe(\n // Here we use \"expand\" to recursively fetch next pages\n expand((pageResult) => {\n // if fetched page has next_cursor, we continue emitting, requesting the next page\n // after 2s to avoid rate limiting\n if (hasMorePages(pageResult)) {\n return timer(2000).pipe(\n concatMap(() =>\n defer(() =>\n fetchMuxAssetsPage(\n client,\n 'next_cursor' in pageResult ? pageResult.next_cursor : null,\n ),\n ),\n ),\n )\n }\n\n // Else, we stop emitting\n return of()\n }),\n\n // On each iteration, persist intermediate states to give feedback to users\n tap((pageResult) =>\n setState((prevState) => accumulateIntermediateState(prevState, pageResult)),\n ),\n )\n .subscribe({\n // Once done, let the user know we've stopped loading\n complete: () => {\n setState((prev) => ({\n ...prev,\n loading: false,\n }))\n },\n })\n\n // Unsubscribe on component unmount to prevent memory leaks or fetching unnecessarily\n return () => subscription.unsubscribe()\n // oxlint-disable-next-line react/rule-suppression\n // oxlint-disable-next-line react/exhaustive-deps -- secrets/pluginConfig are stable for the asset fetch lifecycle once enabled\n }, [enabled])\n\n return state\n}\n","import {uuid} from '@sanity/uuid'\nimport {useMemo, useState} from 'react'\nimport {createHookFromObservableFactory, type DocumentStore, useDocumentStore} from 'sanity'\n\nimport {generateAssetPlaceholder} from '../util/assetTitlePlaceholder'\nimport {parseMuxDate} from '../util/parsers'\nimport type {MuxAsset, VideoAssetDocument} from '../util/types'\nimport {SANITY_API_VERSION, useClient} from './useClient'\nimport useMuxAssets from './useMuxAssets'\nimport {useSecretsDocumentValues} from './useSecretsDocumentValues'\n\ntype ImportState = 'closed' | 'idle' | 'importing' | 'done' | 'error'\n\nexport type AssetInSanity = {\n uploadId: string\n assetId: string\n}\n\nexport default function useImportMuxAssets() {\n const documentStore = useDocumentStore()\n const client = useClient()\n\n const [assetsInSanity, assetsInSanityLoading] = useAssetsInSanity(documentStore)\n\n const secretDocumentValues = useSecretsDocumentValues()\n const hasSecrets = !!secretDocumentValues.value.secrets?.secretKey\n\n const [importError, setImportError] = useState<unknown>()\n const [importState, setImportState] = useState<ImportState>('closed')\n const dialogOpen = importState !== 'closed'\n\n const muxAssets = useMuxAssets({\n client,\n enabled: hasSecrets && dialogOpen,\n })\n\n const missingAssets = useMemo(() => {\n return assetsInSanity && muxAssets.data\n ? muxAssets.data.filter((a) => !assetExistsInSanity(a, assetsInSanity))\n : undefined\n }, [assetsInSanity, muxAssets.data])\n\n const [selectedAssets, setSelectedAssets] = useState<MuxAsset[]>([])\n\n const closeDialog = () => {\n if (importState !== 'importing') setImportState('closed')\n }\n const openDialog = () => {\n if (importState === 'closed') setImportState('idle')\n }\n\n async function importAssets() {\n setImportState('importing')\n const documents = selectedAssets.flatMap((asset) => muxAssetToSanityDocument(asset) || [])\n\n const tx = client.transaction()\n documents.forEach((doc) => tx.create(doc))\n\n try {\n await tx.commit({returnDocuments: false})\n setSelectedAssets([])\n setImportState('done')\n } catch (error) {\n setImportState('error')\n setImportError(error)\n }\n }\n\n return {\n assetsInSanityLoading,\n closeDialog,\n dialogOpen,\n importState,\n importError,\n hasSecrets,\n importAssets,\n missingAssets,\n muxAssets,\n openDialog,\n selectedAssets,\n setSelectedAssets,\n }\n}\n\nfunction muxAssetToSanityDocument(asset: MuxAsset): VideoAssetDocument | undefined {\n const playbackId = (asset.playback_ids || []).find((p) => p.id)?.id\n\n if (!playbackId) return undefined\n\n return {\n _id: uuid(),\n _type: 'mux.videoAsset',\n _updatedAt: new Date().toISOString(),\n _createdAt: parseMuxDate(asset.created_at).toISOString(),\n assetId: asset.id,\n playbackId,\n filename: asset.meta?.title ?? generateAssetPlaceholder(asset.id),\n status: asset.status,\n data: asset,\n }\n}\n\nconst useAssetsInSanity = createHookFromObservableFactory<AssetInSanity[], DocumentStore>(\n (documentStore) => {\n return documentStore.listenQuery(\n /* groq */ `*[_type == \"mux.videoAsset\"] {\n \"uploadId\": coalesce(uploadId, data.upload_id),\n \"assetId\": coalesce(assetId, data.id),\n }`,\n {},\n {\n apiVersion: SANITY_API_VERSION,\n },\n )\n },\n)\n\nfunction assetExistsInSanity(asset: MuxAsset, existingAssets: AssetInSanity[]) {\n // Don't allow importing assets that are not ready\n if (asset.status !== 'ready') return false\n\n return existingAssets.some(\n (existing) => existing.assetId === asset.id || existing.uploadId === asset.upload_id,\n )\n}\n","import {useEffect, useState} from 'react'\n\ntype IntersectionOptions = {\n root?: Element | null\n rootMargin?: string\n threshold?: number\n onChange?: (inView: boolean) => void\n}\n\nexport function useInView(\n ref: React.RefObject<HTMLDivElement | null>,\n options: IntersectionOptions = {},\n) {\n const [inView, setInView] = useState(false)\n\n useEffect(() => {\n if (!ref.current) return\n\n const observer = new IntersectionObserver(([entry], obs) => {\n // ==== from react-intersection-observer ====\n // While it would be nice if you could just look at isIntersecting to determine if the component is inside the viewport, browsers can't agree on how to use it.\n // -Firefox ignores `threshold` when considering `isIntersecting`, so it will never be false again if `threshold` is > 0\n const nowInView =\n entry!.isIntersecting &&\n obs.thresholds.some((threshold) => entry!.intersectionRatio >= threshold)\n\n // Update our state when observer callback fires\n setInView(nowInView)\n options?.onChange?.(nowInView)\n }, options)\n\n const toObserve = ref.current\n observer.observe(toObserve)\n\n return () => {\n if (toObserve) observer.unobserve(toObserve)\n }\n }, [options, ref])\n\n return inView\n}\n","import type {\n AdvancedPlaybackPolicy,\n MuxPlaybackId,\n PlaybackPolicy,\n VideoAssetDocument,\n} from './types'\n\n/* - Returns the playback id of the asset based on the specified priority.\n By default chooses the \"strongest\" policy\n - Otherwise, returns the first playback id in the array.\n */\nexport function getPlaybackId(\n asset: Pick<VideoAssetDocument, 'data'>,\n priority: string[] = ['drm', 'signed', 'public'],\n): string {\n try {\n if (!asset) {\n throw new TypeError('Tried to get playback Id with no asset')\n }\n\n const playbackIds = asset.data?.playback_ids\n if (playbackIds && playbackIds.length > 0) {\n for (const policy of priority) {\n const match = playbackIds.find((entry) => entry.policy === policy)\n if (match) {\n return match.id\n }\n }\n\n return playbackIds[0]!.id\n }\n\n throw new TypeError('Missing playbackId')\n } catch (e) {\n console.error('Asset is missing a playbackId', {asset}, e)\n throw e\n }\n}\n\nexport function getPlaybackPolicy(\n asset: Pick<VideoAssetDocument, 'data' | 'playbackId'>,\n): MuxPlaybackId | undefined {\n return (\n asset.data?.playback_ids?.find(\n (playbackId) => getPlaybackId(asset, ['drm', 'signed', 'public']) === playbackId.id,\n ) ?? {id: '', policy: 'public'}\n )\n}\n\nexport function getPlaybackPolicyById(\n asset: Pick<VideoAssetDocument, 'data'>,\n playbackId: string,\n): MuxPlaybackId | undefined {\n return asset.data?.playback_ids?.find((entry) => playbackId === entry.id)\n}\n\nexport function hasPlaybackPolicy(\n data: Partial<{\n playback_policy?: PlaybackPolicy[]\n advanced_playback_policies: AdvancedPlaybackPolicy[]\n }>,\n policy: PlaybackPolicy,\n) {\n return (\n (data.advanced_playback_policies &&\n data.advanced_playback_policies.find((p) => p.policy === policy)) ||\n data.playback_policy?.find((p) => p === policy)\n )\n}\n","import type {SanityClient} from 'sanity'\nimport {suspend} from 'suspend-react'\n\nimport {readSecrets} from './readSecrets'\nimport type {AnimatedThumbnailOptions, ThumbnailOptions} from './types'\n\nexport type Audience = 'g' | 's' | 't' | 'v' | 'd'\n\nexport type Payload<T extends Audience> = T extends 'g'\n ? AnimatedThumbnailOptions\n : T extends 's'\n ? never\n : T extends 't'\n ? ThumbnailOptions\n : T extends 'v'\n ? never\n : T extends 'd'\n ? never\n : never\n\n/**\n * Uses suspend. Call this with {@link tryWithSuspend} or rethrow the Promise\n */\nexport function generateJwt<T extends Audience>(\n client: SanityClient,\n playbackId: string,\n aud: T,\n payload?: Payload<T>,\n): string {\n const {signingKeyId, signingKeyPrivate} = readSecrets(client)\n if (!signingKeyId) {\n throw new TypeError(\"Missing `signingKeyId`.\\n Check your plugin's configuration\")\n }\n if (!signingKeyPrivate) {\n throw new TypeError(\"Missing `signingKeyPrivate`.\\n Check your plugin's configuration\")\n }\n\n /* Using suspend means we need to use Suspense on parent components.\n Also, this will throw a Promise under the hood (apparently common in React), \n so if we want to catch errors we have to take this into account in catch blocks\n and rethrow promises. */\n // @ts-expect-error - handle missing typings for this package\n const {default: sign} = suspend(() => import('jsonwebtoken-esm/sign'), ['jsonwebtoken-esm/sign'])\n\n return sign(\n payload ? JSON.parse(JSON.stringify(payload, (_, v) => v ?? undefined)) : {},\n atob(signingKeyPrivate),\n {\n algorithm: 'RS256',\n keyid: signingKeyId,\n audience: aud,\n subject: playbackId,\n noTimestamp: true,\n expiresIn: '12h',\n },\n )\n}\n","import type {SanityClient} from 'sanity'\n\nimport {getPlaybackId} from '../util/getPlaybackPolicy'\nimport {type Audience, generateJwt} from './generateJwt'\nimport {getPlaybackPolicyById} from './getPlaybackPolicy'\nimport type {AssetThumbnailOptions} from './types'\n\n/**\n * May throw a Promise. Call this with {@link tryWithSuspend} or rethrow the Promise\n */\nexport function createUrlParamsObject(\n client: SanityClient,\n asset: AssetThumbnailOptions['asset'],\n params: object,\n audience: Audience,\n) {\n const playbackId = getPlaybackId(asset)\n\n let searchParams = new URLSearchParams(\n JSON.parse(JSON.stringify(params, (_, v) => v ?? undefined)),\n )\n const playbackPolicy = getPlaybackPolicyById(asset, playbackId)?.policy\n if (playbackPolicy === 'signed' || playbackPolicy === 'drm') {\n const token = generateJwt(client, playbackId, audience, params)\n searchParams = new URLSearchParams({token})\n }\n\n return {playbackId, searchParams}\n}\n","import type {SanityClient} from 'sanity'\n\nimport {createUrlParamsObject} from './createUrlParamsObject'\nimport type {AnimatedThumbnailOptions, MuxAnimatedThumbnailUrl} from './types'\nimport {type AssetThumbnailOptions} from './types'\n\nexport interface AnimatedPosterSrcOptions extends AnimatedThumbnailOptions {\n asset: AssetThumbnailOptions['asset']\n client: SanityClient\n}\n\nexport function getAnimatedPosterSrc({\n asset,\n client,\n height,\n width,\n start = asset.thumbTime ? Math.max(0, asset.thumbTime - 2.5) : 0,\n end = start + 5,\n fps = 15,\n}: AnimatedPosterSrcOptions): MuxAnimatedThumbnailUrl {\n const params = {height, width, start, end, fps}\n\n const {playbackId, searchParams} = createUrlParamsObject(client, asset, params, 'g')\n\n return `https://image.mux.com/${playbackId}/animated.gif?${searchParams}`\n}\n","import type {SanityClient} from 'sanity'\n\nimport {createUrlParamsObject} from './createUrlParamsObject'\nimport type {MuxThumbnailUrl, ThumbnailOptions} from './types'\nimport {type AssetThumbnailOptions} from './types'\n\nexport interface PosterSrcOptions extends ThumbnailOptions {\n asset: AssetThumbnailOptions['asset']\n client: SanityClient\n}\n\nexport function getPosterSrc({\n asset,\n client,\n fit_mode,\n height,\n time = asset.thumbTime ?? undefined,\n width,\n}: PosterSrcOptions): MuxThumbnailUrl {\n const params = {fit_mode, height, width}\n if (time !== undefined) {\n ;(params as any).time = time\n }\n\n const {playbackId, searchParams} = createUrlParamsObject(client, asset, params, 't')\n\n return `https://image.mux.com/${playbackId}/thumbnail.png?${searchParams}`\n}\n","/**\n * When running `suspend()` from react-suspend a function may throw a Promise\n * causing unexpected behavior when catching.\n * @param block Your block of code that uses suspend\n * @param onError (optional) How to handle a regular Error\n * @returns Whatever is returned by the block if it succeeds, otherwise whatever is resolved by onError if defined\n * @throws rethrows the caught Promise to comply with Suspense logic\n */\nexport function tryWithSuspend<T, E>(\n block: () => T,\n onError?: (error: Error) => E,\n): T | E | undefined {\n try {\n return block()\n } catch (errorOrPromise) {\n if (errorOrPromise instanceof Promise) {\n // react-suspend will throw a Promise\n throw errorOrPromise\n }\n return onError ? onError(errorOrPromise as Error) : undefined\n }\n}\n","import {ErrorOutlineIcon} from '@sanity/icons/ErrorOutline'\nimport {Box, Card, type CardTone, Spinner, Stack, Text} from '@sanity/ui'\nimport {Suspense, useMemo, useRef, useState} from 'react'\nimport {styled} from 'styled-components'\n\nimport {useClient} from '../hooks/useClient'\nimport {useInView} from '../hooks/useInView'\nimport {THUMBNAIL_ASPECT_RATIO} from '../util/constants'\nimport {getAnimatedPosterSrc} from '../util/getAnimatedPosterSrc'\nimport {getPosterSrc} from '../util/getPosterSrc'\nimport {tryWithSuspend} from '../util/tryWithSuspend'\nimport type {AssetThumbnailOptions, MuxAnimatedThumbnailUrl, MuxThumbnailUrl} from '../util/types'\n\nconst Image = styled.img`\n transition: opacity 0.175s ease-out 0s;\n display: block;\n width: 100%;\n height: 100%;\n object-fit: contain;\n object-position: center center;\n`\n\ntype ImageStatus = 'loading' | 'error' | 'loaded'\n\nconst STATUS_TO_TONE: Record<ImageStatus, CardTone> = {\n loading: 'transparent',\n error: 'critical',\n loaded: 'default',\n}\n\nexport default function VideoThumbnail({\n asset,\n width,\n staticImage = false,\n}: {\n asset: AssetThumbnailOptions['asset']\n width?: number\n staticImage?: boolean\n}) {\n const posterWidth = width || 250\n const client = useClient()\n const ref = useRef<HTMLDivElement | null>(null)\n const inView = useInView(ref)\n\n const [status, setStatus] = useState<ImageStatus>('loading')\n const [error, setError] = useState<string | null>(null)\n\n const thumbnailSrc = useMemo(() => {\n return tryWithSuspend(\n () => {\n let thumbnail: MuxAnimatedThumbnailUrl | MuxThumbnailUrl | undefined\n\n if (staticImage) thumbnail = getPosterSrc({asset, client, width: posterWidth})\n else thumbnail = getAnimatedPosterSrc({asset, client, width: posterWidth})\n return thumbnail\n },\n (err: Error) => {\n // oxlint-disable-next-line react/todo\n handleError(err.message)\n return undefined\n },\n )\n }, [asset, client, posterWidth, staticImage])\n\n function handleLoad() {\n setStatus('loaded')\n }\n\n function handleError(err?: string) {\n setStatus('error')\n if (err) {\n setError(err)\n } else {\n setError('Failed loading thumbnail')\n }\n }\n\n return (\n <Suspense fallback={<span>Preparing thumbnail</span>}>\n <Card\n style={{\n aspectRatio: THUMBNAIL_ASPECT_RATIO,\n position: 'relative',\n maxWidth: width ? `${width}px` : undefined,\n width: '100%',\n flex: 1,\n }}\n border\n radius={2}\n ref={ref}\n tone={STATUS_TO_TONE[status]}\n >\n {inView ? (\n <>\n {status === 'loading' && (\n <Box\n style={{\n position: 'absolute',\n left: '50%',\n top: '50%',\n transform: 'translate(-50%, -50%)',\n }}\n >\n <Spinner />\n </Box>\n )}\n {status === 'error' && (\n <Stack\n gap={4}\n style={{\n position: 'absolute',\n width: '100%',\n left: 0,\n top: '50%',\n transform: 'translateY(-50%)',\n justifyItems: 'center',\n }}\n >\n <Text size={4} muted>\n <ErrorOutlineIcon style={{fontSize: '1.75em'}} />\n </Text>\n <Text muted align=\"center\">\n {error}\n </Text>\n </Stack>\n )}\n <Image\n src={thumbnailSrc ?? undefined}\n alt={`Preview for ${staticImage ? 'image' : 'video'} ${asset.filename || asset.assetId}`}\n onLoad={handleLoad}\n onError={() => handleError()}\n style={{opacity: status === 'loaded' ? 1 : 0}}\n />\n </>\n ) : null}\n </Card>\n </Suspense>\n )\n}\n","import {CheckmarkCircleIcon} from '@sanity/icons/CheckmarkCircle'\nimport {ErrorOutlineIcon} from '@sanity/icons/ErrorOutline'\nimport {InfoOutlineIcon} from '@sanity/icons/InfoOutline'\nimport {RetrieveIcon} from '@sanity/icons/Retrieve'\nimport {RetryIcon} from '@sanity/icons/Retry'\nimport {Box, Button, Card, Checkbox, Dialog, Flex, Heading, Spinner, Stack, Text} from '@sanity/ui'\nimport {Code} from '@sanity/ui/code'\nimport {truncateString, useFormattedDuration} from 'sanity'\nimport {styled} from 'styled-components'\n\nimport useImportMuxAssets from '../hooks/useImportMuxAssets'\nimport {DIALOGS_Z_INDEX} from '../util/constants'\nimport type {MuxAsset} from '../util/types'\nimport VideoThumbnail from './VideoThumbnail'\n\nconst MissingAssetCheckbox = styled(Checkbox)`\n position: static !important;\n\n input::after {\n content: '';\n position: absolute;\n inset: 0;\n display: block;\n cursor: pointer;\n z-index: 1000;\n }\n`\n\nfunction MissingAsset({\n asset,\n selectAsset,\n selected,\n}: {\n asset: MuxAsset\n selectAsset: (selected: boolean) => void\n selected: boolean\n}) {\n const duration = useFormattedDuration(asset.duration * 1000)\n\n return (\n <Card\n key={asset.id}\n tone={selected ? 'positive' : undefined}\n border\n paddingX={2}\n paddingY={3}\n style={{position: 'relative'}}\n radius={1}\n >\n <Flex align=\"center\" gap={2}>\n <MissingAssetCheckbox\n checked={selected}\n onChange={(e) => {\n selectAsset(e.currentTarget.checked)\n }}\n aria-label={selected ? `Import video ${asset.id}` : `Skip import of video ${asset.id}`}\n />\n <VideoThumbnail\n asset={{\n assetId: asset.id,\n data: asset,\n filename: asset.id,\n playbackId: asset.playback_ids.find((p) => p.id)?.id,\n }}\n width={150}\n />\n <Stack gap={2}>\n <Flex align=\"center\" gap={1}>\n <Code size={2}>{truncateString(asset.id, 15)}</Code>{' '}\n <Text muted size={2}>\n ({duration.formatted})\n </Text>\n </Flex>\n <Text size={1}>\n Uploaded at{' '}\n {new Date(Number(asset.created_at) * 1000).toLocaleDateString('en', {\n year: 'numeric',\n day: '2-digit',\n month: '2-digit',\n })}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )\n}\n\nfunction ImportVideosDialog(props: ReturnType<typeof useImportMuxAssets>) {\n const {importState} = props\n\n const canTriggerImport =\n (importState === 'idle' || importState === 'error') && props.selectedAssets.length > 0\n const isImporting = importState === 'importing'\n const noAssetsToImport =\n props.missingAssets?.length === 0 && !props.muxAssets.loading && !props.assetsInSanityLoading\n\n return (\n <Dialog\n animate\n header={'Import videos from Mux'}\n zOffset={DIALOGS_Z_INDEX}\n id=\"video-details-dialog\"\n onClose={props.closeDialog}\n onClickOutside={props.closeDialog}\n width={1}\n position=\"fixed\"\n footer={\n importState !== 'done' &&\n !noAssetsToImport && (\n <Card padding={3}>\n <Flex justify=\"space-between\" align=\"center\">\n <Button\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Cancel\"\n tone=\"critical\"\n onClick={props.closeDialog}\n disabled={isImporting}\n />\n {props.missingAssets && (\n <Button\n icon={RetrieveIcon}\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text={\n props.selectedAssets?.length > 0\n ? `Import ${props.selectedAssets.length} video(s)`\n : 'No video(s) selected'\n }\n tone=\"positive\"\n onClick={props.importAssets}\n iconRight={isImporting && Spinner}\n disabled={!canTriggerImport}\n />\n )}\n </Flex>\n </Card>\n )\n }\n >\n <Box padding={3}>\n {/* WARNING: SKIPPED ASSETS WITHOUT PLAYBACK */}\n {props.muxAssets.hasSkippedAssetsWithoutPlayback && (\n <Card tone=\"caution\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <InfoOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Some videos were skipped\n </Text>\n <Text size={1}>\n Videos without playback IDs cannot be imported and have been excluded from the\n list.\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* LOADING ASSETS STATE */}\n {(props.muxAssets.loading || props.assetsInSanityLoading) && (\n <Card tone=\"primary\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Loading assets from Mux\n </Text>\n <Text size={1}>\n This may take a while.\n {props.missingAssets &&\n props.missingAssets.length > 0 &&\n ` There are at least ${props.missingAssets.length} video${props.missingAssets.length > 1 ? 's' : ''} currently not in Sanity...`}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR LOADING MUX */}\n {props.muxAssets.error && (\n <Card tone=\"critical\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error getting all data from Mux\n </Text>\n <Text size={1}>\n {props.missingAssets\n ? `But we've found ${props.missingAssets.length} video${props.missingAssets.length > 1 ? 's' : ''} not in Sanity, which you can start importing now.`\n : 'Please try again or contact a developer for help.'}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* IMPORTING STATE */}\n {importState === 'importing' && (\n <Card tone=\"primary\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Importing {props.selectedAssets.length} video\n {props.selectedAssets.length > 1 && 's'} from Mux\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR IMPORTING */}\n {importState === 'error' && (\n <Card tone=\"critical\" marginBottom={5} padding={3} border>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error importing videos\n </Text>\n <Text size={1}>\n {props.importError\n ? `Error: ${props.importError}`\n : 'Please try again or contact a developer for help.'}\n </Text>\n <Box marginTop={1}>\n <Button\n icon={RetryIcon}\n text=\"Retry\"\n tone=\"primary\"\n onClick={props.importAssets}\n />\n </Box>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* NO ASSETS TO IMPORT or SUCESS STATE */}\n {(noAssetsToImport || importState === 'done') && (\n <Stack paddingY={5} marginBottom={4} gap={3} style={{textAlign: 'center'}}>\n <Box>\n <CheckmarkCircleIcon fontSize={48} />\n </Box>\n <Heading size={2}>\n {importState === 'done'\n ? `Videos imported successfully`\n : 'There are no Mux videos to import'}\n </Heading>\n <Text size={2}>\n {importState === 'done'\n ? 'You can now use them in your Sanity content.'\n : \"They're all in Sanity and ready to be used in your content.\"}\n </Text>\n </Stack>\n )}\n\n {/* MISSING ASSETS SELECTOR */}\n {props.missingAssets &&\n props.missingAssets.length > 0 &&\n (importState === 'idle' || importState === 'error') && (\n <Stack gap={4}>\n <Heading size={1}>\n There are {props.missingAssets.length}\n {props.muxAssets.loading && '+'} Mux video{props.missingAssets.length > 1 && 's'}{' '}\n not in Sanity\n </Heading>\n {!props.muxAssets.loading && (\n <Flex align=\"center\" paddingX={2}>\n <Checkbox\n id=\"import-all\"\n style={{display: 'block'}}\n onClick={(e) => {\n const selectAll = e.currentTarget.checked\n if (selectAll) {\n // eslint-disable-next-line no-unused-expressions\n props.missingAssets && props.setSelectedAssets(props.missingAssets)\n } else {\n props.setSelectedAssets([])\n }\n }}\n checked={props.selectedAssets.length === props.missingAssets.length}\n />\n <Box flex={1} paddingLeft={3} as=\"label\" htmlFor=\"import-all\">\n <Text>Import all</Text>\n </Box>\n </Flex>\n )}\n {props.missingAssets.map((asset) => (\n <MissingAsset\n key={asset.id}\n asset={asset}\n selectAsset={(selected) => {\n if (selected) {\n props.setSelectedAssets([...props.selectedAssets, asset])\n } else {\n props.setSelectedAssets(props.selectedAssets.filter((a) => a.id !== asset.id))\n }\n }}\n selected={props.selectedAssets.some((a) => a.id === asset.id)}\n />\n ))}\n </Stack>\n )}\n </Box>\n </Dialog>\n )\n}\n\nexport default function ImportVideosFromMux() {\n const importAssets = useImportMuxAssets()\n\n if (!importAssets.hasSecrets) {\n return\n }\n\n if (importAssets.dialogOpen) {\n return <ImportVideosDialog {...importAssets} />\n }\n\n return <Button mode=\"bleed\" text=\"Import from Mux\" onClick={importAssets.openDialog} />\n}\n","import {ChevronLeftIcon} from '@sanity/icons/ChevronLeft'\nimport {ChevronRightIcon} from '@sanity/icons/ChevronRight'\nimport {Button, Label} from '@sanity/ui'\nimport {type Dispatch, type SetStateAction, useEffect} from 'react'\n\nconst PageSelector = (props: {\n page: number\n setPage: Dispatch<SetStateAction<number>>\n total: number\n}) => {\n const page = props.page\n const setPage = props.setPage\n\n useEffect(() => {\n // Constraint in bounds.\n const clamped = Math.min(props.total - 1, Math.max(0, page))\n if (page !== clamped) {\n setPage(clamped)\n }\n }, [page, props.total, setPage])\n\n return (\n <>\n <Button\n icon={ChevronLeftIcon}\n mode=\"bleed\"\n padding={3}\n style={{cursor: 'pointer'}}\n disabled={page <= 0}\n onClick={() => {\n setPage((p) => {\n return Math.min(props.total - 1, Math.max(0, p - 1))\n })\n }}\n />\n <Label muted>\n Page {page + 1}/{props.total}\n </Label>\n <Button\n icon={ChevronRightIcon}\n mode=\"bleed\"\n padding={3}\n style={{cursor: 'pointer'}}\n disabled={page >= props.total - 1}\n onClick={() => {\n setPage((p) => {\n return Math.min(props.total - 1, Math.max(0, p + 1))\n })\n }}\n />\n </>\n )\n}\n\nexport default PageSelector\n","import type {MuxAsset} from './types'\n\n/**\n * Adds a `_key` to array items in MuxAsset data (Sanity requires `_key` on array\n * items). Keys are derived from each item's stable Mux `id`, so repeated calls\n * are idempotent and don't churn the document — important because the asset is\n * persisted on every poll while it prepares.\n */\nexport function addKeysToMuxData(data: MuxAsset): MuxAsset {\n return {\n ...data,\n tracks: data.tracks?.map((track, index) => ({\n ...track,\n _key: track.id || `track-${index}`,\n })),\n playback_ids: data.playback_ids?.map((playbackId, index) => ({\n ...playbackId,\n _key: playbackId.id || `playback-${index}`,\n })),\n static_renditions: data.static_renditions\n ? {\n ...data.static_renditions,\n files: data.static_renditions.files?.map((file, index) => ({\n ...file,\n _key: file.id || `rendition-${index}`,\n })),\n }\n : undefined,\n }\n}\n","import {useMemo, useState} from 'react'\nimport {createHookFromObservableFactory, type DocumentStore, useDocumentStore} from 'sanity'\n\nimport {addKeysToMuxData} from '../util/addKeysToMuxData'\nimport {isEmptyOrPlaceholderTitle} from '../util/assetTitlePlaceholder'\nimport type {VideoAssetDocument} from '../util/types'\nimport {SANITY_API_VERSION, useClient} from './useClient'\nimport useMuxAssets from './useMuxAssets'\nimport {useSecretsDocumentValues} from './useSecretsDocumentValues'\n\ntype ResyncState = 'closed' | 'idle' | 'syncing' | 'done' | 'error'\n\nexport default function useResyncMuxMetadata() {\n const documentStore = useDocumentStore()\n const client = useClient()\n\n const [sanityAssets, sanityAssetsLoading] = useSanityAssets(documentStore)\n\n const secretDocumentValues = useSecretsDocumentValues()\n const hasSecrets = !!secretDocumentValues.value.secrets?.secretKey\n\n const [resyncError, setResyncError] = useState<unknown>()\n const [resyncState, setResyncState] = useState<ResyncState>('closed')\n const dialogOpen = resyncState !== 'closed'\n\n const muxAssets = useMuxAssets({\n client,\n enabled: hasSecrets && dialogOpen,\n })\n\n const matchedAssets = useMemo(() => {\n return sanityAssets && muxAssets.data\n ? sanityAssets.map((sanityDoc) => {\n const muxAsset = muxAssets.data?.find(\n (m) => m.id === sanityDoc.assetId || m.id === sanityDoc.data?.id,\n )\n return {\n sanityDoc,\n muxAsset,\n muxTitle: muxAsset?.meta?.title,\n currentTitle: sanityDoc.filename,\n }\n })\n : undefined\n }, [sanityAssets, muxAssets.data])\n\n const closeDialog = () => {\n if (resyncState !== 'syncing') setResyncState('closed')\n }\n\n const openDialog = () => {\n if (resyncState === 'closed') setResyncState('idle')\n }\n\n async function syncAllVideos() {\n if (!matchedAssets) return\n\n setResyncState('syncing')\n\n try {\n const tx = client.transaction()\n\n matchedAssets.forEach((matched) => {\n // Update all videos with the Mux title, even if it's undefined/empty\n const newTitle = matched.muxTitle || ''\n tx.patch(matched.sanityDoc._id, {set: {filename: newTitle}})\n })\n\n await tx.commit({returnDocuments: false})\n setResyncState('done')\n } catch (error) {\n setResyncState('error')\n setResyncError(error)\n }\n }\n\n async function syncOnlyEmpty() {\n if (!matchedAssets) return\n\n setResyncState('syncing')\n\n try {\n const tx = client.transaction()\n\n matchedAssets.forEach((matched) => {\n // Only update if the current title is empty or has the placeholder format\n // AND there's a new title available from Mux\n if (\n matched.muxAsset &&\n matched.muxTitle &&\n isEmptyOrPlaceholderTitle(matched.currentTitle, matched.muxAsset.id)\n ) {\n tx.patch(matched.sanityDoc._id, {set: {filename: matched.muxTitle}})\n }\n })\n\n await tx.commit({returnDocuments: false})\n setResyncState('done')\n } catch (error) {\n setResyncState('error')\n setResyncError(error)\n }\n }\n\n async function syncFullData() {\n if (!matchedAssets) return\n\n setResyncState('syncing')\n\n try {\n const tx = client.transaction()\n\n matchedAssets.forEach((matched) => {\n if (!matched.muxAsset) return\n\n const dataWithKeys = addKeysToMuxData(matched.muxAsset)\n\n // Update all fields: filename, status, and full data from Mux\n tx.patch(matched.sanityDoc._id, {\n set: {\n filename: matched.muxTitle || matched.currentTitle || '',\n status: matched.muxAsset.status,\n data: dataWithKeys,\n },\n })\n })\n\n await tx.commit({returnDocuments: false})\n setResyncState('done')\n } catch (error) {\n setResyncState('error')\n setResyncError(error)\n }\n }\n\n return {\n sanityAssetsLoading,\n closeDialog,\n dialogOpen,\n resyncState,\n resyncError,\n hasSecrets,\n syncAllVideos,\n syncOnlyEmpty,\n syncFullData,\n matchedAssets,\n muxAssets,\n openDialog,\n }\n}\n\nconst useSanityAssets = createHookFromObservableFactory<VideoAssetDocument[], DocumentStore>(\n (documentStore) => {\n return documentStore.listenQuery(\n /* groq */ `*[_type == \"mux.videoAsset\"]`,\n {},\n {\n apiVersion: SANITY_API_VERSION,\n },\n )\n },\n)\n","import {CheckmarkCircleIcon} from '@sanity/icons/CheckmarkCircle'\nimport {ErrorOutlineIcon} from '@sanity/icons/ErrorOutline'\nimport {SyncIcon} from '@sanity/icons/Sync'\nimport {Box, Button, Card, Dialog, Flex, Heading, Radio, Spinner, Stack, Text} from '@sanity/ui'\nimport {useState} from 'react'\n\nimport useResyncMuxMetadata from '../hooks/useResyncMuxMetadata'\nimport {isEmptyOrPlaceholderTitle} from '../util/assetTitlePlaceholder'\nimport {DIALOGS_Z_INDEX} from '../util/constants'\n\ntype SyncOption = 'fillEmpty' | 'syncTitles' | 'fullResync'\n\ninterface OptionCardProps {\n id: SyncOption\n selected: boolean\n onSelect: (id: SyncOption) => void\n title: string\n count: number\n description: string\n disabled?: boolean\n}\n\nfunction OptionCard({\n id,\n selected,\n onSelect,\n title,\n count,\n description,\n disabled,\n}: OptionCardProps) {\n return (\n <Card\n as=\"label\"\n padding={3}\n radius={2}\n border\n tone={selected ? 'primary' : 'default'}\n style={{\n cursor: disabled ? 'not-allowed' : 'pointer',\n opacity: disabled ? 0.5 : 1,\n }}\n >\n <Flex gap={3} align=\"flex-start\">\n <Box paddingTop={1}>\n <Radio\n checked={selected}\n onChange={() => onSelect(id)}\n disabled={disabled}\n name=\"sync-option\"\n />\n </Box>\n <Stack gap={2} flex={1}>\n <Flex align=\"center\" gap={2}>\n <Text size={2} weight=\"semibold\">\n {title} ({count})\n </Text>\n </Flex>\n <Text size={1} muted>\n {description}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )\n}\n\nfunction ResyncMetadataDialog(props: ReturnType<typeof useResyncMuxMetadata>) {\n const {resyncState} = props\n\n const videosToUpdate = props.matchedAssets?.filter((m) => m.muxAsset).length || 0\n const videosWithEmptyOrPlaceholder =\n props.matchedAssets?.filter(\n (m) => m.muxAsset && m.muxTitle && isEmptyOrPlaceholderTitle(m.currentTitle, m.muxAsset.id),\n ).length || 0\n\n const hasEmptyTitles = videosWithEmptyOrPlaceholder > 0\n const defaultOption: SyncOption = hasEmptyTitles ? 'fillEmpty' : 'syncTitles'\n const [selectedOption, setSelectedOption] = useState<SyncOption>(defaultOption)\n\n const canTriggerResync = resyncState === 'idle' || resyncState === 'error'\n const isResyncing = resyncState === 'syncing'\n const isDone = resyncState === 'done'\n const isLoading = props.muxAssets.loading || props.sanityAssetsLoading\n\n const handleSync = () => {\n switch (selectedOption) {\n case 'fillEmpty':\n void props.syncOnlyEmpty()\n break\n case 'syncTitles':\n void props.syncAllVideos()\n break\n case 'fullResync':\n void props.syncFullData()\n break\n default:\n break\n }\n }\n\n return (\n <Dialog\n animate\n header=\"Sync with Mux\"\n zOffset={DIALOGS_Z_INDEX}\n id=\"resync-metadata-dialog\"\n onClose={props.closeDialog}\n onClickOutside={props.closeDialog}\n width={1}\n position=\"fixed\"\n footer={\n !isDone && (\n <Card padding={3}>\n <Flex justify=\"flex-end\" gap={2}>\n <Button\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Cancel\"\n onClick={props.closeDialog}\n disabled={isResyncing}\n />\n <Button\n icon={SyncIcon}\n fontSize={2}\n padding={3}\n text=\"Run sync\"\n tone=\"primary\"\n onClick={handleSync}\n iconRight={isResyncing && Spinner}\n disabled={!canTriggerResync || isLoading}\n />\n </Flex>\n </Card>\n )\n }\n >\n <Box padding={4}>\n {/* LOADING ASSETS STATE */}\n {isLoading && (\n <Card tone=\"primary\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Loading assets from Mux\n </Text>\n <Text size={1} muted>\n This may take a while.\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR LOADING MUX */}\n {props.muxAssets.error && (\n <Card tone=\"critical\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error getting data from Mux\n </Text>\n <Text size={1}>Please try again or contact a developer for help.</Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* SYNCING STATE */}\n {resyncState === 'syncing' && (\n <Card tone=\"primary\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={4}>\n <Spinner muted size={4} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n Syncing metadata\n </Text>\n <Text size={1} muted>\n Updating videos from Mux...\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* ERROR SYNCING */}\n {resyncState === 'error' && (\n <Card tone=\"critical\" marginBottom={4} padding={3} border radius={2}>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon fontSize={36} />\n <Stack gap={2}>\n <Text size={2} weight=\"semibold\">\n There was an error syncing metadata\n </Text>\n <Text size={1}>\n {props.resyncError\n ? `Error: ${props.resyncError}`\n : 'Please try again or contact a developer for help.'}\n </Text>\n </Stack>\n </Flex>\n </Card>\n )}\n\n {/* SUCCESS STATE */}\n {resyncState === 'done' && (\n <Stack paddingY={5} gap={3} style={{textAlign: 'center'}}>\n <Box>\n <CheckmarkCircleIcon fontSize={48} />\n </Box>\n <Heading size={2}>Sync completed</Heading>\n <Text size={2} muted>\n Videos have been updated from Mux.\n </Text>\n </Stack>\n )}\n\n {/* OPTIONS */}\n {!isDone && !isLoading && !props.muxAssets.error && (\n <Stack gap={4}>\n <Text size={1} muted>\n Found {videosToUpdate} video{videosToUpdate === 1 ? '' : 's'} linked to Mux.\n </Text>\n\n <Stack gap={3}>\n {hasEmptyTitles && (\n <OptionCard\n id=\"fillEmpty\"\n selected={selectedOption === 'fillEmpty'}\n onSelect={setSelectedOption}\n title=\"Fill missing titles only\"\n count={videosWithEmptyOrPlaceholder}\n description=\"Updates only videos without a title or with placeholder titles (e.g., 'Asset #123') using the title from Mux.\"\n disabled={isResyncing}\n />\n )}\n\n <OptionCard\n id=\"syncTitles\"\n selected={selectedOption === 'syncTitles'}\n onSelect={setSelectedOption}\n title=\"Sync all titles\"\n count={videosToUpdate}\n description=\"Replaces the title in Sanity with the title from Mux for all videos.\"\n disabled={isResyncing}\n />\n\n <OptionCard\n id=\"fullResync\"\n selected={selectedOption === 'fullResync'}\n onSelect={setSelectedOption}\n title=\"Full resync\"\n count={videosToUpdate}\n description=\"Updates all fields from Mux including status, duration, tracks, captions, and renditions.\"\n disabled={isResyncing}\n />\n </Stack>\n </Stack>\n )}\n </Box>\n </Dialog>\n )\n}\n\nexport default function ResyncMetadata() {\n const resyncMetadata = useResyncMuxMetadata()\n\n if (!resyncMetadata.hasSecrets) {\n return\n }\n\n if (resyncMetadata.dialogOpen) {\n return <ResyncMetadataDialog {...resyncMetadata} />\n }\n\n return <Button mode=\"bleed\" text=\"Sync with Mux\" onClick={resyncMetadata.openDialog} />\n}\n","import {SortIcon} from '@sanity/icons/Sort'\nimport {Button} from '@sanity/ui'\nimport {Menu, MenuButton, MenuItem} from '@sanity/ui/menu'\nimport {type PopoverProps} from '@sanity/ui/popover'\nimport {useId} from 'react'\n\nimport {ASSET_SORT_OPTIONS, type SortOption} from '../hooks/useAssets'\n\nconst CONTEXT_MENU_POPOVER_PROPS: PopoverProps = {\n constrainSize: true,\n placement: 'bottom',\n portal: true,\n width: 0,\n}\n\n/**\n * @sanity/ui components adapted from:\n * https://github.com/sanity-io/sanity/blob/next/packages/sanity/src/desk/components/pane/PaneContextMenuButton.tsx#L19\n */\nexport function SelectSortOptions(props: {sort: SortOption; setSort: (s: SortOption) => void}) {\n const id = useId()\n\n return (\n <MenuButton\n button={\n <Button text=\"Sort\" icon={SortIcon} mode=\"bleed\" padding={3} style={{cursor: 'pointer'}} />\n }\n id={id}\n menu={\n <Menu>\n {Object.entries(ASSET_SORT_OPTIONS).map(([type, {label}]) => (\n <MenuItem\n key={type}\n data-as=\"button\"\n onClick={() => props.setSort(type as SortOption)}\n padding={3}\n tone=\"default\"\n text={label}\n pressed={type === props.sort}\n />\n ))}\n </Menu>\n }\n popover={CONTEXT_MENU_POPOVER_PROPS}\n />\n )\n}\n","import {Box, Spinner} from '@sanity/ui'\n\nconst SpinnerBox: React.FC = () => (\n <Box\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: '150px',\n }}\n >\n <Spinner />\n </Box>\n)\n\nexport default SpinnerBox\n","import {Flex, Text} from '@sanity/ui'\n\nconst IconInfo: React.FC<{\n text: string\n icon: React.FC\n size?: number\n muted?: boolean\n}> = (props) => {\n const Icon = props.icon\n return (\n <Flex gap={2} align=\"center\" padding={1}>\n <Text size={(props.size || 1) + 1} muted>\n <Icon />\n </Text>\n <Text size={props.size || 1} muted={props.muted}>\n {props.text}\n </Text>\n </Flex>\n )\n}\n\nexport default IconInfo\n","import type {SVGProps} from 'react'\n\nexport function ResolutionIcon(props: SVGProps<SVGSVGElement>) {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\" {...props}>\n <path\n fill=\"currentColor\"\n d=\"M20 9V6h-3V4h5v5h-2ZM2 9V4h5v2H4v3H2Zm15 11v-2h3v-3h2v5h-5ZM2 20v-5h2v3h3v2H2Zm4-4V8h12v8H6Zm2-2h8v-4H8v4Zm0 0v-4v4Z\"\n />\n </svg>\n )\n}\n","import type {SVGProps} from 'react'\n\nexport function StopWatchIcon(props: SVGProps<SVGSVGElement>) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 512 512\"\n {...props}\n >\n <path d=\"M232 306.667h48V176h-48v130.667z\" fill=\"currentColor\" />\n <path\n d=\"M407.67 170.271l30.786-30.786-33.942-33.941-30.785 30.786C341.217 111.057 300.369 96 256 96 149.961 96 64 181.961 64 288s85.961 192 192 192 192-85.961 192-192c0-44.369-15.057-85.217-40.33-117.729zm-45.604 223.795C333.734 422.398 296.066 438 256 438s-77.735-15.602-106.066-43.934C121.602 365.735 106 328.066 106 288s15.602-77.735 43.934-106.066C178.265 153.602 215.934 138 256 138s77.734 15.602 106.066 43.934C390.398 210.265 406 247.934 406 288s-15.602 77.735-43.934 106.066z\"\n fill=\"currentColor\"\n />\n <path d=\"M192 32h128v48H192z\" fill=\"currentColor\" />\n </svg>\n )\n}\n","import {useToast} from '@sanity/ui/toast'\nimport {useCallback, useEffect, useMemo, useState} from 'react'\n\nimport {getAsset, updateMasterAccess} from '../actions/assets'\nimport {addKeysToMuxData} from '../util/addKeysToMuxData'\nimport type {MuxAsset, VideoAssetDocument} from '../util/types'\nimport {useClient} from './useClient'\n\n/**\n * UI status for the mezzanine (\"master access\") file of a Mux asset, derived\n * solely from the stored `master` object.\n * - `disabled`: master access is not enabled (or reverted to `none`).\n * - `preparing`: Mux is preparing the file (we poll until it's ready).\n * - `ready`: the file is ready to download.\n * - `errored`: Mux failed to prepare the file.\n */\nexport type MezzanineStatus = 'disabled' | 'preparing' | 'ready' | 'errored'\n\n// Poll cadence while the mezzanine is preparing.\nconst POLL_INTERVAL_MS = 3000\n\nexport interface UseMezzanineReturn {\n status: MezzanineStatus\n /** `true` while an enable or pre-download check request is in flight. */\n busy: boolean\n /**\n * `true` when the last download attempt found the file gone (the 24h window\n * elapsed). Used to show a \"enable it again\" hint; the button state still\n * comes from `status`.\n */\n expired: boolean\n /** Mezzanine resolution label (e.g. `1080p`), when known. */\n resolution?: string\n /** Enables master access and starts polling until the file is ready. */\n enable: () => Promise<void>\n /** Re-fetches the asset and, if the file is still alive, triggers the download. */\n download: () => Promise<void>\n}\n\n/** Derives the mezzanine status from the persisted asset data alone (no polling or local state). */\nexport function getMezzanineStatus(\n asset: VideoAssetDocument,\n): 'disabled' | 'preparing' | 'ready' | 'errored' {\n const master = asset.data?.master\n if (master?.status === 'preparing') return 'preparing'\n if (master?.status === 'ready' && master.url) return 'ready'\n if (master?.status === 'errored') return 'errored'\n return 'disabled'\n}\n\n/**\n * Encapsulates the mezzanine (Mux \"master access\") lifecycle for an asset:\n * enabling it through the Mux addon proxy, persisting the result on the Sanity\n * document, polling until it's ready, and downloading by redirecting to the\n * fresh, short-lived Mux URL.\n *\n * The full Mux asset `data` (including the `master` object) is stored on the\n * Sanity document via `client.patch`, so the status survives reloads and is\n * already present for assets imported from Mux.\n */\nexport function useMezzanine(asset: VideoAssetDocument): UseMezzanineReturn {\n const client = useClient()\n const toast = useToast()\n\n const master = asset.data?.master\n const [busy, setBusy] = useState(false)\n const [expired, setExpired] = useState(false)\n // Track the previous assetId so we can reset transient flags during render\n // when the asset changes, without triggering a cascading setState-in-effect.\n const [prevAssetId, setPrevAssetId] = useState(asset.assetId)\n if (prevAssetId !== asset.assetId) {\n setPrevAssetId(asset.assetId)\n setExpired(false)\n }\n\n const resolution = useMemo(\n () => asset.data?.max_resolution_tier || asset.data?.max_stored_resolution || undefined,\n [asset.data?.max_resolution_tier, asset.data?.max_stored_resolution],\n )\n\n const status: MezzanineStatus = getMezzanineStatus(asset)\n\n // Persist a Mux asset payload on the Sanity document.\n const persist = useCallback(\n async (data: MuxAsset) => {\n if (!asset._id) return\n await client\n .patch(asset._id)\n .set({status: data.status, data: addKeysToMuxData(data)})\n .commit({returnDocuments: false})\n },\n [asset._id, client],\n )\n\n // Fetch the latest asset from Mux (through the proxy) and persist it on the Sanity document.\n const refresh = useCallback(async (): Promise<MuxAsset | undefined> => {\n if (!asset.assetId || !asset._id) return undefined\n const {data} = await getAsset(client, asset.assetId)\n await persist(data)\n return data\n }, [asset.assetId, asset._id, client, persist])\n\n // Poll while the mezzanine is preparing; stop once it's ready or no longer preparing.\n useEffect(() => {\n if (master?.status !== 'preparing' || !asset.assetId || !asset._id) return undefined\n\n let cancelled = false\n let running = false\n const interval = setInterval(async () => {\n // Skip this tick if the previous refresh hasn't finished, so a slow\n // request can't pile up overlapping reads/writes.\n if (running) return\n running = true\n try {\n const data = await refresh()\n if (cancelled) return\n if (!data || data.master?.status !== 'preparing') {\n clearInterval(interval)\n }\n } catch (error) {\n console.error('Failed to poll mezzanine status:', error)\n // oxlint-disable-next-line react/todo\n } finally {\n running = false\n }\n }, POLL_INTERVAL_MS)\n\n return () => {\n cancelled = true\n clearInterval(interval)\n }\n }, [master?.status, asset.assetId, asset._id, refresh])\n\n const enable = useCallback(async () => {\n if (!asset.assetId || !asset._id) return\n\n setBusy(true)\n setExpired(false)\n try {\n const {data} = await updateMasterAccess(client, asset.assetId, 'temporary')\n // Persist the PUT response directly — it already reports master.status\n // 'preparing', so polling starts without relying on a follow-up GET that\n // could read stale data and miss it.\n await persist(data)\n } catch (error) {\n toast.push({\n status: 'error',\n title: 'Could not enable the mezzanine file',\n description: error instanceof Error ? error.message : 'Please try again',\n })\n // oxlint-disable-next-line react/todo\n } finally {\n setBusy(false)\n }\n }, [asset.assetId, asset._id, client, persist, toast])\n\n const download = useCallback(async () => {\n if (!asset.assetId) return\n\n setBusy(true)\n try {\n // The Mux URL is short-lived (24h), so re-fetch the asset right before\n // downloading and only redirect if the file is still alive.\n const data = await refresh()\n const url = data?.master?.status === 'ready' ? data.master.url : undefined\n\n if (url) {\n setExpired(false)\n triggerMezzanineDownload(url)\n } else {\n // The window elapsed and master_access reverted: prompt to re-enable.\n setExpired(true)\n }\n } catch (error) {\n toast.push({\n status: 'error',\n title: 'Could not download the mezzanine file',\n description: error instanceof Error ? error.message : 'Please try again',\n })\n // oxlint-disable-next-line react/todo\n } finally {\n setBusy(false)\n }\n }, [asset.assetId, refresh, toast])\n\n return {status, busy, expired, resolution, enable, download}\n}\n\n/**\n * Redirects the browser to the Mux mezzanine URL to start the download. The URL\n * already serves the file with its default name (`mezzanine.mp4`).\n * @see {@link https://www.mux.com/docs/guides/download-for-offline-editing}\n */\nfunction triggerMezzanineDownload(masterUrl: string): void {\n if (typeof window === 'undefined') return\n\n const anchor = document.createElement('a')\n anchor.href = masterUrl\n anchor.target = '_blank'\n anchor.rel = 'noopener noreferrer'\n document.body.appendChild(anchor)\n anchor.click()\n document.body.removeChild(anchor)\n}\n","import {Stack, Text} from '@sanity/ui'\n\n/** Explains what the mezzanine file is and how it differs from the streamable MP4 renditions. */\nexport default function MezzanineExplanation() {\n return (\n <Stack gap={3}>\n <Text size={1} muted>\n When you enable the mezzanine file, Mux creates a copy equivalent in quality to your\n original video — ideal for offline editing or archiving. Unlike the streamable MP4 (static)\n renditions, it is not meant for streaming.\n </Text>\n <Text size={1} muted>\n The file is prepared in the background and may take a few minutes depending on the\n asset's duration and resolution. Enabling is free and the download stays available for\n 24 hours.\n </Text>\n </Stack>\n )\n}\n","import {DownloadIcon} from '@sanity/icons/Download'\nimport {Button, Card, Flex, Label, Spinner, Stack, Text} from '@sanity/ui'\n\nimport {useMezzanine} from '../hooks/useMezzanine'\nimport {MEZZANINE_LEARN_MORE_URL} from '../util/constants'\nimport type {VideoAssetDocument} from '../util/types'\nimport MezzanineExplanation from './MezzanineExplanation'\n\nexport interface Props {\n asset: VideoAssetDocument\n /**\n * Render the mezzanine explanation copy inside the card.\n * @defaultValue true\n */\n withExplanation?: boolean\n}\n\n/**\n * \"Mezzanine\" panel, modeled after Mux's dashboard card: enable the\n * master-access copy, watch it prepare, then download it.\n */\nexport default function Mezzanine({asset, withExplanation = true}: Props) {\n const {status, busy, expired, resolution, enable, download} = useMezzanine(asset)\n\n const assetReady = asset.status === 'ready' || asset.data?.status === 'ready'\n // Once a download finds the file gone, treat it as not-ready even if the\n // (stale) asset prop still reports `ready`, so we show the re-enable path\n // instead of a dead Download button.\n const isReady = status === 'ready' && !expired\n const isPreparing = status === 'preparing'\n const showExplanation = !isReady && !isPreparing\n\n return (\n <Card padding={3} radius={2} tone=\"transparent\" border>\n <Stack gap={4}>\n <Flex align=\"center\" justify=\"space-between\" gap={3}>\n <Label muted size={1}>\n Mezzanine\n </Label>\n <Text size={1}>\n <a href={MEZZANINE_LEARN_MORE_URL} target=\"_blank\" rel=\"noopener noreferrer\">\n Learn more\n </a>\n </Text>\n </Flex>\n\n <Stack gap={2}>\n <Text size={1} muted={!isReady}>\n mezzanine.mp4\n </Text>\n {resolution && (\n <Text size={1} muted>\n {resolution}\n </Text>\n )}\n </Stack>\n\n {withExplanation && showExplanation && <MezzanineExplanation />}\n\n {showExplanation && (expired || status === 'errored') && (\n <Stack gap={2}>\n {expired && (\n <Text size={1} muted>\n The previous mezzanine file expired. Enable it again to download.\n </Text>\n )}\n {status === 'errored' && (\n <Text size={1} style={{color: 'var(--card-critical-color)'}}>\n Mux could not prepare the mezzanine file. Please try again.\n </Text>\n )}\n </Stack>\n )}\n\n {isPreparing && (\n <Text size={1} muted>\n Preparing the mezzanine file… this can take a few minutes. You can close this and come\n back later.\n </Text>\n )}\n\n {isReady && (\n <Text size={1} muted>\n Ready to download. The link stays available for about 24 hours.\n </Text>\n )}\n\n <Flex justify=\"flex-end\" gap={2}>\n {isPreparing ? (\n <Flex align=\"center\" gap={2}>\n <Spinner muted size={1} />\n <Text size={1} muted>\n Preparing…\n </Text>\n </Flex>\n ) : isReady ? (\n <Button\n icon={DownloadIcon}\n text=\"Download\"\n tone=\"positive\"\n fontSize={1}\n padding={3}\n loading={busy}\n disabled={busy}\n onClick={() => void download()}\n />\n ) : (\n <Button\n text={status === 'errored' ? 'Try again' : 'Enable'}\n tone=\"primary\"\n fontSize={1}\n padding={3}\n loading={busy}\n disabled={busy || !assetReady}\n onClick={() => void enable()}\n />\n )}\n </Flex>\n </Stack>\n </Card>\n )\n}\n","import {useToast} from '@sanity/ui/toast'\nimport {useCallback, useState} from 'react'\n\nimport {getAsset} from '../actions/assets'\nimport {addKeysToMuxData} from '../util/addKeysToMuxData'\nimport type {MuxAsset, VideoAssetDocument} from '../util/types'\nimport {useClient} from './useClient'\n\ntype ResyncAssetState = 'idle' | 'syncing' | 'success' | 'error'\n\ninterface UseResyncAssetOptions {\n showToast?: boolean\n onSuccess?: (updatedData: MuxAsset) => void\n onError?: (error: unknown) => void\n}\n\ninterface UseResyncAssetReturn {\n resyncState: ResyncAssetState\n resyncError: unknown\n resyncAsset: (asset: VideoAssetDocument) => Promise<MuxAsset | undefined>\n isResyncing: boolean\n}\n\nexport function useResyncAsset(options?: UseResyncAssetOptions): UseResyncAssetReturn {\n const client = useClient()\n const toast = useToast()\n const [resyncState, setResyncState] = useState<ResyncAssetState>('idle')\n const [resyncError, setResyncError] = useState<unknown>(null)\n\n const showToast = options?.showToast ?? false\n\n const resyncAsset = useCallback(\n async (asset: VideoAssetDocument) => {\n if (!asset.assetId) {\n if (showToast) {\n toast.push({\n title: 'Cannot resync',\n description: 'Asset has no Mux ID',\n status: 'error',\n })\n }\n options?.onError?.(new Error('Asset has no Mux ID'))\n return undefined\n }\n\n if (!asset._id) {\n if (showToast) {\n toast.push({\n title: 'Cannot resync',\n description: 'Asset has no document ID',\n status: 'error',\n })\n }\n options?.onError?.(new Error('Asset has no document ID'))\n return undefined\n }\n\n setResyncState('syncing')\n setResyncError(null)\n\n try {\n const response = await getAsset(client, asset.assetId)\n const muxData = response.data\n const dataWithKeys = addKeysToMuxData(muxData)\n\n await client\n .patch(asset._id)\n .set({\n status: muxData.status,\n data: dataWithKeys,\n ...(muxData.meta?.title && {filename: muxData.meta.title}),\n })\n .commit({returnDocuments: false})\n\n setResyncState('success')\n if (showToast) {\n toast.push({\n title: 'Asset synced',\n description: 'Data has been updated from Mux',\n status: 'success',\n })\n }\n\n options?.onSuccess?.(muxData)\n return muxData\n } catch (error) {\n setResyncState('error')\n setResyncError(error)\n console.error('Failed to refresh asset data:', error)\n if (showToast) {\n toast.push({\n title: 'Sync failed',\n description: 'Could not sync asset from Mux',\n status: 'error',\n })\n }\n options?.onError?.(error)\n return undefined\n }\n },\n [client, toast, options, showToast],\n )\n\n return {\n resyncState,\n resyncError,\n resyncAsset,\n isResyncing: resyncState === 'syncing',\n }\n}\n","import type {SanityClient} from '@sanity/client'\n\nimport {getAsset} from '../actions/assets'\nimport {generateJwt} from './generateJwt'\nimport {getPlaybackId} from './getPlaybackPolicy'\nimport {getPlaybackPolicy} from './getPlaybackPolicy'\nimport type {MuxTextTrack, VideoAssetDocument} from './types'\n\nexport function extractErrorMessage(\n error: unknown,\n defaultMessage = 'Failed to process request',\n): string {\n let message = ''\n\n if (error && typeof error === 'object') {\n const err = error as {response?: {body?: {message?: string}}; message?: string}\n message = err.response?.body?.message || err.message || ''\n } else if (typeof error === 'string') {\n message = error\n }\n\n if (!message) {\n return defaultMessage\n }\n\n const match = message.match(/\\(([^)]+)\\)/)\n if (match && match[1]) {\n return match[1]\n }\n\n if (message.includes('responded with')) {\n const parts = message.split('(')\n if (parts.length > 1) {\n return parts[parts.length - 1]!.replace(')', '').trim()\n }\n }\n\n return message\n}\n\nexport interface PollTrackStatusOptions {\n client: SanityClient\n assetId: string\n trackName: string\n trackLanguageCode: string\n maxAttempts?: number\n onTrackFound?: (track: MuxTextTrack) => void\n onTrackErrored?: (track: MuxTextTrack) => void\n onTrackReady?: (track: MuxTextTrack) => void\n}\n\nexport interface PollTrackStatusResult {\n track: MuxTextTrack | undefined\n found: boolean\n status: 'ready' | 'preparing' | 'errored' | 'not-found'\n}\n\n/**\n * Polls Mux API to find and track the status of a newly added text track.\n * The track may be in \"preparing\" state initially, then become \"ready\" or \"errored\".\n *\n * @param options - Configuration options for polling\n * @returns Promise resolving to the poll result\n */\nexport async function pollTrackStatus(\n options: PollTrackStatusOptions,\n): Promise<PollTrackStatusResult> {\n const {\n client,\n assetId,\n trackName,\n trackLanguageCode,\n maxAttempts = 10,\n onTrackFound,\n onTrackErrored,\n onTrackReady,\n } = options\n\n const trimmedName = trackName.trim()\n const trimmedLanguageCode = trackLanguageCode.trim()\n let newTrack: MuxTextTrack | undefined\n let attempts = 0\n let trackFound = false\n\n const findTrack = (textTracks: MuxTextTrack[]): MuxTextTrack | undefined => {\n let foundTrack = textTracks.find(\n (track) => track.name === trimmedName && track.language_code === trimmedLanguageCode,\n )\n\n if (!foundTrack) {\n foundTrack = textTracks.find((track) => track.language_code === trimmedLanguageCode)\n }\n\n if (!foundTrack && textTracks.length > 0) {\n foundTrack = textTracks[textTracks.length - 1]\n }\n\n return foundTrack\n }\n\n while (attempts < maxAttempts) {\n try {\n if (attempts > 0) {\n await new Promise((resolve) => setTimeout(resolve, 1000))\n }\n\n const assetData = await getAsset(client, assetId)\n const textTracks =\n assetData.data.tracks?.filter((track): track is MuxTextTrack => track.type === 'text') || []\n\n const foundTrack = findTrack(textTracks)\n\n if (!foundTrack) {\n attempts++\n continue\n }\n\n trackFound = true\n newTrack = foundTrack\n\n if (onTrackFound) {\n onTrackFound(foundTrack)\n }\n\n if (foundTrack.status === 'ready') {\n if (onTrackReady) {\n onTrackReady(foundTrack)\n }\n break\n }\n\n if (foundTrack.status === 'errored') {\n if (onTrackErrored) {\n onTrackErrored(foundTrack)\n }\n return {\n track: foundTrack,\n found: true,\n status: 'errored',\n }\n }\n } catch (error) {\n console.error('Failed to fetch updated asset:', error)\n }\n\n attempts++\n }\n\n if (!newTrack || !trackFound) {\n return {\n track: undefined,\n found: false,\n status: 'not-found',\n }\n }\n\n if (newTrack.status === 'preparing') {\n return {\n track: newTrack,\n found: true,\n status: 'preparing',\n }\n }\n\n return {\n track: newTrack,\n found: true,\n status: 'ready',\n }\n}\n\n/**\n * May throw a Promise. Call this with {@link tryWithSuspend} or rethrow the Promise\n */\nexport async function downloadVttFile(\n client: SanityClient,\n asset: VideoAssetDocument,\n track: MuxTextTrack,\n): Promise<void> {\n if (!track.id) {\n throw new Error('Track ID is missing')\n }\n\n if (track.status !== 'ready') {\n throw new Error(`Track is not ready yet. Status: ${track.status}`)\n }\n\n if (!asset.assetId) {\n throw new Error('Asset ID is required')\n }\n\n const playbackId = getPlaybackId(asset)\n if (!playbackId) {\n throw new Error('Playback ID is required')\n }\n\n const playbackPolicy = getPlaybackPolicy(asset)?.policy\n\n let downloadUrl = `https://stream.mux.com/${playbackId}/text/${track.id}.vtt`\n\n if (playbackPolicy === 'signed' || playbackPolicy === 'drm') {\n const token = generateJwt(client, playbackId, 'v')\n downloadUrl += `?token=${token}`\n }\n\n const response = await fetch(downloadUrl)\n if (!response.ok) {\n throw new Error(`Failed to download file: ${response.statusText}`)\n }\n\n const blob = await response.blob()\n const blobUrl = URL.createObjectURL(blob)\n\n const link = document.createElement('a')\n link.href = blobUrl\n link.download = `${asset.filename || 'captions'}-${track.language_code || 'en'}.vtt`\n document.body.appendChild(link)\n link.click()\n document.body.removeChild(link)\n\n URL.revokeObjectURL(blobUrl)\n}\n","import type MuxPlayerElement from '@mux/mux-player'\nimport type {ObjectInputProps} from 'sanity'\nimport type {PartialDeep} from 'type-fest'\n\n/**\n * All static rendition resolution options supported by Mux\n */\nexport type StaticRenditionResolution =\n | 'highest'\n | 'audio-only'\n | '270p'\n | '360p'\n | '480p'\n | '540p'\n | '720p'\n | '1080p'\n | '1440p'\n | '2160p'\n\nexport interface MuxInputConfig {\n /**\n * Enable static renditions by default. Can be overwritten on a per-asset basis.\n * Supports:\n * - Standard mode: 'highest' (up to 4K MP4) and/or 'audio-only' (M4A)\n * - Advanced mode: Specific resolutions ('270p', '360p', '480p', '540p', '720p', '1080p', '1440p', '2160p') and/or 'audio-only'\n *\n * **Important**: 'highest' cannot be mixed with specific resolutions. If both are provided, only 'highest' will be used.\n *\n * @see {@link https://docs.mux.com/guides/video/enable-static-mp4-renditions}\n * @defaultValue []\n */\n static_renditions: StaticRenditionResolution[]\n\n /**\n * @deprecated Use `static_renditions` instead. This field is kept for backward compatibility.\n * Enable static renditions by setting this to 'standard'. Can be overwritten on a per-asset basis.\n * Requires `\"video_quality\": \"plus\"`\n * @see {@link https://docs.mux.com/guides/video/enable-static-mp4-renditions#why-enable-mp4-support}\n * @defaultValue 'none'\n */\n mp4_support: 'none' | 'standard'\n\n /**\n * Max resolution tier can be used to control the maximum resolution_tier your asset is encoded, stored, and streamed at.\n * Requires `\"video_quality\": \"plus\"`\n * @see {@link https://docs.mux.com/guides/stream-videos-in-4k}\n * @defaultValue '1080p'\n */\n max_resolution_tier: '2160p' | '1440p' | '1080p'\n\n /**\n * @deprecated Use {@link video_quality}\n * <br>\n * The encoding tier informs the cost, quality, and available platform features for the asset.\n * @see {@link https://docs.mux.com/guides/use-encoding-tiers}\n * @defaultValue 'smart'\n */\n encoding_tier?: 'baseline' | 'smart'\n\n /**\n * The video quality level informs the cost, quality, and available platform features for the asset.\n * @see {@link https://www.mux.com/docs/guides/use-video-quality-levels}\n * @defaultValue 'plus'\n */\n video_quality: 'basic' | 'plus' | 'premium'\n\n /**\n * Normalize the audio track loudness level.\n * @see {@link https://docs.mux.com/guides/adjust-audio-levels#how-to-turn-on-audio-normalization}\n * @defaultValue false\n */\n normalize_audio: boolean\n\n /**\n * Enables signed URLs by default, if you configured them with your API token.\n * @see {@link https://docs.mux.com/guides/secure-video-playback}\n * @defaultValue false\n */\n defaultSigned?: boolean\n\n /**\n * Enables public URLs by default.\n * @defaultValue true\n */\n defaultPublic?: boolean\n\n /**\n * Enables DRM Protection by default, if you configured your DRM Configuration Id.\n * @see {@link https://www.mux.com/docs/guides/protect-videos-with-drm}\n * @defaultValue true\n */\n defaultDrm?: boolean\n\n /**\n * Auto-generate captions for these languages by default.\n * Requires `\"video_quality\": \"plus\"`\n *\n * @see {@link https://docs.mux.com/guides/add-autogenerated-captions-and-use-transcripts}\n * @deprecated use `defaultAutogeneratedSubtitleLang` instead. Only a single autogenerated\n */\n defaultAutogeneratedSubtitleLangs?: SupportedMuxLanguage[]\n\n /**\n * Auto-generate captions for this language by default. Users can still\n * Requires `\"video_quality\": \"plus\"`\n *\n * @see {@link https://docs.mux.com/guides/add-autogenerated-captions-and-use-transcripts}\n */\n defaultAutogeneratedSubtitleLang?: SupportedMuxLanguage\n\n /**\n * Whether or not to allow content editors to override asset upload\n * configuration settings when uploading a video to Mux.\n *\n * @see {@link https://docs.mux.com/guides/secure-video-playback}\n * @defaultValue false\n */\n disableUploadConfig?: boolean\n\n /**\n * Whether or not to allow content editors to add text tracks alongside their\n * asset when uploading a video to Mux.\n *\n * @see {@link https://docs.mux.com/guides/secure-video-playback}\n * @defaultValue false\n */\n disableTextTrackConfig?: boolean\n\n /**\n * Whether or not to show the playback warning when trying to watch DRM content for the first time.\n *\n * @defaultValue false\n */\n disableDrmPlaybackWarning?: boolean\n\n /**\n * The mime types that are accepted by the input.\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/accept}\n * @defaultValue ['video/*','audio/*']\n\n */\n acceptedMimeTypes?: ('audio/*' | 'video/*')[]\n\n /**\n * Maximum file size allowed for video uploads in bytes.\n * If not specified, no file size validation will be performed.\n *\n * @example 1024 * 1024 * 1024 // 1 GB\n * @defaultValue undefined\n */\n maxAssetFileSize?: number\n\n /**\n * Maximum video duration allowed in seconds.\n * If not specified, no duration validation will be performed.\n *\n * @example 2 * 60 * 60 // 2 hours\n * @defaultValue undefined\n */\n maxAssetDuration?: number\n\n /**\n * HLS.js configuration options to be passed to the Mux Player.\n * These options allow you to customize the underlying HLS.js playback engine behavior.\n *\n * @see {@link https://github.com/video-dev/hls.js/blob/master/docs/API.md#fine-tuning}\n * @defaultValue undefined\n * @example\n * ```ts\n * {\n * maxBufferLength: 30,\n * lowLatencyMode: true,\n * capLevelToPlayerSize: true\n * }\n * ```\n */\n hlsConfig?: MuxPlayerElement['_hlsConfig']\n}\n\nexport interface PluginConfig extends MuxInputConfig {\n /**\n * How the videos browser should appear as a studio tool in Sanity's top navigation\n *\n * Pass `false` if you want to disable it.\n * @defaultValue {title: 'Videos', icon: VideoIcon}\n **/\n tool:\n | false\n | {\n title?: string\n icon?: React.ComponentType\n }\n\n /**\n * The roles that are allowed to configure the plugin.\n *\n * If not set, all roles will be allowed to configure the plugin.\n * @defaultValue []\n */\n allowedRolesForConfiguration: string[]\n\n /**\n * Send only Mux addon requests (`/v<apiVersion>/addons/mux/...`) to this host, for example a\n * local development server. Content Lake requests (queries, listeners, asset documents)\n * still use the Studio API host.\n *\n * The host is used as-is: the plugin does not prepend the project id to it. If your server needs\n * the project id in the hostname, include it in the host, like `http://<projectId>.example.test:8000`.\n *\n * Auth: the Studio token (if any) is sent as `Authorization: Bearer`. Session cookies for the\n * Studio API host are not sent to a different host.\n *\n * @example 'http://127.0.0.1:8080'\n * @defaultValue undefined\n */\n muxApiHost?: string\n}\n\nexport const SUPPORTED_MUX_LANGUAGES = [\n {label: 'English', code: 'en', state: 'Stable'},\n {label: 'Spanish', code: 'es', state: 'Stable'},\n {label: 'Italian', code: 'it', state: 'Stable'},\n {label: 'Portuguese', code: 'pt', state: 'Stable'},\n {label: 'German', code: 'de', state: 'Stable'},\n {label: 'French', code: 'fr', state: 'Stable'},\n {label: 'Polish', code: 'pl', state: 'Beta'},\n {label: 'Russian', code: 'ru', state: 'Beta'},\n {label: 'Dutch', code: 'nl', state: 'Beta'},\n {label: 'Catalan', code: 'ca', state: 'Beta'},\n {label: 'Turkish', code: 'tr', state: 'Beta'},\n {label: 'Swedish', code: 'sv', state: 'Beta'},\n {label: 'Ukrainian', code: 'uk', state: 'Beta'},\n {label: 'Norwegian', code: 'no', state: 'Beta'},\n {label: 'Finnish', code: 'fi', state: 'Beta'},\n {label: 'Slovak', code: 'sk', state: 'Beta'},\n {label: 'Greek', code: 'el', state: 'Beta'},\n {label: 'Czech', code: 'cs', state: 'Beta'},\n {label: 'Croatian', code: 'hr', state: 'Beta'},\n {label: 'Danish', code: 'da', state: 'Beta'},\n {label: 'Romanian', code: 'ro', state: 'Beta'},\n {label: 'Bulgarian', code: 'bg', state: 'Beta'},\n] as const\n\nexport const SUPPORTED_MUX_LANGUAGES_VALUES = SUPPORTED_MUX_LANGUAGES.map((l) => l.code)\n\nexport type SupportedMuxLanguage = (typeof SUPPORTED_MUX_LANGUAGES_VALUES)[number]\n\nexport interface TextTrack {\n _id: string\n name: string\n}\n\nexport interface AutogeneratedTextTrack extends TextTrack {\n type: 'autogenerated'\n language_code: SupportedMuxLanguage\n}\n\nexport interface CustomTextTrack extends TextTrack {\n type: 'subtitles' | 'captions'\n language_code: string\n file: {\n contents: string\n type: string\n name: string\n size: number\n }\n}\n\nexport function isCustomTextTrack(track: Partial<UploadTextTrack>): track is CustomTextTrack {\n return track.type !== 'autogenerated'\n}\n\nexport function isAutogeneratedTrack(\n track: Partial<UploadTextTrack>,\n): track is AutogeneratedTextTrack {\n return track.type === 'autogenerated'\n}\n\nexport type UploadTextTrack = AutogeneratedTextTrack | CustomTextTrack\n\n/**\n * Watermark configuration for UI (draggable position)\n */\nexport interface WatermarkConfig {\n enabled: boolean\n imageUrl?: string\n /**\n * Aspect ratio (width / height) of the watermark image.\n * Used to convert between our center-based UI coords and Mux overlay margins.\n */\n imageAspectRatio?: number\n /**\n * Optional explicit Mux `overlay_settings`.\n * When set, these values should be used as-is for the upload request and preview.\n * @see {@link https://www.mux.com/docs/guides/add-watermarks-to-your-videos}\n */\n overlay_settings?: MuxOverlaySettings\n position?: {\n x: number // percentage (0-100)\n y: number // percentage (0-100)\n }\n size?: number // percentage of video width (0-100)\n opacity?: number // 0-1 (converted to percentage string for Mux API)\n}\n\n/**\n * Mux overlay_settings format for watermark API\n * @see {@link https://www.mux.com/docs/guides/add-watermarks-to-your-videos}\n */\nexport interface MuxOverlaySettings {\n vertical_align: 'top' | 'middle' | 'bottom'\n vertical_margin: string // percentage (e.g., \"10%\") or pixels (e.g., \"40px\")\n horizontal_align: 'left' | 'center' | 'right'\n horizontal_margin: string // percentage (e.g., \"10%\") or pixels (e.g., \"40px\")\n width?: string // percentage (e.g., \"25%\") or pixels (e.g., \"80px\")\n height?: string // percentage or pixels\n opacity?: string // percentage string (e.g., \"90%\")\n}\n\nexport interface UploadConfig extends Pick<\n MuxInputConfig,\n 'max_resolution_tier' | 'normalize_audio' | 'video_quality'\n> {\n static_renditions: StaticRenditionResolution[]\n text_tracks: UploadTextTrack[]\n signed_policy: boolean\n public_policy: boolean\n watermark?: WatermarkConfig\n drm_policy: boolean\n}\n\n/**\n * Data sent to Mux to create a new asset.\n * @docs {@link https://docs.mux.com/api-reference#video/operation/create-direct-upload}\n */\nexport interface MuxNewAssetSettings extends Pick<\n MuxInputConfig,\n 'max_resolution_tier' | 'normalize_audio' | 'video_quality'\n> {\n /** Static renditions configuration for downloadable files */\n static_renditions?: {resolution: StaticRenditionResolution}[]\n /** An array of objects that each describe an input file to be used to create the asset.*/\n input?: {\n /** The URL of the file that Mux should download and use. */\n url?: string\n /** Generate subtitle tracks using automatic speech recognition with this configuration. This may only be provided for the first input object (the main input file). */\n generated_subtitles?: {\n /** A name for this subtitle track. */\n name: string\n /** Arbitrary metadata set for the subtitle track. Max 255 characters. */\n passthrough?: string\n /** The language to generate subtitles in. */\n language_code: SupportedMuxLanguage\n }[]\n /** The time offset in seconds from the beginning of the video indicating the clip's starting marker. */\n start_time?: number\n /** The time offset in seconds from the beginning of the video indicating the clip's ending marker. */\n end_time?: number\n /** This parameter is required for text type tracks. */\n type?: 'video' | 'audio' | 'text'\n /** Type of text track. This parameter only supports subtitles value. */\n text_type?: 'subtitles'\n /** The language code value must be a valid BCP 47 specification compliant value. */\n language_code?: string\n /** The name of the track containing a human-readable description. This value must be unique within each group of text or audio track types. */\n name?: string\n /** Indicates the track provides Subtitles for the Deaf or Hard-of-hearing (SDH). */\n closed_captions?: boolean\n /** This optional parameter should be used tracks with type of text and text_type set to subtitles. */\n passthrough?: string\n /** Overlay settings for watermarks. Used when adding a watermark image as a second input. */\n overlay_settings?: MuxOverlaySettings\n }[]\n\n /** An array of playback policy names that you want applied to this asset and available through playback_ids. */\n playback_policy?: PlaybackPolicy[]\n\n /** An array of playback policy objects that you want applied to this asset and available through playback_ids. advanced_playback_policies must be used instead of playback_policies when creating a DRM playback ID. */\n advanced_playback_policies: AdvancedPlaybackPolicy[]\n\n /** Arbitrary user-supplied metadata that will be included in the asset details and related webhooks. */\n passthrough?: string\n}\n\n/** Used by advanced_playback_policies, allows to define DRM config. */\nexport type AdvancedPlaybackPolicy = {\n policy: PlaybackPolicy\n drm_configuration_id?: string\n}\n\nexport interface Secrets {\n token: string | null\n secretKey: string | null\n enableSignedUrls: boolean\n signingKeyId: string | null\n signingKeyPrivate: string | null\n drmConfigId: string | null\n}\n\nexport type MuxImageOrigin = `https://image.mux.com`\nexport type MuxThumbnailUrl = `${MuxImageOrigin}/${string}/thumbnail.png?${string}`\nexport type MuxAnimatedThumbnailUrl = `${MuxImageOrigin}/${string}/animated.gif?${string}`\nexport type MuxVideoOrigin = `https://stream.mux.com`\nexport type MuxVideoUrl = `${MuxVideoOrigin}/${string}.m3u8?${string}`\n\n// 'preserve' by default\n// @url: https://docs.mux.com/guides/video/get-images-from-a-video#thumbnail-query-string-parameters\nexport type FitMode = 'preserve' | 'crop' | 'smartcrop' | 'pad'\n\nexport interface ThumbnailOptions {\n fit_mode?: FitMode\n height?: number\n time?: number\n width?: number\n}\n\nexport interface AnimatedThumbnailOptions {\n // Starting time code for the animation, if no end is set it'll have a 5s duration\n // The start and end timecodes uses `asset.thumbTime` to create an iOS `Live Photo` effect by showing you the 5 secodnds before, and after, the thumb time`\n start?: number\n // End code, can't be longer than 10s after the start code\n end?: number\n // Max 640px, 320px by default\n width?: number\n // Preserves aspect ratio, like width, you can't set both the height and width, max 640\n height?: number\n // The fps is 15 by default, but can go up to 30\n fps?: number\n}\n\nexport interface AssetThumbnailOptions {\n asset: Pick<VideoAssetDocument, 'playbackId' | 'data' | 'thumbTime' | 'filename' | 'assetId'>\n}\n\nexport type PlaybackPolicy = 'signed' | 'public' | 'drm'\n\nexport interface MuxErrors {\n type: string\n messages: string[]\n}\n\nexport interface MuxPlaybackId {\n id: string\n policy: PlaybackPolicy\n}\n\nexport interface MuxVideoTrack {\n type: 'video'\n id: string\n max_width: number\n max_height: number\n // if the fps can't be reliably determined, this will be -1\n max_frame_rate: -1 | number\n // top-level duration is always set, while track level duration is not\n duration?: number\n}\nexport interface MuxAudioTrack {\n type: 'audio'\n id: string\n duration?: number\n max_channels: number\n max_channel_layout: 'stereo' | string\n}\nexport interface MuxTextTrack {\n type: 'text'\n id: string\n text_type?: 'subtitles'\n // https://docs.mux.com/api-reference/video#operation/list-assets:~:text=text%20type%20tracks.-,tracks%5B%5D.,text_source,-string\n text_source?:\n | 'uploaded'\n | 'embedded'\n | 'generated_live'\n | 'generated_live_final'\n | 'generated_vod'\n // BCP 47 language code\n language_code?: 'en' | 'en-US' | string\n // The name of the track containing a human-readable description. The hls manifest will associate a subtitle text track with this value\n name?: 'English' | string\n closed_captions?: boolean\n // Max 255 characters\n passthrough?: string\n status: 'preparing' | 'ready' | 'errored'\n error?: {\n type: string\n messages?: string[]\n }\n}\nexport type MuxTrack = MuxVideoTrack | MuxAudioTrack | MuxTextTrack\n// Typings lifted from https://docs.mux.com/api-reference/video#tag/assets\nexport interface MuxAsset {\n id: string\n /** In seconds (instead of JS's default milliseconds) */\n created_at: string\n status: 'preparing' | 'ready' | 'errored'\n duration: number\n max_stored_resolution: 'Audio only' | 'SD' | 'HD' | 'FHD' | 'UHD'\n max_resolution_tier?: '2160p' | '1440p' | '1080p'\n // if the fps can't be reliably determined, this will be -1\n max_stored_frame_rate: -1 | number\n // The aspect ratio of the asset in the form of width:height, for example 16:9\n aspect_ratio: `${number}:${number}`\n playback_ids: MuxPlaybackId[]\n tracks: MuxTrack[]\n errors?: MuxErrors\n upload_id: string\n is_live?: boolean\n // We use passthrough to set the mux.videoAsset._id of the asset that originally uploaded the video\n passthrough: string\n live_stream_id?: string\n master?: {\n status: 'ready' | 'preparing' | 'errored'\n // Temporary URL to master MP4, expires after 24 hours.\n // Only present once `status` is 'ready'.\n url?: string\n }\n master_access: 'temporary' | 'none'\n mp4_support: 'standard' | 'none'\n // Asset Identifier of the video used as the source for creating the clip.\n source_asset_id?: string\n // Normalize the audio track loudness level. This parameter is only applicable to on-demand (not live) assets., default false\n normalize_audio?: boolean\n // The object does not exist if no static renditions have been requested\n static_renditions?: {\n status: 'ready' | 'preparing' | 'disabled' | 'errored'\n files: {\n name: string\n ext: 'mp4' | 'm4a'\n height: number\n width: number\n bitrate: number\n filesize: string\n type: 'standard' | 'advanced'\n status: 'ready' | 'preparing' | 'skipped' | 'errored'\n resolution_tier?: string\n resolution?: string\n id: string\n passthrough?: string\n }[]\n }\n recording_times?: {\n started_at: string\n duration: number\n type: 'content' | 'slate'\n }[]\n // https://docs.mux.com/guides/video/minimize-processing-time\n non_standard_input_reasons?: {\n video_codec?: string\n audio_codec?: string\n video_gop_size?: 'high'\n video_frame_rate?: string\n video_resolution?: string\n video_bitrate?: 'high'\n pixel_aspect_ratio?: string\n video_edit_list?: 'non-standard'\n audio_edit_list?: 'non-standard'\n unexpected_media_file_parameters?: 'non-standard'\n test?: boolean\n }\n meta?: {\n title?: string\n }\n}\n\nexport interface VideoAssetDocument {\n _id: string\n _type: 'mux.videoAsset'\n _createdAt: string\n _updatedAt?: string\n status?: string\n assetId?: string\n playbackId?: string\n filename?: string\n thumbTime?: number\n // Docs for what goes in `data` https://docs.mux.com/api-reference/video#tag/assets\n data?: PartialDeep<MuxAsset>\n}\n\nexport type Reference = {_type: 'reference'; _ref: string}\n\n// @TODO add Reference, and ReferenceSchemaType in the generic\nexport type MuxInputProps = ObjectInputProps<{\n asset?: Reference\n}>\n","import {TranslateIcon} from '@sanity/icons/Translate'\nimport {UploadIcon} from '@sanity/icons/Upload'\nimport {\n Button,\n Card,\n Checkbox,\n Dialog,\n Flex,\n Label,\n Spinner,\n Stack,\n Text,\n TextInput,\n} from '@sanity/ui'\nimport {Autocomplete} from '@sanity/ui/autocomplete'\nimport {useToast} from '@sanity/ui/toast'\nimport LanguagesList from 'iso-639-1'\nimport {useId, useRef, useState} from 'react'\n\nimport {addTextTrackFromUrl, generateSubtitles, getAsset} from '../actions/assets'\nimport {useClient} from '../hooks/useClient'\nimport {addKeysToMuxData} from '../util/addKeysToMuxData'\nimport {extractErrorMessage, pollTrackStatus} from '../util/textTracks'\nimport {type MuxTextTrack, SUPPORTED_MUX_LANGUAGES, type VideoAssetDocument} from '../util/types'\n\nconst LANGUAGE_OPTIONS = LanguagesList.getAllCodes().map((code) => ({\n value: code,\n label: LanguagesList.getNativeName(code),\n}))\n\nconst MUX_LANGUAGE_OPTIONS = SUPPORTED_MUX_LANGUAGES.map((lang) => ({\n value: lang.code,\n label: lang.label,\n}))\n\nexport interface Props {\n asset: VideoAssetDocument\n onAdd: (track: MuxTextTrack) => void\n onClose: () => void\n}\n\nexport default function AddCaptionDialog({asset, onAdd, onClose}: Props) {\n const client = useClient()\n const toast = useToast()\n const dialogId = `AddCaptionDialog${useId()}`\n\n const [isAutogenerated, setIsAutogenerated] = useState(false)\n const [vttUrl, setVttUrl] = useState('')\n const [languageCode, setLanguageCode] = useState('')\n const [selectedLanguage, setSelectedLanguage] = useState<{value: string; label: string} | null>(\n null,\n )\n const [name, setName] = useState('')\n const [isSubmitting, setIsSubmitting] = useState(false)\n const [selectedFile, setSelectedFile] = useState<File | null>(null)\n const fileInputRef = useRef<HTMLInputElement>(null)\n\n const uploadVttFile = async (file: File): Promise<string> => {\n const assetDocument = await client.assets.upload('file', file, {\n filename: file.name,\n })\n return assetDocument.url\n }\n\n const refreshAssetData = async () => {\n if (!asset._id || !asset.assetId) return\n try {\n const latestAssetData = await getAsset(client, asset.assetId)\n const dataWithKeys = addKeysToMuxData(latestAssetData.data)\n await client\n .patch(asset._id)\n .set({data: dataWithKeys, status: latestAssetData.data.status})\n .commit({returnDocuments: false})\n } catch (refreshError) {\n console.error('Failed to refresh asset data:', refreshError)\n }\n }\n\n const handleAddTrackFromUrl = async () => {\n if (!asset.assetId) {\n throw new Error('Asset ID is required')\n }\n\n const trimmedName = name.trim()\n const trimmedLanguageCode = languageCode.trim()\n\n let vttUrlToUse = vttUrl.trim()\n\n if (selectedFile) {\n try {\n vttUrlToUse = await uploadVttFile(selectedFile)\n } catch (uploadError) {\n toast.push({\n title: 'Failed to upload caption file',\n status: 'error',\n description: 'Could not upload the caption file to Sanity. Please try again.',\n })\n setIsSubmitting(false)\n throw uploadError\n }\n }\n\n await addTextTrackFromUrl(client, asset.assetId, vttUrlToUse, {\n language_code: trimmedLanguageCode,\n name: trimmedName,\n text_type: 'subtitles',\n })\n\n const result = await pollTrackStatus({\n client,\n assetId: asset.assetId,\n trackName: trimmedName,\n trackLanguageCode: trimmedLanguageCode,\n onTrackErrored: async (track) => {\n const errorMessage =\n track.error?.messages?.[0] ||\n track.error?.type ||\n 'The track failed to download from the provided URL'\n toast.push({\n title: 'Caption track failed',\n status: 'error',\n description: errorMessage,\n })\n await refreshAssetData()\n onAdd(track)\n onClose()\n },\n })\n\n if (!result.found || !result.track) {\n toast.push({\n title: 'Caption track may have been added',\n status: 'warning',\n description:\n 'The track was created but its status could not be determined. It may still be processing. Please refresh the page to see if it appears.',\n })\n onClose()\n return\n }\n\n if (result.status === 'errored') {\n return\n }\n\n if (result.status === 'preparing') {\n toast.push({\n title: 'Caption track is processing',\n status: 'info',\n description:\n 'The track was created and is being processed. It will appear in the list shortly.',\n })\n await refreshAssetData()\n onAdd(result.track)\n onClose()\n return\n }\n\n await refreshAssetData()\n toast.push({\n title: 'Caption track added',\n status: 'success',\n description: 'Caption track added successfully',\n })\n\n onAdd(result.track)\n onClose()\n }\n\n const handleGenerateSubtitles = async () => {\n if (!asset.assetId) {\n throw new Error('Asset ID is required')\n }\n\n const assetData = await getAsset(client, asset.assetId)\n const audioTrack = assetData.data.tracks?.find((track) => track.type === 'audio')\n\n if (!audioTrack || !audioTrack.id) {\n toast.push({\n title: 'No audio track found',\n status: 'error',\n description:\n 'The asset does not have an audio track. Auto-generated subtitles require an audio track.',\n })\n throw new Error('No audio track found')\n }\n\n await generateSubtitles(client, asset.assetId, audioTrack.id, {\n language_code: languageCode.trim(),\n name: name.trim(),\n })\n\n const mockTrackId = `generating-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`\n const mockTrack: MuxTextTrack = {\n type: 'text',\n id: mockTrackId,\n text_type: 'subtitles',\n text_source: 'generated_live',\n language_code: languageCode.trim(),\n name: name.trim(),\n status: 'preparing',\n }\n\n toast.push({\n title: 'Generating subtitles',\n status: 'success',\n description: 'This may take a few minutes',\n })\n\n onAdd(mockTrack)\n onClose()\n }\n\n const handleSubmit = async () => {\n if (!isAutogenerated) {\n if (!selectedFile && !vttUrl.trim()) {\n toast.push({\n title: 'Caption file or URL required',\n status: 'error',\n description: 'Please select a VTT or SRT file or enter a caption file URL',\n })\n return\n }\n\n if (vttUrl.trim() && !selectedFile) {\n try {\n void new URL(vttUrl.trim())\n } catch {\n toast.push({\n title: 'Invalid URL',\n status: 'error',\n description:\n 'Please enter a valid URL (e.g., https://example.com/subtitles.vtt or subtitles.srt)',\n })\n return\n }\n }\n }\n\n if (!name.trim()) {\n toast.push({\n title: 'Audio name required',\n status: 'error',\n description: 'Please enter an audio name for this caption track',\n })\n return\n }\n\n if (!languageCode.trim()) {\n toast.push({\n title: 'Language code required',\n status: 'error',\n description: 'Please enter a language code (e.g., en, es, fr)',\n })\n return\n }\n\n setIsSubmitting(true)\n\n try {\n if (isAutogenerated) {\n await handleGenerateSubtitles()\n } else {\n await handleAddTrackFromUrl()\n }\n } catch (error) {\n toast.push({\n title: 'Failed to add caption track',\n status: 'error',\n description: extractErrorMessage(error, 'Failed to add caption track'),\n })\n // oxlint-disable-next-line react/todo\n } finally {\n setIsSubmitting(false)\n }\n }\n\n return (\n <Dialog\n id={dialogId}\n header=\"Add Caption Track\"\n onClose={onClose}\n width={1}\n onClickOutside={onClose}\n >\n <Stack padding={4} gap={4}>\n <Stack gap={2}>\n <Flex align=\"center\" marginBottom={3}>\n <Checkbox\n id=\"autogenerated-checkbox\"\n style={{display: 'block'}}\n checked={isAutogenerated}\n onChange={(e) => {\n setIsAutogenerated(e.currentTarget.checked)\n if (e.currentTarget.checked) {\n setVttUrl('')\n }\n }}\n disabled={isSubmitting}\n />\n <Flex flex={1} paddingLeft={2}>\n <Text>\n <label htmlFor=\"autogenerated-checkbox\">Generate captions</label>\n </Text>\n </Flex>\n </Flex>\n {!isAutogenerated && (\n <Stack gap={2}>\n <Card padding={3} marginBottom={2} tone=\"transparent\" border radius={2}>\n <Flex align=\"center\" justify=\"space-between\">\n <Text size={1} muted>\n {selectedFile ? `Selected: ${selectedFile.name}` : 'No file selected'}\n </Text>\n <Button\n icon={UploadIcon}\n text=\"Select File\"\n mode=\"ghost\"\n tone=\"primary\"\n fontSize={1}\n padding={2}\n onClick={() => fileInputRef.current?.click()}\n disabled={isSubmitting}\n />\n </Flex>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\".vtt,text/vtt,.srt,application/x-subrip\"\n style={{display: 'none'}}\n onChange={(e) => {\n if (e.target.files && e.target.files.length > 0 && !isSubmitting) {\n setSelectedFile(e.target.files[0]!)\n setVttUrl('')\n }\n }}\n />\n </Card>\n <Text size={1} muted style={{textAlign: 'center'}}>\n Or enter the caption file URL\n </Text>\n <Stack gap={2}>\n <Label as=\"label\" htmlFor=\"vtt-url\">\n Caption File URL (.vtt or .srt)\n </Label>\n <TextInput\n id=\"vtt-url\"\n placeholder=\"https://example.com/subtitles.vtt\"\n value={vttUrl}\n onChange={(e) => {\n setVttUrl(e.currentTarget.value)\n setSelectedFile(null)\n }}\n disabled={isSubmitting}\n />\n </Stack>\n </Stack>\n )}\n </Stack>\n\n <Stack gap={2}>\n <Label as=\"label\" htmlFor=\"caption-name\">\n Audio name\n </Label>\n <Autocomplete\n id=\"caption-name\"\n value={selectedLanguage?.value || ''}\n onChange={(newValue) => {\n const options = isAutogenerated ? MUX_LANGUAGE_OPTIONS : LANGUAGE_OPTIONS\n const selected = options.find((opt) => opt.value === newValue)\n if (selected) {\n setSelectedLanguage(selected)\n setLanguageCode(selected.value)\n setName(selected.label)\n }\n }}\n options={isAutogenerated ? MUX_LANGUAGE_OPTIONS : LANGUAGE_OPTIONS}\n icon={TranslateIcon}\n placeholder=\"Select language\"\n filterOption={(query, option) =>\n option.label.toLowerCase().indexOf(query.toLowerCase()) > -1 ||\n option.value.toLowerCase().indexOf(query.toLowerCase()) > -1\n }\n openButton\n renderValue={(value) =>\n (isAutogenerated ? MUX_LANGUAGE_OPTIONS : LANGUAGE_OPTIONS).find(\n (l) => l.value === value,\n )?.label || value\n }\n renderOption={(option) => (\n <Card data-as=\"button\" padding={3} radius={2} tone=\"inherit\">\n <Text size={2} textOverflow=\"ellipsis\">\n {option.label} ({option.value})\n </Text>\n </Card>\n )}\n disabled={isSubmitting}\n />\n </Stack>\n\n <Stack gap={2}>\n <Label as=\"label\" htmlFor=\"caption-language\">\n Language Code\n </Label>\n <TextInput\n id=\"caption-language\"\n placeholder=\"en-US\"\n value={languageCode}\n onChange={(e) => {\n setLanguageCode(e.currentTarget.value)\n if (selectedLanguage && selectedLanguage.value !== e.currentTarget.value) {\n setSelectedLanguage(null)\n if (!name || name === selectedLanguage.label) {\n setName('')\n }\n }\n }}\n disabled={isSubmitting}\n />\n </Stack>\n\n <Flex gap={2} justify=\"flex-end\" marginTop={2}>\n <Button text=\"Cancel\" mode=\"ghost\" onClick={onClose} disabled={isSubmitting} />\n <Button\n text=\"Add Caption Track\"\n tone=\"primary\"\n icon={\n isSubmitting ? (\n <Spinner\n style={{\n verticalAlign: 'middle',\n display: 'inline-block',\n marginBottom: '-3px',\n width: '1em',\n height: '1em',\n marginRight: '-6px',\n }}\n />\n ) : (\n <UploadIcon />\n )\n }\n onClick={handleSubmit}\n disabled={isSubmitting}\n />\n </Flex>\n </Stack>\n </Dialog>\n )\n}\n","import {DownloadIcon} from '@sanity/icons/Download'\nimport {TranslateIcon} from '@sanity/icons/Translate'\nimport {UploadIcon} from '@sanity/icons/Upload'\nimport {Button, Card, Dialog, Flex, Label, Spinner, Stack, Text, TextInput} from '@sanity/ui'\nimport {Autocomplete} from '@sanity/ui/autocomplete'\nimport {useToast} from '@sanity/ui/toast'\nimport LanguagesList from 'iso-639-1'\nimport {useEffect, useId, useRef, useState} from 'react'\n\nimport {addTextTrackFromUrl, deleteTextTrack, getAsset} from '../actions/assets'\nimport {useClient} from '../hooks/useClient'\nimport {addKeysToMuxData} from '../util/addKeysToMuxData'\nimport {generateJwt} from '../util/generateJwt'\nimport {getPlaybackId} from '../util/getPlaybackPolicy'\nimport {getPlaybackPolicy} from '../util/getPlaybackPolicy'\nimport {downloadVttFile, extractErrorMessage, pollTrackStatus} from '../util/textTracks'\nimport type {MuxTextTrack, VideoAssetDocument} from '../util/types'\n\nconst LANGUAGE_OPTIONS = LanguagesList.getAllCodes().map((code) => ({\n value: code,\n label: LanguagesList.getNativeName(code),\n}))\n\nexport interface Props {\n asset: VideoAssetDocument\n track: MuxTextTrack\n onUpdate: (track: MuxTextTrack, oldTrackId?: string) => void\n onClose: () => void\n}\n\nexport default function EditCaptionDialog({asset, track, onUpdate, onClose}: Props) {\n const client = useClient()\n const toast = useToast()\n const dialogId = `EditCaptionDialog${useId()}`\n\n const isAutogenerated =\n track.text_source === 'generated_live' ||\n track.text_source === 'generated_live_final' ||\n track.text_source === 'generated_vod'\n\n const [vttUrl, setVttUrl] = useState('')\n const [languageCode, setLanguageCode] = useState(track.language_code || '')\n const [selectedLanguage, setSelectedLanguage] = useState<{value: string; label: string} | null>(\n () => {\n const baseCode = track.language_code?.split('-')[0]\n const found = LANGUAGE_OPTIONS.find(\n (opt) => opt.value === track.language_code || opt.value === baseCode,\n )\n if (found) return found\n if (track.name) {\n const foundByName = LANGUAGE_OPTIONS.find((opt) => opt.label === track.name)\n if (foundByName) return foundByName\n }\n return null\n },\n )\n const [name, setName] = useState(track.name || '')\n const [isSubmitting, setIsSubmitting] = useState(false)\n const [downloading, setDownloading] = useState(false)\n const [selectedFile, setSelectedFile] = useState<File | null>(null)\n const fileInputRef = useRef<HTMLInputElement>(null)\n\n useEffect(() => {\n // oxlint-disable-next-line react/set-state-in-effect\n setLanguageCode(track.language_code || '')\n setName(track.name || '')\n setVttUrl('')\n const baseCode = track.language_code?.split('-')[0]\n const foundByCode = LANGUAGE_OPTIONS.find(\n (opt) => opt.value === track.language_code || opt.value === baseCode,\n )\n const foundByName = track.name ? LANGUAGE_OPTIONS.find((opt) => opt.label === track.name) : null\n setSelectedLanguage(foundByCode || foundByName || null)\n // oxlint-disable-next-line react/exhaustive-effect-dependencies\n }, [track, asset, client])\n\n const handleDownloadCurrentFile = async () => {\n setDownloading(true)\n try {\n await downloadVttFile(client, asset, track)\n } catch (error) {\n let errorMessage = 'Please try again'\n let title = 'Failed to download VTT file'\n\n if (error instanceof Error) {\n errorMessage = error.message\n if (error.message.includes('Track')) {\n title = 'Cannot download'\n }\n } else if (error === 'Track ID is missing' || error === 'Track is not ready yet') {\n errorMessage = error\n title = 'Cannot download'\n }\n\n toast.push({\n title,\n status: 'error',\n description: errorMessage,\n })\n // oxlint-disable-next-line react/todo\n } finally {\n setDownloading(false)\n }\n }\n\n const getCurrentFileName = () => {\n if (track.id && asset.filename) {\n return `${asset.filename}-${track.language_code || 'en'}.vtt`\n }\n return `captions-${track.language_code || 'en'}.vtt`\n }\n\n const uploadVttFile = async (file: File): Promise<string> => {\n const assetDocument = await client.assets.upload('file', file, {\n filename: file.name,\n })\n return assetDocument.url\n }\n\n const refreshAssetData = async () => {\n if (!asset._id || !asset.assetId) return\n try {\n const latestAssetData = await getAsset(client, asset.assetId)\n const dataWithKeys = addKeysToMuxData(latestAssetData.data)\n await client\n .patch(asset._id)\n .set({data: dataWithKeys, status: latestAssetData.data.status})\n .commit({returnDocuments: false})\n } catch (refreshError) {\n console.error('Failed to refresh asset data:', refreshError)\n }\n }\n\n const handleUpdateTrackWithNewUrl = async () => {\n if (!asset.assetId) {\n throw new Error('Asset ID is required')\n }\n\n const trimmedName = name.trim()\n const trimmedLanguageCode = languageCode.trim()\n\n const oldTrackId = track.id\n\n try {\n await deleteTextTrack(client, asset.assetId, oldTrackId)\n } catch (deleteError) {\n toast.push({\n title: 'Failed to delete old track',\n status: 'error',\n description: 'Could not delete the old track. Please try again or delete it manually.',\n })\n setIsSubmitting(false)\n throw deleteError\n }\n\n let vttUrlToUse = vttUrl.trim()\n\n if (selectedFile) {\n try {\n vttUrlToUse = await uploadVttFile(selectedFile)\n } catch (uploadError) {\n toast.push({\n title: 'Failed to upload VTT file',\n status: 'error',\n description: 'Could not upload the VTT file to Sanity. Please try again.',\n })\n setIsSubmitting(false)\n throw uploadError\n }\n }\n\n try {\n await addTextTrackFromUrl(client, asset.assetId, vttUrlToUse, {\n language_code: trimmedLanguageCode,\n name: trimmedName,\n text_type: 'subtitles',\n })\n } catch (error: unknown) {\n toast.push({\n title: 'Failed to update caption track',\n status: 'error',\n description: extractErrorMessage(error, 'Failed to update caption track'),\n })\n setIsSubmitting(false)\n throw error\n }\n\n const result = await pollTrackStatus({\n client,\n assetId: asset.assetId,\n trackName: trimmedName,\n trackLanguageCode: trimmedLanguageCode,\n onTrackErrored: async (erroredTrack) => {\n const errorMessage =\n erroredTrack.error?.messages?.[0] ||\n erroredTrack.error?.type ||\n 'The track failed to download from the provided URL'\n toast.push({\n title: 'Caption track failed',\n status: 'error',\n description: errorMessage,\n })\n await refreshAssetData()\n onUpdate(erroredTrack, oldTrackId)\n setIsSubmitting(false)\n },\n })\n\n if (!result.found || !result.track) {\n toast.push({\n title: 'Caption track may have been updated',\n status: 'warning',\n description:\n 'The track was updated but its status could not be determined. It may still be processing. Please refresh the page to see if it appears.',\n })\n setIsSubmitting(false)\n return\n }\n\n if (result.status === 'errored') {\n return\n }\n\n await refreshAssetData()\n\n if (result.status === 'preparing') {\n toast.push({\n title: 'Caption track is processing',\n status: 'info',\n description:\n 'The track was updated and is being processed. It will appear in the list shortly.',\n })\n } else {\n toast.push({\n title: 'Caption track updated',\n status: 'success',\n description: 'Caption track updated successfully',\n })\n }\n\n onUpdate(result.track, oldTrackId)\n setIsSubmitting(false)\n }\n\n const handleSubmit = async () => {\n if (!name.trim()) {\n toast.push({\n title: 'Audio name required',\n status: 'error',\n description: 'Please enter an audio name for this caption track',\n })\n return\n }\n\n if (!languageCode.trim()) {\n toast.push({\n title: 'Language code required',\n status: 'error',\n description: 'Please enter a language code (e.g., en, es, fr)',\n })\n return\n }\n\n setIsSubmitting(true)\n\n try {\n if (!asset.assetId) {\n // oxlint-disable-next-line react/todo\n throw new Error('Asset ID is required')\n }\n\n const originalVttUrl = (() => {\n if (isAutogenerated || !track.id) return ''\n const playbackId = getPlaybackId(asset)\n if (!playbackId) return ''\n let url = `https://stream.mux.com/${playbackId}/text/${track.id}.vtt`\n if (getPlaybackPolicy(asset)?.policy === 'signed') {\n const token = generateJwt(client, playbackId, 'v')\n url += `?token=${token}`\n }\n return url\n })()\n\n const urlChanged =\n selectedFile !== null || (vttUrl.trim() && vttUrl.trim() !== originalVttUrl)\n\n if (!urlChanged) {\n toast.push({\n title: 'No changes',\n status: 'info',\n description:\n 'Please provide a new VTT file or URL using the \"Replace\" button or URL field to update the track.',\n })\n setIsSubmitting(false)\n return\n }\n\n if (urlChanged) {\n if (!selectedFile && vttUrl.trim()) {\n try {\n void new URL(vttUrl.trim())\n } catch {\n toast.push({\n title: 'Invalid URL',\n status: 'error',\n description: 'Please enter a valid URL (e.g., https://example.com/subtitles.vtt)',\n })\n setIsSubmitting(false)\n return\n }\n }\n\n if (!selectedFile && !vttUrl.trim()) {\n toast.push({\n title: 'VTT file or URL required',\n status: 'error',\n description: 'Please select a VTT file or enter a VTT file URL',\n })\n setIsSubmitting(false)\n return\n }\n\n await handleUpdateTrackWithNewUrl()\n }\n\n onClose()\n } catch (error) {\n toast.push({\n title: 'Failed to update caption track',\n status: 'error',\n description: error instanceof Error ? error.message : 'Please try again',\n })\n // oxlint-disable-next-line react/todo\n } finally {\n setIsSubmitting(false)\n }\n }\n\n return (\n <Dialog\n id={dialogId}\n header=\"Edit Caption Track\"\n onClose={onClose}\n width={1}\n onClickOutside={onClose}\n >\n <Stack padding={4} gap={4}>\n <Stack gap={2}>\n <Card padding={3} marginBottom={2} tone=\"transparent\" border radius={2}>\n <Flex align=\"center\" justify=\"space-between\">\n <Text>{getCurrentFileName()}</Text>\n <Flex gap={2}>\n {track.status !== 'errored' && (\n <Button\n icon={\n downloading ? (\n <Spinner\n style={{\n verticalAlign: 'middle',\n display: 'inline-block',\n marginTop: '-2px',\n width: '0.5em',\n height: '0.5em',\n }}\n />\n ) : (\n <DownloadIcon />\n )\n }\n text=\"Download\"\n mode=\"ghost\"\n tone=\"primary\"\n fontSize={1}\n padding={2}\n onClick={handleDownloadCurrentFile}\n disabled={downloading || isSubmitting}\n />\n )}\n <Button\n icon={UploadIcon}\n text=\"Replace\"\n mode=\"ghost\"\n tone=\"primary\"\n fontSize={1}\n padding={2}\n onClick={() => fileInputRef.current?.click()}\n disabled={isSubmitting}\n />\n </Flex>\n </Flex>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\".vtt,text/vtt\"\n style={{display: 'none'}}\n onChange={(e) => {\n if (e.target.files && e.target.files.length > 0 && !isSubmitting) {\n setSelectedFile(e.target.files[0]!)\n setVttUrl('')\n }\n }}\n />\n {selectedFile && (\n <Text size={1} muted style={{marginTop: 8}}>\n Selected: {selectedFile.name}\n </Text>\n )}\n </Card>\n <Stack gap={2}>\n <Label as=\"label\" htmlFor=\"vtt-url\">\n VTT File URL\n </Label>\n <TextInput\n id=\"vtt-url\"\n placeholder=\"https://example.com/subtitles.vtt\"\n value={vttUrl}\n onChange={(e) => {\n setVttUrl(e.currentTarget.value)\n setSelectedFile(null)\n }}\n disabled={isSubmitting}\n />\n <Text size={1} muted>\n Add a URL to replace the existing VTT file with a new one\n </Text>\n </Stack>\n </Stack>\n\n <Stack gap={2}>\n <Label as=\"label\" htmlFor=\"caption-name\">\n Audio name\n </Label>\n <Autocomplete\n id=\"caption-name\"\n value={selectedLanguage?.value || ''}\n onChange={(newValue) => {\n const selected = LANGUAGE_OPTIONS.find((opt) => opt.value === newValue)\n if (selected) {\n setSelectedLanguage(selected)\n setLanguageCode(selected.value)\n setName(selected.label)\n }\n }}\n options={LANGUAGE_OPTIONS}\n icon={TranslateIcon}\n placeholder=\"Select language\"\n filterOption={(query, option) =>\n option.label.toLowerCase().indexOf(query.toLowerCase()) > -1 ||\n option.value.toLowerCase().indexOf(query.toLowerCase()) > -1\n }\n openButton\n renderValue={(value) => LANGUAGE_OPTIONS.find((l) => l.value === value)?.label || value}\n renderOption={(option) => (\n <Card data-as=\"button\" padding={3} radius={2} tone=\"inherit\">\n <Text size={2} textOverflow=\"ellipsis\">\n {option.label} ({option.value})\n </Text>\n </Card>\n )}\n disabled={isSubmitting}\n />\n </Stack>\n\n <Stack gap={2}>\n <Label as=\"label\" htmlFor=\"caption-language\">\n Language Code\n </Label>\n <TextInput\n id=\"caption-language\"\n placeholder=\"en-US\"\n value={languageCode}\n onChange={(e) => {\n setLanguageCode(e.currentTarget.value)\n if (selectedLanguage && selectedLanguage.value !== e.currentTarget.value) {\n setSelectedLanguage(null)\n if (!name || name === selectedLanguage.label) {\n setName('')\n }\n }\n }}\n disabled={isSubmitting}\n />\n </Stack>\n\n <Flex gap={2} justify=\"flex-end\" marginTop={2}>\n <Button text=\"Cancel\" mode=\"ghost\" onClick={onClose} disabled={isSubmitting} />\n <Button\n text=\"Update Caption Track\"\n tone=\"primary\"\n icon={\n isSubmitting ? (\n <Spinner\n style={{\n verticalAlign: 'middle',\n display: 'inline-block',\n marginBottom: '-3px',\n width: '1em',\n height: '1em',\n marginRight: '-6px',\n }}\n />\n ) : (\n UploadIcon\n )\n }\n onClick={handleSubmit}\n disabled={isSubmitting}\n />\n </Flex>\n </Stack>\n </Dialog>\n )\n}\n","import {AddIcon} from '@sanity/icons/Add'\nimport {ChevronDownIcon} from '@sanity/icons/ChevronDown'\nimport {ChevronUpIcon} from '@sanity/icons/ChevronUp'\nimport {DownloadIcon} from '@sanity/icons/Download'\nimport {EditIcon} from '@sanity/icons/Edit'\nimport {ErrorOutlineIcon} from '@sanity/icons/ErrorOutline'\nimport {TrashIcon} from '@sanity/icons/Trash'\nimport {Box, Button, Card, Dialog, Flex, Heading, Spinner, Stack, Text} from '@sanity/ui'\nimport {useToast} from '@sanity/ui/toast'\nimport {useEffect, useId, useMemo, useState} from 'react'\n\nimport {deleteTextTrack} from '../actions/assets'\nimport {useClient} from '../hooks/useClient'\nimport {useResyncAsset} from '../hooks/useResyncAsset'\nimport {downloadVttFile} from '../util/textTracks'\nimport type {MuxTextTrack, VideoAssetDocument} from '../util/types'\nimport AddCaptionDialog from './AddCaptionDialog'\nimport EditCaptionDialog from './EditCaptionDialog'\n\ninterface TrackCardProps {\n track: MuxTextTrack\n iconOnly: boolean\n downloadingTrackId: string | null\n deletingTrackId: string | null\n trackToEdit: MuxTextTrack | null\n getTrackSourceLabel: (track: MuxTextTrack) => string\n handleDownload: (track: MuxTextTrack) => void\n setTrackToEdit: (track: MuxTextTrack) => void\n setTrackToDelete: (track: MuxTextTrack) => void\n}\n\nfunction TrackCard({\n track,\n iconOnly,\n downloadingTrackId,\n deletingTrackId,\n trackToEdit,\n getTrackSourceLabel,\n handleDownload,\n setTrackToEdit,\n setTrackToDelete,\n}: TrackCardProps) {\n const isDisabled = (action: 'download' | 'edit' | 'delete') => {\n if (action === 'download') {\n return (\n downloadingTrackId !== null || deletingTrackId === track.id || trackToEdit?.id === track.id\n )\n }\n if (action === 'edit') {\n return (\n downloadingTrackId === track.id ||\n deletingTrackId === track.id ||\n trackToEdit?.id === track.id\n )\n }\n return (\n downloadingTrackId === track.id || deletingTrackId !== null || trackToEdit?.id === track.id\n )\n }\n\n const renderActionButtons = () => {\n if (track.status === 'preparing') {\n return (\n <Flex align=\"center\" gap={2}>\n <Spinner\n muted\n style={{\n width: '0.75em',\n height: '0.75em',\n verticalAlign: 'middle',\n display: 'inline-block',\n marginBottom: '-2px',\n }}\n />\n <Text size={1} muted>\n Processing...\n </Text>\n </Flex>\n )\n }\n\n return (\n <Flex gap={2}>\n {track.status !== 'errored' && (\n <Button\n icon={\n downloadingTrackId === track.id ? (\n <Spinner\n style={{\n verticalAlign: 'middle',\n display: 'inline-block',\n marginTop: '-2px',\n width: '0.5em',\n height: '0.5em',\n }}\n />\n ) : (\n <DownloadIcon />\n )\n }\n text={iconOnly ? undefined : 'Download'}\n mode=\"ghost\"\n tone=\"primary\"\n fontSize={1}\n padding={2}\n onClick={() => handleDownload(track)}\n disabled={isDisabled('download')}\n title=\"Download\"\n />\n )}\n <Button\n icon={<EditIcon />}\n text={iconOnly ? undefined : 'Edit'}\n mode=\"ghost\"\n tone=\"primary\"\n fontSize={1}\n padding={2}\n disabled={isDisabled('edit')}\n onClick={() => setTrackToEdit(track)}\n title=\"Edit\"\n />\n <Button\n icon={\n deletingTrackId === track.id ? (\n <Spinner\n style={{\n verticalAlign: 'middle',\n display: 'inline-block',\n marginTop: '-2px',\n width: '0.5em',\n height: '0.5em',\n }}\n />\n ) : (\n <TrashIcon />\n )\n }\n text={iconOnly ? undefined : 'Delete'}\n mode=\"ghost\"\n tone=\"critical\"\n fontSize={1}\n padding={2}\n disabled={isDisabled('delete')}\n onClick={() => setTrackToDelete(track)}\n title=\"Delete\"\n />\n </Flex>\n )\n }\n\n return (\n <Card\n padding={3}\n radius={2}\n tone={track.status === 'errored' ? 'caution' : 'transparent'}\n border\n >\n <Flex align=\"center\" justify=\"space-between\" gap={3}>\n <Stack gap={2} flex={1}>\n <Flex align=\"center\" gap={2}>\n <Text weight=\"semibold\">{track.name || 'Untitled'}</Text>\n <Text size={1} muted>\n ({getTrackSourceLabel(track)})\n </Text>\n {track.status === 'errored' && (\n <ErrorOutlineIcon\n style={{color: 'var(--card-critical-color)'}}\n aria-label=\"Error\"\n fontSize={20}\n />\n )}\n </Flex>\n {track.language_code && (\n <Text size={1} muted>\n Language: {track.language_code}\n </Text>\n )}\n {track.status === 'errored' && track.error && (\n <Text size={1} style={{color: 'var(--card-critical-color)'}}>\n {track.error.messages?.[0] || track.error.type || 'Failed to process track'}\n </Text>\n )}\n </Stack>\n {renderActionButtons()}\n </Flex>\n </Card>\n )\n}\n\ninterface TextTracksManagerProps {\n asset: VideoAssetDocument\n iconOnly?: boolean\n tracks?: MuxTextTrack[]\n collapseTracks?: boolean\n}\n\nexport default function TextTracksManager({\n asset,\n iconOnly = false,\n tracks: propTracks,\n collapseTracks = false,\n}: TextTracksManagerProps) {\n const client = useClient()\n const toast = useToast()\n const dialogId = `DeleteCaptionDialog${useId()}`\n const {resyncAsset} = useResyncAsset()\n const [downloadingTrackId, setDownloadingTrackId] = useState<string | null>(null)\n const [deletingTrackId, setDeletingTrackId] = useState<string | null>(null)\n const [addedTracks, setAddedTracks] = useState<MuxTextTrack[]>([])\n const [updatedTracks, setUpdatedTracks] = useState<Map<string, MuxTextTrack>>(new Map())\n const [trackActivityOrder, setTrackActivityOrder] = useState<Map<string, number>>(new Map())\n const [autogeneratedTrackIds, setAutogeneratedTrackIds] = useState<Set<string>>(new Set())\n const [trackToDelete, setTrackToDelete] = useState<MuxTextTrack | null>(null)\n const [trackToEdit, setTrackToEdit] = useState<MuxTextTrack | null>(null)\n const [showAddDialog, setShowAddDialog] = useState(false)\n const [isExpanded, setIsExpanded] = useState(false)\n\n const MAX_VISIBLE_TRACKS = 4\n\n const realTracks: MuxTextTrack[] = propTracks\n ? propTracks\n : asset.data?.tracks?.filter((track): track is MuxTextTrack => track.type === 'text') || []\n\n const activeTracks = realTracks.filter(\n (track) =>\n track.id &&\n (track.status === 'ready' || track.status === 'preparing' || track.status === 'errored'),\n )\n\n const allTracks = useMemo(() => {\n const tracksWithUpdates = activeTracks.map((track) => {\n const updated = updatedTracks.get(track.id)\n return updated || track\n })\n\n const isMockTrackReplaced = (mockTrack: MuxTextTrack, realTracksList: MuxTextTrack[]) => {\n if (!mockTrack.id || !mockTrack.id.startsWith('generating-')) {\n return false\n }\n return realTracksList.some((realTrack) => {\n const nameMatches = realTrack.name === mockTrack.name\n const languageMatches = realTrack.language_code === mockTrack.language_code\n if (!nameMatches || !languageMatches) {\n return false\n }\n if (realTrack.status === 'ready') {\n const isGenerated =\n realTrack.text_source === 'generated_live' ||\n realTrack.text_source === 'generated_live_final' ||\n realTrack.text_source === 'generated_vod'\n return isGenerated\n }\n if (realTrack.status === 'preparing') {\n return true\n }\n return false\n })\n }\n\n const isTrackAlreadyInRealTracks = (\n addedTrack: MuxTextTrack,\n realTracksList: MuxTextTrack[],\n ) => {\n if (!addedTrack.id) return false\n if (addedTrack.id.startsWith('generating-')) {\n return isMockTrackReplaced(addedTrack, realTracksList)\n }\n return realTracksList.some((realTrack) => realTrack.id === addedTrack.id)\n }\n\n const tracksToKeep = addedTracks.filter((addedTrack) => {\n if (addedTrack.id && addedTrack.id.startsWith('generating-')) {\n return !isMockTrackReplaced(addedTrack, tracksWithUpdates)\n }\n return !isTrackAlreadyInRealTracks(addedTrack, tracksWithUpdates)\n })\n\n return [...tracksWithUpdates, ...tracksToKeep]\n }, [activeTracks, addedTracks, updatedTracks])\n\n useEffect(() => {\n const newAutogeneratedIds = new Set<string>()\n\n activeTracks.forEach((track) => {\n if (\n track.id &&\n (track.text_source === 'generated_live' ||\n track.text_source === 'generated_live_final' ||\n track.text_source === 'generated_vod')\n ) {\n newAutogeneratedIds.add(track.id)\n }\n })\n\n addedTracks.forEach((mockTrack) => {\n if (mockTrack.id && mockTrack.id.startsWith('generating-')) {\n const realTrack = activeTracks.find((rt) => {\n const nameMatches = rt.name === mockTrack.name\n const languageMatches = rt.language_code === mockTrack.language_code\n return nameMatches && languageMatches\n })\n if (realTrack?.id) {\n newAutogeneratedIds.add(realTrack.id)\n }\n }\n })\n\n // oxlint-disable-next-line react/set-state-in-effect\n setAutogeneratedTrackIds((prev) => {\n let hasNew = false\n const updated = new Set(prev)\n newAutogeneratedIds.forEach((id) => {\n if (!prev.has(id)) {\n updated.add(id)\n hasNew = true\n }\n })\n return hasNew ? updated : prev\n })\n }, [activeTracks, addedTracks])\n\n useEffect(() => {\n const preparingTracks = allTracks.filter((track) => track.status === 'preparing')\n if (preparingTracks.length === 0 || !asset.assetId || !asset._id) {\n return undefined\n }\n\n const interval = setInterval(async () => {\n try {\n const muxData = await resyncAsset(asset)\n if (!muxData) return\n\n const fetchedTracks =\n muxData.tracks?.filter((track): track is MuxTextTrack => track.type === 'text') || []\n\n const isMockTrackReplaced = (\n mockTrack: MuxTextTrack,\n fetchedTracksList: MuxTextTrack[],\n ) => {\n if (!mockTrack.id || !mockTrack.id.startsWith('generating-')) {\n return false\n }\n return fetchedTracksList.some((realTrack) => {\n const nameMatches = realTrack.name === mockTrack.name\n const languageMatches = realTrack.language_code === mockTrack.language_code\n if (!nameMatches || !languageMatches) {\n return false\n }\n if (realTrack.status === 'ready') {\n const isGenerated =\n realTrack.text_source === 'generated_live' ||\n realTrack.text_source === 'generated_live_final' ||\n realTrack.text_source === 'generated_vod'\n return isGenerated\n }\n if (realTrack.status === 'preparing') {\n return true\n }\n return false\n })\n }\n\n const newAutogeneratedIds = new Set<string>()\n fetchedTracks.forEach((track) => {\n if (\n track.id &&\n (track.text_source === 'generated_live' ||\n track.text_source === 'generated_live_final' ||\n track.text_source === 'generated_vod')\n ) {\n newAutogeneratedIds.add(track.id)\n }\n })\n\n const findMatchingRealTrack = (mockTrack: MuxTextTrack, tracksList: MuxTextTrack[]) => {\n return tracksList.find((rt) => {\n const nameMatches = rt.name === mockTrack.name\n const languageMatches = rt.language_code === mockTrack.language_code\n return nameMatches && languageMatches\n })\n }\n\n setAddedTracks((prev) => {\n return prev.filter((mockTrack) => {\n if (mockTrack.id && mockTrack.id.startsWith('generating-')) {\n const replaced = isMockTrackReplaced(mockTrack, fetchedTracks)\n if (replaced) {\n const realTrack = findMatchingRealTrack(mockTrack, fetchedTracks)\n if (realTrack?.id) {\n newAutogeneratedIds.add(realTrack.id)\n setTrackActivityOrder((prevOrder) => {\n const mockOrder = prevOrder.get(mockTrack.id)\n if (mockOrder) {\n const newMap = new Map(prevOrder)\n newMap.set(realTrack.id, mockOrder)\n return newMap\n }\n return prevOrder\n })\n }\n }\n return !replaced\n }\n return true\n })\n })\n\n if (newAutogeneratedIds.size > 0) {\n setAutogeneratedTrackIds((prevIds) => {\n const updated = new Set(prevIds)\n newAutogeneratedIds.forEach((id) => updated.add(id))\n return updated\n })\n }\n } catch (error) {\n console.error('Failed to refresh asset data:', error)\n }\n }, 3000) // Poll every 3 seconds\n\n return () => clearInterval(interval)\n }, [allTracks, asset, resyncAsset])\n\n const visibleTracks = allTracks\n .filter(\n (track) =>\n track.status === 'ready' || track.status === 'preparing' || track.status === 'errored',\n )\n .sort((a, b) => {\n const orderA = trackActivityOrder.get(a.id) || 0\n const orderB = trackActivityOrder.get(b.id) || 0\n\n if (orderA > 0 && orderB > 0) {\n return orderB - orderA\n }\n\n if (orderA > 0) return -1\n if (orderB > 0) return 1\n\n const aIsPreparing = a.status === 'preparing'\n const bIsPreparing = b.status === 'preparing'\n if (aIsPreparing && !bIsPreparing) return -1\n if (!aIsPreparing && bIsPreparing) return 1\n\n const aIsAutogenerated =\n (a.id && a.id.startsWith('generating-')) || (a.id && autogeneratedTrackIds.has(a.id))\n const bIsAutogenerated =\n (b.id && b.id.startsWith('generating-')) || (b.id && autogeneratedTrackIds.has(b.id))\n if (aIsAutogenerated && !bIsAutogenerated) return -1\n if (!aIsAutogenerated && bIsAutogenerated) return 1\n\n return 0\n })\n\n const handleDownload = async (track: MuxTextTrack) => {\n if (!track.id) return\n\n setDownloadingTrackId(track.id)\n try {\n await downloadVttFile(client, asset, track)\n } catch (error) {\n toast.push({\n title: 'Failed to download VTT file',\n status: 'error',\n description: error instanceof Error ? error.message : 'Please try again',\n })\n // oxlint-disable-next-line react/todo\n } finally {\n setDownloadingTrackId(null)\n }\n }\n\n const confirmDelete = async () => {\n if (!trackToDelete || !trackToDelete.id) return\n\n const track = trackToDelete\n setTrackToDelete(null)\n setDeletingTrackId(track.id)\n try {\n if (!asset.assetId) {\n // oxlint-disable-next-line react/todo\n throw new Error('Asset ID is required')\n }\n await deleteTextTrack(client, asset.assetId, track.id)\n\n // Refresh asset data after deletion\n await resyncAsset(asset)\n\n toast.push({\n title: 'Successfully deleted caption track',\n status: 'success',\n })\n\n setAddedTracks((prev) => prev.filter((t) => t.id !== track.id))\n setUpdatedTracks((prev) => {\n const newMap = new Map(prev)\n newMap.delete(track.id)\n return newMap\n })\n setTrackActivityOrder((prev) => {\n const newMap = new Map(prev)\n newMap.delete(track.id)\n return newMap\n })\n setAutogeneratedTrackIds((prev) => {\n const updated = new Set(prev)\n updated.delete(track.id)\n return updated\n })\n } catch (error) {\n toast.push({\n title: 'Failed to delete caption track',\n status: 'error',\n description: error instanceof Error ? error.message : 'Please try again',\n })\n // oxlint-disable-next-line react/todo\n } finally {\n setDeletingTrackId(null)\n }\n }\n\n const handleAddTrack = (track: MuxTextTrack) => {\n setAddedTracks((prev) => [...prev, track])\n setTrackActivityOrder((prev) => {\n const newMap = new Map(prev)\n newMap.set(track.id, prev.size + 1)\n return newMap\n })\n setShowAddDialog(false)\n }\n\n const handleUpdateTrack = async (updatedTrack: MuxTextTrack, oldTrackId?: string) => {\n if (oldTrackId) {\n setAddedTracks((prev) => prev.filter((t) => t.id !== oldTrackId))\n setUpdatedTracks((prev) => {\n const newMap = new Map(prev)\n newMap.delete(oldTrackId)\n return newMap\n })\n setTrackActivityOrder((prev) => {\n const newMap = new Map(prev)\n newMap.delete(oldTrackId)\n return newMap\n })\n setAutogeneratedTrackIds((prev) => {\n const updated = new Set(prev)\n updated.delete(oldTrackId)\n return updated\n })\n }\n\n const isAddedTrack = addedTracks.some((t) => t.id === updatedTrack.id)\n\n if (isAddedTrack) {\n setAddedTracks((prev) => prev.map((t) => (t.id === updatedTrack.id ? updatedTrack : t)))\n } else {\n setUpdatedTracks((prev) => {\n const newMap = new Map(prev)\n newMap.set(updatedTrack.id, updatedTrack)\n return newMap\n })\n }\n\n setTrackActivityOrder((prev) => {\n const newMap = new Map(prev)\n newMap.set(updatedTrack.id, prev.size + 1)\n return newMap\n })\n\n setTrackToEdit(null)\n\n // Refresh asset data after update\n await resyncAsset(asset)\n }\n\n const getTrackSourceLabel = (track: MuxTextTrack) => {\n if (track.id && track.id.startsWith('generating-')) {\n return 'Auto-generated'\n }\n if (track.id && autogeneratedTrackIds.has(track.id)) {\n return 'Auto-generated'\n }\n if (\n track.text_source === 'generated_live_final' ||\n track.text_source === 'generated_live' ||\n track.text_source === 'generated_vod'\n ) {\n return 'Auto-generated'\n }\n if (track.text_source === 'uploaded') {\n return 'Uploaded'\n }\n return 'Custom'\n }\n\n if (visibleTracks.length === 0 && !showAddDialog) {\n return (\n <Stack gap={3}>\n <Flex justify=\"flex-end\">\n <Button\n icon={AddIcon}\n text=\"Add Caption\"\n tone=\"primary\"\n onClick={() => setShowAddDialog(true)}\n />\n </Flex>\n <Card padding={4} radius={2} tone=\"transparent\" border>\n <Text size={1} muted>\n No captions available. Add captions when uploading a video or add them manually.\n </Text>\n </Card>\n {showAddDialog && (\n <AddCaptionDialog\n asset={asset}\n onAdd={handleAddTrack}\n onClose={() => setShowAddDialog(false)}\n />\n )}\n </Stack>\n )\n }\n\n const displayedTracks =\n collapseTracks && !isExpanded ? visibleTracks.slice(0, MAX_VISIBLE_TRACKS) : visibleTracks\n const hasMoreTracks = collapseTracks && visibleTracks.length > MAX_VISIBLE_TRACKS\n\n return (\n <Stack gap={3}>\n <Flex justify=\"flex-end\">\n <Button\n icon={AddIcon}\n text=\"Add Caption\"\n tone=\"primary\"\n onClick={() => setShowAddDialog(true)}\n />\n </Flex>\n\n {displayedTracks.map((track) => (\n <TrackCard\n key={track.id}\n track={track}\n iconOnly={iconOnly}\n downloadingTrackId={downloadingTrackId}\n deletingTrackId={deletingTrackId}\n trackToEdit={trackToEdit}\n getTrackSourceLabel={getTrackSourceLabel}\n handleDownload={handleDownload}\n setTrackToEdit={setTrackToEdit}\n setTrackToDelete={setTrackToDelete}\n />\n ))}\n\n {hasMoreTracks && (\n <Flex justify=\"center\">\n <Button\n icon={isExpanded ? ChevronUpIcon : ChevronDownIcon}\n text={\n isExpanded ? 'Show less' : `Show ${visibleTracks.length - MAX_VISIBLE_TRACKS} more`\n }\n mode=\"ghost\"\n tone=\"primary\"\n onClick={() => setIsExpanded(!isExpanded)}\n />\n </Flex>\n )}\n\n {trackToDelete && (\n <Dialog\n animate\n id={dialogId}\n header=\"Delete track\"\n onClose={() => setTrackToDelete(null)}\n onClickOutside={() => setTrackToDelete(null)}\n width={1}\n >\n <Card\n padding={3}\n style={{\n minHeight: '150px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <Stack gap={3}>\n <Heading size={2}>\n Are you sure you want to delete "\n {trackToDelete.name || trackToDelete.language_code || 'Untitled'}"?\n </Heading>\n <Text size={2}>This action is irreversible</Text>\n <Stack gap={4} marginY={4}>\n <Box>\n <Button\n icon={\n deletingTrackId === trackToDelete.id ? (\n <Spinner\n style={{\n verticalAlign: 'middle',\n display: 'inline-block',\n marginTop: '-2px',\n width: '0.5em',\n height: '0.5em',\n }}\n />\n ) : (\n <TrashIcon />\n )\n }\n fontSize={2}\n padding={3}\n text=\"Delete track\"\n tone=\"critical\"\n onClick={confirmDelete}\n disabled={deletingTrackId !== null}\n />\n </Box>\n </Stack>\n </Stack>\n </Card>\n </Dialog>\n )}\n\n {showAddDialog && (\n <AddCaptionDialog\n asset={asset}\n onAdd={handleAddTrack}\n onClose={() => setShowAddDialog(false)}\n />\n )}\n\n {trackToEdit && (\n <EditCaptionDialog\n asset={asset}\n track={trackToEdit}\n onUpdate={handleUpdateTrack}\n onClose={() => setTrackToEdit(null)}\n />\n )}\n </Stack>\n )\n}\n","import {createContext, useContext, useMemo} from 'react'\n\nimport {type DialogState, type SetDialogState} from '../hooks/useDialogState'\n\ntype DialogStateContextProps = {\n dialogState: DialogState\n setDialogState: SetDialogState\n}\n\nconst DialogStateContext = createContext<DialogStateContextProps>({\n dialogState: false,\n setDialogState: () => {\n return null\n },\n})\n\ninterface DialogStateProviderProps extends DialogStateContextProps {\n children: React.ReactNode\n}\n\nexport const DialogStateProvider = ({\n dialogState,\n setDialogState,\n children,\n}: DialogStateProviderProps) => {\n const value = useMemo(() => ({dialogState, setDialogState}), [dialogState, setDialogState])\n return <DialogStateContext.Provider value={value}>{children}</DialogStateContext.Provider>\n}\n\nexport const useDialogStateContext = () => {\n const context = useContext(DialogStateContext)\n return context\n}\n","import type {SanityClient} from 'sanity'\n\nimport {generateJwt} from './generateJwt'\nimport type {MuxPlaybackId, MuxVideoUrl} from './types'\n\ninterface VideoSrcOptions {\n muxPlaybackId: MuxPlaybackId\n client: SanityClient\n}\n\n/**\n * May throw a Promise. Call this with {@link tryWithSuspend} or rethrow the Promise\n */\nexport function getVideoSrc({client, muxPlaybackId}: VideoSrcOptions): MuxVideoUrl {\n const searchParams = new URLSearchParams()\n\n if (muxPlaybackId.policy === 'signed' || muxPlaybackId.policy === 'drm') {\n const token = generateJwt(client, muxPlaybackId.id, 'v')\n searchParams.set('token', token)\n }\n\n return `https://stream.mux.com/${muxPlaybackId.id}.m3u8?${searchParams}`\n}\n","import {Dialog, Stack} from '@sanity/ui'\nimport {useId} from 'react'\n\nimport {useDialogStateContext} from '../context/DialogStateContext'\nimport type {VideoAssetDocument} from '../util/types'\nimport TextTracksManager from './TextTracksManager'\n\nexport interface Props {\n asset: VideoAssetDocument\n}\n\nexport default function CaptionsDialog({asset}: Props) {\n const {setDialogState} = useDialogStateContext()\n const dialogId = `CaptionsDialog${useId()}`\n\n return (\n <Dialog id={dialogId} header=\"Edit Captions\" onClose={() => setDialogState(false)} width={1}>\n <Stack padding={4}>\n <TextTracksManager asset={asset} />\n </Stack>\n </Dialog>\n )\n}\n","// From: https://stackoverflow.com/a/11486026/10433647\nexport function formatSeconds(seconds: number): string {\n if (typeof seconds !== 'number' || Number.isNaN(seconds)) {\n return ''\n }\n // Hours, minutes and seconds\n const hrs = ~~(seconds / 3600)\n const mins = ~~((seconds % 3600) / 60)\n const secs = ~~seconds % 60\n\n // Output like \"1:01\" or \"4:03:59\" or \"123:03:59\"\n let ret = ''\n\n if (hrs > 0) {\n ret += '' + hrs + ':' + (mins < 10 ? '0' : '')\n }\n\n ret += '' + mins + ':' + (secs < 10 ? '0' : '')\n ret += '' + secs\n return ret\n}\n\n// Output like \"05:14:01\"\nexport function formatSecondsToHHMMSS(seconds: number): string {\n const hrs = Math.floor(seconds / 3600)\n .toString()\n .padStart(2, '0')\n const mins = Math.floor((seconds % 3600) / 60)\n .toString()\n .padStart(2, '0')\n const secs = Math.floor(seconds % 60)\n .toString()\n .padStart(2, '0')\n\n return `${hrs}:${mins}:${secs}`\n}\n\n// Checks if time has a HH:MM:SS format like \"05:14:01\"\nexport function isValidTimeFormat(time: string) {\n const regex = /^([0-1]?[0-9]|2[0-3]):([0-5]?[0-9]):([0-5]?[0-9])$/\n return regex.test(time) || time === ''\n}\n\n// Converts a time like \"05:14:01\" to seconds\nexport function getSecondsFromTimeFormat(time: string): number {\n const [hh = 0, mm = 0, ss = 0] = time.split(':').map(Number)\n return hh * 3600 + mm * 60 + ss\n}\n","import {Button, Dialog, Flex, Stack, Text, TextInput} from '@sanity/ui'\nimport {type ChangeEvent, useId, useMemo, useState} from 'react'\nimport {getDevicePixelRatio} from 'use-device-pixel-ratio'\n\nimport {useDialogStateContext} from '../context/DialogStateContext'\nimport {useClient} from '../hooks/useClient'\nimport {\n formatSecondsToHHMMSS,\n getSecondsFromTimeFormat,\n isValidTimeFormat,\n} from '../util/formatSeconds'\nimport type {VideoAssetDocument} from '../util/types'\nimport VideoThumbnail from './VideoThumbnail'\n\nexport interface Props {\n asset: VideoAssetDocument\n currentTime?: number\n}\n\nexport default function EditThumbnailDialog({asset, currentTime = 0}: Props) {\n const client = useClient()\n\n const {setDialogState} = useDialogStateContext()\n const dialogId = `EditThumbnailDialog${useId()}`\n\n const [timeFormatted, setTimeFormatted] = useState<string>(() =>\n formatSecondsToHHMMSS(currentTime),\n )\n const [nextTime, setNextTime] = useState<number>(currentTime)\n const [inputError, setInputError] = useState<string>('')\n\n const assetWithNewThumbnail = useMemo(() => ({...asset, thumbTime: nextTime}), [asset, nextTime])\n const [saving, setSaving] = useState(false)\n const [saveThumbnailError, setSaveThumbnailError] = useState<Error | null>(null)\n const handleSave = () => {\n setSaving(true)\n client\n .patch(asset._id)\n .set({thumbTime: nextTime})\n .commit({returnDocuments: false})\n .then(() => setDialogState(false))\n .catch(setSaveThumbnailError)\n .finally(() => setSaving(false))\n }\n const width = 300 * getDevicePixelRatio({maxDpr: 2})\n\n if (saveThumbnailError) {\n // @TODO handle errors more gracefully\n throw saveThumbnailError\n }\n\n const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {\n const value = event.currentTarget.value\n setTimeFormatted(value)\n\n if (isValidTimeFormat(value)) {\n setInputError('')\n const totalSeconds = getSecondsFromTimeFormat(value)\n setNextTime(totalSeconds)\n } else {\n setInputError('Invalid time format')\n }\n }\n\n return (\n <Dialog\n id={dialogId}\n header=\"Edit thumbnail\"\n onClose={() => setDialogState(false)}\n footer={\n <Stack padding={3}>\n <Button\n key=\"thumbnail\"\n disabled={inputError !== ''}\n mode=\"ghost\"\n tone=\"primary\"\n loading={saving}\n onClick={handleSave}\n text=\"Set new thumbnail\"\n />\n </Stack>\n }\n >\n <Stack gap={3} padding={3}>\n <Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n Current:\n </Text>\n <VideoThumbnail asset={asset} width={width} staticImage />\n </Stack>\n <Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n New:\n </Text>\n <VideoThumbnail asset={assetWithNewThumbnail} width={width} staticImage />\n </Stack>\n\n <Stack gap={2}>\n <Flex align={'center'} justify={'center'}>\n <Text size={5} weight=\"semibold\">\n Or\n </Text>\n </Flex>\n </Stack>\n\n <Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n Selected time for thumbnail (hh:mm:ss):\n </Text>\n <TextInput\n size={1}\n value={timeFormatted}\n placeholder=\"hh:mm:ss\"\n onChange={handleInputChange}\n customValidity={inputError}\n />\n </Stack>\n </Stack>\n </Dialog>\n )\n}\n","import type {SVGProps} from 'react'\n\nexport function AudioIcon(props: SVGProps<SVGSVGElement>) {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\" {...props}>\n <path\n fill=\"currentColor\"\n style={{opacity: '0.65'}}\n 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\"\n />\n </svg>\n )\n}\n","import {Box, Dialog, Stack} from '@sanity/ui'\nimport {useId} from 'react'\n\nimport {useDialogStateContext} from '../context/DialogStateContext'\nimport {getMezzanineStatus} from '../hooks/useMezzanine'\nimport {DIALOGS_Z_INDEX} from '../util/constants'\nimport type {VideoAssetDocument} from '../util/types'\nimport Mezzanine from './Mezzanine'\nimport MezzanineExplanation from './MezzanineExplanation'\n\nexport interface Props {\n asset: VideoAssetDocument\n onClose?: () => void\n}\n\n/**\n * Player actions menu entry point: the explanation in the dialog body (until the\n * file is enabled) with the {@link Mezzanine} card below for the action/status.\n */\nexport default function MezzanineDialog({asset, onClose}: Props) {\n const {setDialogState} = useDialogStateContext()\n const dialogId = `MezzanineDialog${useId()}`\n\n const closing = () => {\n onClose?.()\n setDialogState(false)\n }\n\n const status = getMezzanineStatus(asset)\n const showExplanation = status !== 'preparing' && status !== 'ready'\n\n return (\n <Dialog\n id={dialogId}\n header=\"Mezzanine file\"\n onClose={closing}\n zOffset={DIALOGS_Z_INDEX}\n width={1}\n >\n <Box padding={4}>\n <Stack gap={4}>\n {showExplanation && <MezzanineExplanation />}\n <Mezzanine asset={asset} withExplanation={false} />\n </Stack>\n </Box>\n </Dialog>\n )\n}\n","import {type MuxPlayerProps, type MuxPlayerRefAttributes} from '@mux/mux-player-react'\nimport MuxPlayer from '@mux/mux-player-react/lazy'\nimport {ErrorOutlineIcon} from '@sanity/icons/ErrorOutline'\nimport {Card, Text} from '@sanity/ui'\nimport {type PropsWithChildren, Suspense, useMemo, useRef, useState} from 'react'\n\nimport {PLUGIN_VERSION} from '../constants'\nimport {useDialogStateContext} from '../context/DialogStateContext'\nimport {useClient} from '../hooks/useClient'\nimport {AUDIO_ASPECT_RATIO, MIN_ASPECT_RATIO} from '../util/constants'\nimport {generateJwt} from '../util/generateJwt'\nimport {getPlaybackId} from '../util/getPlaybackPolicy'\nimport {getPlaybackPolicyById} from '../util/getPlaybackPolicy'\nimport {getPosterSrc} from '../util/getPosterSrc'\nimport {getVideoSrc} from '../util/getVideoSrc'\nimport {tryWithSuspend} from '../util/tryWithSuspend'\nimport type {VideoAssetDocument} from '../util/types'\nimport CaptionsDialog from './CaptionsDialog'\nimport EditThumbnailDialog from './EditThumbnailDialog'\nimport {AudioIcon} from './icons/Audio'\nimport MezzanineDialog from './MezzanineDialog'\n\nexport default function VideoPlayer({\n asset,\n thumbnailWidth = 250,\n children,\n hlsConfig,\n ...props\n}: PropsWithChildren<\n {\n asset: VideoAssetDocument\n thumbnailWidth?: number\n forceAspectRatio?: number\n hlsConfig?: MuxPlayerProps['_hlsConfig']\n } & Partial<Pick<MuxPlayerProps, 'autoPlay'>>\n>) {\n const client = useClient()\n const {dialogState} = useDialogStateContext()\n\n const isAudio = assetIsAudio(asset)\n const muxPlayer = useRef<MuxPlayerRefAttributes>(null)\n const playerContainerRef = useRef<HTMLDivElement>(null)\n const [error, setError] = useState<Error>()\n\n /* Playback ID that will be used to play the video */\n const playbackId = useMemo(() => {\n try {\n return getPlaybackId(asset, ['public', 'signed', 'drm'])\n } catch (e) {\n // oxlint-disable-next-line react/set-state-in-render\n setError(new TypeError('Asset has no playback ID', {cause: e}))\n return undefined\n }\n }, [asset])\n\n const muxPlaybackId = useMemo(() => {\n if (!playbackId) return undefined\n return getPlaybackPolicyById(asset, playbackId)\n }, [asset, playbackId])\n\n const src = useMemo(() => {\n if (!playbackId) return undefined\n if (!muxPlaybackId) return undefined\n return tryWithSuspend(\n () => getVideoSrc({muxPlaybackId, client}),\n (e: Error) => {\n setError(e)\n return undefined\n },\n )\n }, [muxPlaybackId, playbackId, client])\n\n const poster = useMemo(() => {\n return tryWithSuspend(\n () => getPosterSrc({asset, client, width: thumbnailWidth}),\n (e: Error) => {\n setError(e)\n return undefined\n },\n )\n }, [asset, client, thumbnailWidth])\n\n const signedToken = useMemo(() => {\n try {\n const url = new URL(src!)\n return url.searchParams.get('token')\n } catch {\n return undefined\n }\n }, [src])\n const drmToken = useMemo(() => {\n if (!playbackId) return undefined\n if (muxPlaybackId?.policy !== 'drm') return undefined\n\n return tryWithSuspend(\n () => generateJwt(client, playbackId, 'd'),\n (e: Error) => {\n setError(e)\n return undefined\n },\n )\n }, [client, muxPlaybackId?.policy, playbackId])\n const tokens:\n | Partial<{\n playback?: string\n thumbnail?: string\n storyboard?: string\n drm?: string\n }>\n | undefined = useMemo(() => {\n try {\n const partialTokens: {\n playback?: string\n thumbnail?: string\n storyboard?: string\n drm?: string\n } = {\n playback: undefined,\n thumbnail: undefined,\n storyboard: undefined,\n drm: undefined,\n }\n\n if (signedToken) {\n partialTokens.playback = signedToken\n partialTokens.thumbnail = signedToken\n partialTokens.storyboard = signedToken\n }\n\n if (drmToken) {\n partialTokens.drm = drmToken\n }\n\n return {...partialTokens}\n } catch {\n return undefined\n }\n }, [signedToken, drmToken])\n\n const [width, height] = (asset?.data?.aspect_ratio ?? '16:9').split(':').map(Number)\n const targetAspectRatio =\n props.forceAspectRatio || (Number.isNaN(width) ? 16 / 9 : width! / height!)\n let aspectRatio = Math.max(MIN_ASPECT_RATIO, targetAspectRatio)\n if (isAudio) {\n aspectRatio = props.forceAspectRatio\n ? // Make it wider when forcing aspect ratio to balance with videos' rendering height (audio players overflow a bit)\n props.forceAspectRatio * 1.2\n : AUDIO_ASPECT_RATIO\n }\n\n /* We use Suspense here because `generateJwt` and related functions use suspend()\n under the hood */\n return (\n <>\n <Card\n ref={playerContainerRef}\n tone=\"transparent\"\n style={{\n aspectRatio: aspectRatio,\n position: 'relative',\n ...(isAudio && {display: 'flex', alignItems: 'flex-end'}),\n }}\n >\n {src && poster && (\n <>\n {isAudio && (\n <AudioIcon\n style={{\n padding: '0.5em',\n width: '2.2em',\n height: '2.2em',\n position: 'absolute',\n top: 0,\n left: 0,\n zIndex: 1,\n }}\n />\n )}\n <Suspense fallback={null}>\n <MuxPlayer\n poster={isAudio ? undefined : poster}\n ref={muxPlayer}\n {...props}\n playsInline\n playbackId={playbackId}\n tokens={tokens}\n preload=\"metadata\"\n crossOrigin=\"anonymous\"\n metadata={{\n player_name: 'Sanity Admin Dashboard',\n player_version: PLUGIN_VERSION,\n page_type: 'Preview Player',\n }}\n audio={isAudio}\n _hlsConfig={hlsConfig}\n style={{\n ...(!isAudio && {height: '100%'}),\n width: '100%',\n display: 'block',\n objectFit: 'contain',\n ...(isAudio && {alignSelf: 'end'}),\n }}\n />\n {children}\n </Suspense>\n </>\n )}\n {error ? (\n <div\n style={{\n position: 'absolute',\n top: '50%',\n left: '50%',\n transform: 'translate(-50%, -50%)',\n }}\n >\n <Text muted>\n <ErrorOutlineIcon style={{marginRight: '0.15em'}} />\n {typeof error === 'object' && 'message' in error && typeof error.message === 'string'\n ? error.message\n : 'Error loading video'}\n </Text>\n </div>\n ) : null}\n {children}\n </Card>\n\n {dialogState === 'edit-thumbnail' && (\n <EditThumbnailDialog\n asset={asset}\n // oxlint-disable-next-line react/refs\n currentTime={muxPlayer?.current?.currentTime}\n />\n )}\n {dialogState === 'edit-captions' && <CaptionsDialog asset={asset} />}\n {dialogState === 'mezzanine' && <MezzanineDialog asset={asset} />}\n </>\n )\n}\n\nexport function assetIsAudio(asset: VideoAssetDocument) {\n return asset.data?.max_stored_resolution === 'Audio only'\n}\n","// Adapted from https://github.com/sanity-io/sanity/blob/next/packages/sanity/src/desk/components/MissingSchemaType.tsx\nimport {WarningOutlineIcon} from '@sanity/icons/WarningOutline'\nimport type {SanityDocument} from 'sanity'\nimport type {GeneralPreviewLayoutKey} from 'sanity'\nimport {SanityDefaultPreview} from 'sanity'\n\nexport interface MissingSchemaTypeProps {\n layout?: GeneralPreviewLayoutKey\n value: SanityDocument\n}\n\nconst getUnknownTypeFallback = (id: string, typeName: string) => ({\n title: (\n <em>\n No schema found for type <code>{typeName}</code>\n </em>\n ),\n subtitle: (\n <em>\n Document: <code>{id}</code>\n </em>\n ),\n media: () => <WarningOutlineIcon />,\n})\n\nexport function MissingSchemaType(props: MissingSchemaTypeProps) {\n const {layout, value} = props\n\n return (\n <SanityDefaultPreview {...getUnknownTypeFallback(value._id, value._type)} layout={layout} />\n )\n}\n","// Adapted from https://github.com/sanity-io/sanity/blob/next/packages/sanity/src/desk/components/TimeAgo.tsx\nimport {useRelativeTime} from 'sanity'\n\nexport interface TimeAgoProps {\n time: string | Date\n}\n\nexport function TimeAgo({time}: TimeAgoProps) {\n const timeAgo = useRelativeTime(time, {useTemporalPhrase: true})\n\n return <span title={timeAgo}>{timeAgo}</span>\n}\n","// Adapted from https://github.com/sanity-io/sanity/blob/next/packages/sanity/src/desk/components/DraftStatus.tsx\nimport {EditIcon} from '@sanity/icons/Edit'\nimport {Box, Text} from '@sanity/ui'\nimport {Tooltip} from '@sanity/ui/tooltip'\nimport type {PreviewValue, SanityDocument} from 'sanity'\nimport {TextWithTone} from 'sanity'\n\nimport {TimeAgo} from './TimeAgo'\n\nexport function DraftStatus(props: {document?: PreviewValue | Partial<SanityDocument> | null}) {\n const {document} = props\n const updatedAt = document && '_updatedAt' in document && document._updatedAt\n\n return (\n <Tooltip\n animate\n portal\n content={\n <Box padding={2}>\n <Text size={1}>\n {document ? (\n <>Edited {updatedAt && <TimeAgo time={updatedAt} />}</>\n ) : (\n <>No unpublished edits</>\n )}\n </Text>\n </Box>\n }\n >\n <TextWithTone tone=\"caution\" dimmed={!document} muted={!document} size={1}>\n <EditIcon />\n </TextWithTone>\n </Tooltip>\n )\n}\n","// Adapted from https://github.com/sanity-io/sanity/blob/next/packages/sanity/src/desk/components/PublishedStatus.tsx\n\nimport {PublishIcon} from '@sanity/icons/Publish'\nimport {Box, Text} from '@sanity/ui'\nimport {Tooltip} from '@sanity/ui/tooltip'\nimport type {PreviewValue, SanityDocument} from 'sanity'\nimport {TextWithTone} from 'sanity'\n\nimport {TimeAgo} from './TimeAgo'\n\nexport function PublishedStatus(props: {document?: PreviewValue | Partial<SanityDocument> | null}) {\n const {document} = props\n const updatedAt = document && '_updatedAt' in document && document._updatedAt\n\n return (\n <Tooltip\n animate\n portal\n content={\n <Box padding={2}>\n <Text size={1}>\n {document ? (\n <>Published {updatedAt && <TimeAgo time={updatedAt} />}</>\n ) : (\n <>Not published</>\n )}\n </Text>\n </Box>\n }\n >\n <TextWithTone tone=\"positive\" dimmed={!document} muted={!document} size={1}>\n <PublishIcon />\n </TextWithTone>\n </Tooltip>\n )\n}\n","// Adapted from:\n// https://github.com/sanity-io/sanity/blob/current/packages/sanity/src/structure/components/paneItem/PaneItemPreview.tsx\nimport {Inline} from '@sanity/ui'\nimport {isNumber, isString} from 'lodash'\nimport {isValidElement, useMemo} from 'react'\nimport {useObservable} from 'react-rx'\nimport type {SanityDocument, SchemaType} from 'sanity'\nimport {\n type DocumentPresence,\n DocumentPreviewPresence,\n type DocumentPreviewStore,\n type GeneralPreviewLayoutKey,\n getPreviewStateObservable,\n getPreviewValueWithFallback,\n isRecord,\n SanityDefaultPreview,\n} from 'sanity'\n\nimport {DraftStatus} from './DraftStatus'\nimport {PublishedStatus} from './PublishedStatus'\n\nexport interface PaneItemPreviewProps {\n documentPreviewStore: DocumentPreviewStore\n icon: React.ComponentType | false\n layout: GeneralPreviewLayoutKey\n presence?: DocumentPresence[]\n schemaType: SchemaType\n value: SanityDocument\n}\n\nconst INITIAL_PREVIEW_STATE = {\n snapshot: null,\n isLoading: true,\n original: null,\n}\n\nexport function PaneItemPreview(props: PaneItemPreviewProps) {\n const {icon, layout, presence, schemaType, value} = props\n const title =\n (isRecord(value['title']) && isValidElement(value['title'])) ||\n isString(value['title']) ||\n isNumber(value['title'])\n ? value['title']\n : null\n\n const previewStateObservable = useMemo(\n () => getPreviewStateObservable(props.documentPreviewStore, schemaType, value._id),\n [props.documentPreviewStore, schemaType, value._id],\n )\n const {snapshot, original, isLoading} = useObservable(\n previewStateObservable,\n INITIAL_PREVIEW_STATE,\n )\n\n const status = isLoading ? null : (\n <Inline gap={4}>\n {presence && presence.length > 0 && <DocumentPreviewPresence presence={presence} />}\n <PublishedStatus document={original} />\n <DraftStatus document={snapshot} />\n </Inline>\n )\n\n return (\n <SanityDefaultPreview\n {...(getPreviewValueWithFallback({snapshot, original, fallback: {title}}) as any)}\n isPlaceholder={isLoading}\n icon={icon}\n layout={layout}\n status={status}\n />\n )\n}\n","// Adapted from https://github.com/sanity-io/sanity/blob/next/packages/sanity/src/desk/components/paneItem/PaneItem.tsx\n\nimport {DocumentIcon} from '@sanity/icons/Document'\nimport {useMemo} from 'react'\nimport type {CollatedHit, SanityDocument, SchemaType} from 'sanity'\nimport {PreviewCard, useDocumentPresence, useDocumentPreviewStore, useSchema} from 'sanity'\nimport {IntentLink} from 'sanity/router'\n\nimport {MissingSchemaType} from './MissingSchemaType'\nimport {PaneItemPreview} from './PaneItemPreview'\n\ninterface DocumentPreviewProps {\n schemaType?: SchemaType\n documentPair: CollatedHit<SanityDocument>\n}\n\n/**\n * Return `false` if we explicitly disable the icon.\n * Otherwise return the passed icon or the schema type icon as a backup.\n */\nfunction getIconWithFallback(\n icon: React.ComponentType<any> | false | undefined,\n schemaType: SchemaType | undefined,\n defaultIcon: React.ComponentType<any>,\n): React.ComponentType<any> | false {\n if (icon === false) {\n return false\n }\n\n return icon || ((schemaType && schemaType.icon) as any) || defaultIcon || false\n}\n\nexport function DocumentPreview(props: DocumentPreviewProps) {\n const {schemaType, documentPair} = props\n const doc = documentPair?.draft || documentPair?.published\n const id = documentPair.id || ''\n const documentPreviewStore = useDocumentPreviewStore()\n const schema = useSchema()\n const documentPresence = useDocumentPresence(id)\n const hasSchemaType = Boolean(schemaType && schemaType.name && schema.get(schemaType.name))\n\n const children = useMemo(() => {\n if (!doc) return null\n\n if (!schemaType || !hasSchemaType) {\n return <MissingSchemaType value={doc} />\n }\n\n return (\n <PaneItemPreview\n documentPreviewStore={documentPreviewStore}\n icon={getIconWithFallback(undefined, schemaType, DocumentIcon)}\n schemaType={schemaType}\n layout=\"default\"\n value={doc}\n presence={documentPresence}\n />\n )\n }, [hasSchemaType, schemaType, documentPresence, doc, documentPreviewStore])\n\n return (\n <PreviewCard\n __unstable_focusRing\n as={IntentLink}\n intent=\"edit\"\n params={{id: props.documentPair.id}}\n data-as=\"a\"\n data-ui=\"PaneItem\"\n padding={2}\n radius={2}\n tone=\"inherit\"\n >\n {children}\n </PreviewCard>\n )\n}\n","import type {SanityDocument} from '@sanity/client'\nimport {Box, Card, Text} from '@sanity/ui'\nimport {collate, useSchema} from 'sanity'\nimport {styled} from 'styled-components'\n\nimport {DocumentPreview} from '../documentPreview/DocumentPreview'\nimport SpinnerBox from '../SpinnerBox'\n\nconst Container = styled(Box)`\n * {\n color: ${(props: any) => props.theme.sanity.color.base.fg};\n }\n a {\n text-decoration: none;\n }\n h2 {\n font-size: ${(props: any) => props.theme.sanity.fonts.text.sizes[1]};\n }\n`\n\nconst VideoReferences: React.FC<{\n references?: SanityDocument[]\n isLoaded: boolean\n}> = (props) => {\n const schema = useSchema()\n if (!props.isLoaded) {\n return <SpinnerBox />\n }\n\n if (!props.references?.length) {\n return (\n <Card border radius={3} padding={3}>\n <Text size={2}>No documents are using this video</Text>\n </Card>\n )\n }\n\n const documentPairs = collate(props.references || [])\n return (\n <Container>\n {documentPairs?.map((documentPair) => {\n const schemaType = schema.get(documentPair.type)\n\n return (\n <Card\n key={documentPair.id}\n marginBottom={2}\n padding={2}\n radius={2}\n shadow={1}\n style={{overflow: 'hidden'}}\n >\n <Box>\n <DocumentPreview documentPair={documentPair} schemaType={schemaType} />\n </Box>\n </Card>\n )\n })}\n </Container>\n )\n}\n\nexport default VideoReferences\n","import {TrashIcon} from '@sanity/icons/Trash'\nimport {Box, Button, Card, Checkbox, Dialog, Flex, Heading, Stack, Text} from '@sanity/ui'\nimport {useToast} from '@sanity/ui/toast'\nimport {useEffect, useState} from 'react'\nimport type {SanityDocument} from 'sanity'\n\nimport {deleteAsset} from '../../actions/assets'\nimport {useClient} from '../../hooks/useClient'\nimport {DIALOGS_Z_INDEX} from '../../util/constants'\nimport type {VideoAssetDocument} from '../../util/types'\nimport SpinnerBox from '../SpinnerBox'\nimport VideoReferences from './VideoReferences'\n\nexport default function DeleteDialog({\n asset,\n references,\n referencesLoading,\n cancelDelete,\n succeededDeleting,\n}: {\n asset: VideoAssetDocument\n references?: SanityDocument[]\n referencesLoading: boolean\n cancelDelete: () => void\n succeededDeleting: () => void\n}) {\n const client = useClient()\n const [state, setState] = useState<\n 'processing_deletion' | 'checkingReferences' | 'error_deleting' | 'cantDelete' | 'confirm'\n >('checkingReferences')\n const [deleteOnMux, setDeleteOnMux] = useState(true)\n const toast = useToast()\n\n useEffect(() => {\n if (state !== 'checkingReferences' || referencesLoading) return\n\n // oxlint-disable-next-line react/set-state-in-effect\n setState(references?.length ? 'cantDelete' : 'confirm')\n }, [state, references, referencesLoading])\n\n async function confirmDelete() {\n if (state !== 'confirm') return\n\n setState('processing_deletion')\n const worked = await deleteAsset({client, asset, deleteOnMux})\n if (worked === true) {\n toast.push({title: 'Successfully deleted video', status: 'success'})\n succeededDeleting()\n } else if (worked === 'failed-mux') {\n toast.push({\n title: 'Deleted video in Sanity',\n description: \"But it wasn't deleted in Mux\",\n status: 'warning',\n })\n succeededDeleting()\n } else {\n toast.push({title: 'Failed deleting video', status: 'error'})\n\n setState('error_deleting')\n }\n }\n\n return (\n <Dialog\n animate\n header={'Delete video'}\n zOffset={DIALOGS_Z_INDEX}\n id=\"deleting-video-details-dialog\"\n onClose={cancelDelete}\n onClickOutside={cancelDelete}\n width={1}\n position=\"fixed\"\n >\n <Card\n padding={3}\n style={{\n minHeight: '150px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <Stack gap={3}>\n {state === 'checkingReferences' && (\n <>\n <Heading size={2}>Checking if video can be deleted</Heading>\n <SpinnerBox />\n </>\n )}\n {state === 'cantDelete' && (\n <>\n <Heading size={2}>Video can't be deleted</Heading>\n <Text size={2} style={{marginBottom: '2rem'}}>\n There are {references?.length} document{references && references.length > 0 && 's'}{' '}\n pointing to this video. Remove their references to this file or delete them before\n proceeding.\n </Text>\n <VideoReferences references={references} isLoaded={!referencesLoading} />\n </>\n )}\n {state === 'confirm' && (\n <>\n <Heading size={2}>Are you sure you want to delete this video?</Heading>\n <Text size={2}>This action is irreversible</Text>\n <Stack gap={4} marginY={4}>\n <Flex align=\"center\" as=\"label\">\n <Checkbox\n checked={deleteOnMux}\n onChange={() => setDeleteOnMux((prev) => !prev)}\n />\n <Text style={{margin: '0 10px'}}>Delete asset on Mux</Text>\n </Flex>\n <Flex align=\"center\" as=\"label\">\n <Checkbox disabled checked />\n <Text style={{margin: '0 10px'}}>Delete video from dataset</Text>\n </Flex>\n <Box>\n <Button\n icon={TrashIcon}\n fontSize={2}\n padding={3}\n text=\"Delete video\"\n tone=\"critical\"\n onClick={confirmDelete}\n disabled={['processing_deletion', 'checkingReferences', 'cantDelete'].some(\n (s) => s === state,\n )}\n />\n </Box>\n </Stack>\n </>\n )}\n {state === 'processing_deletion' && (\n <>\n <Heading size={2}>Deleting video...</Heading>\n <SpinnerBox />\n </>\n )}\n {state === 'error_deleting' && (\n <>\n <Heading size={2}>Something went wrong!</Heading>\n <Text size={2}>Try deleting the video again by clicking the button below</Text>\n </>\n )}\n </Stack>\n </Card>\n </Dialog>\n )\n}\n","import {createHookFromObservableFactory, type DocumentStore, type SanityDocument} from 'sanity'\n\nimport {SANITY_API_VERSION} from './useClient'\n\nconst useDocReferences = createHookFromObservableFactory<\n SanityDocument[],\n {\n documentStore: DocumentStore\n id: string\n }\n>(({documentStore, id}) => {\n return documentStore.listenQuery(\n /* groq */ '*[references($id)]{_id, _type, _rev, _updatedAt, _createdAt}',\n {id},\n {\n apiVersion: SANITY_API_VERSION,\n },\n )\n})\n\nexport default useDocReferences\n","import {formatSeconds} from './formatSeconds'\nimport type {MuxTextTrack, VideoAssetDocument} from './types'\n\nexport default function getVideoMetadata(doc: VideoAssetDocument) {\n const id = doc.assetId || doc._id || ''\n const date = doc.data?.created_at\n ? new Date(Number(doc.data.created_at) * 1000)\n : new Date(doc._createdAt || doc._updatedAt || Date.now())\n\n return {\n title: doc.filename || id.slice(0, 12),\n id: id,\n playbackId: doc.playbackId,\n createdAt: date,\n duration: doc.data?.duration ? formatSeconds(doc.data?.duration) : undefined,\n playback_ids: doc.data?.playback_ids,\n aspect_ratio: doc.data?.aspect_ratio,\n max_stored_resolution: doc.data?.max_stored_resolution,\n max_stored_frame_rate: doc.data?.max_stored_frame_rate,\n text_tracks:\n doc.data?.tracks?.filter((track): track is MuxTextTrack => track.type === 'text') || [],\n }\n}\n","import {useToast} from '@sanity/ui/toast'\nimport {useMemo, useState} from 'react'\nimport {useDocumentStore} from 'sanity'\n\nimport {useClient} from '../../hooks/useClient'\nimport useDocReferences from '../../hooks/useDocReferences'\nimport {useResyncAsset} from '../../hooks/useResyncAsset'\nimport getVideoMetadata from '../../util/getVideoMetadata'\nimport {type VideoAssetDocument} from '../../util/types'\n\ntype VideoDetailsState = 'idle' | 'saving' | 'deleting' | 'closing' | 'resyncing'\n\nexport interface VideoDetailsProps {\n closeDialog: () => void\n asset: VideoAssetDocument & {autoPlay?: boolean}\n}\n\nexport default function useVideoDetails(props: VideoDetailsProps) {\n const documentStore = useDocumentStore()\n const toast = useToast()\n const client = useClient()\n\n const [references, referencesLoading] = useDocReferences(\n useMemo(() => ({documentStore, id: props.asset._id}), [documentStore, props.asset._id]),\n )\n\n const [originalAsset, setOriginalAsset] = useState(() => props.asset)\n const [filename, setFilename] = useState(props.asset.filename)\n const modified = filename !== originalAsset.filename\n\n const displayInfo = getVideoMetadata({...props.asset, filename})\n\n const [state, setState] = useState<VideoDetailsState>('idle')\n\n const {resyncAsset, isResyncing} = useResyncAsset({showToast: true})\n\n async function handleResync() {\n if (state !== 'idle') return\n setState('resyncing')\n await resyncAsset(props.asset)\n setState('idle')\n }\n\n function handleClose() {\n if (state !== 'idle') return\n\n if (modified) {\n setState('closing')\n return\n }\n\n props.closeDialog()\n }\n\n function confirmClose(shouldClose: boolean) {\n if (state !== 'closing') return\n\n if (shouldClose) props.closeDialog()\n\n setState('idle')\n }\n\n async function saveChanges() {\n if (state !== 'idle') return\n setState('saving')\n\n try {\n await client.patch(props.asset._id).set({filename}).commit()\n setOriginalAsset((prev) => ({...prev, filename}))\n toast.push({\n title: 'Video title updated',\n description: `New title: ${filename}`,\n status: 'success',\n })\n props.closeDialog()\n } catch (error) {\n toast.push({\n title: 'Failed updating file name',\n status: 'error',\n description: typeof error === 'string' ? error : 'Please try again',\n })\n setFilename(originalAsset.filename)\n }\n\n setState('idle')\n }\n\n return {\n references,\n referencesLoading,\n modified,\n filename,\n setFilename,\n displayInfo,\n state,\n setState,\n handleClose,\n confirmClose,\n saveChanges,\n handleResync,\n isResyncing,\n }\n}\n","import {CalendarIcon} from '@sanity/icons/Calendar'\nimport {CheckmarkIcon} from '@sanity/icons/Checkmark'\nimport {ClockIcon} from '@sanity/icons/Clock'\nimport {CropIcon} from '@sanity/icons/Crop'\nimport {EditIcon} from '@sanity/icons/Edit'\nimport {ErrorOutlineIcon} from '@sanity/icons/ErrorOutline'\nimport {RevertIcon} from '@sanity/icons/Revert'\nimport {SearchIcon} from '@sanity/icons/Search'\nimport {SyncIcon} from '@sanity/icons/Sync'\nimport {TagIcon} from '@sanity/icons/Tag'\nimport {TrashIcon} from '@sanity/icons/Trash'\nimport {\n Button,\n Card,\n Dialog,\n Flex,\n Heading,\n Spinner,\n Stack,\n Tab,\n TabList,\n TabPanel,\n Text,\n TextInput,\n} from '@sanity/ui'\nimport {type InputEvent, useEffect, useRef, useState} from 'react'\n\nimport {DIALOGS_Z_INDEX} from '../../util/constants'\nimport type {MuxPlaybackId, MuxTextTrack, PlaybackPolicy} from '../../util/types'\nimport FormField from '../FormField'\nimport IconInfo from '../IconInfo'\nimport {ResolutionIcon} from '../icons/Resolution'\nimport {StopWatchIcon} from '../icons/StopWatch'\nimport Mezzanine from '../Mezzanine'\nimport TextTracksManager from '../TextTracksManager'\nimport VideoPlayer from '../VideoPlayer'\nimport DeleteDialog from './DeleteDialog'\nimport useVideoDetails, {type VideoDetailsProps} from './useVideoDetails'\nimport VideoReferences from './VideoReferences'\n\nconst AssetInput: React.FC<{\n label: string\n description?: string\n placeholder?: string\n value: string\n onInput: (e: InputEvent<HTMLInputElement>) => void\n disabled?: boolean\n}> = (props) => (\n <FormField title={props.label} description={props.description} inputId={props.label}>\n <TextInput\n id={props.label}\n value={props.value}\n placeholder={props.placeholder}\n onInput={props.onInput}\n disabled={props.disabled}\n />\n </FormField>\n)\n\nconst VideoDetails: React.FC<VideoDetailsProps> = (props) => {\n const [tab, setTab] = useState<'details' | 'references'>('details')\n const {\n displayInfo,\n filename,\n modified,\n references,\n referencesLoading,\n setFilename,\n state,\n setState,\n handleClose,\n confirmClose,\n saveChanges,\n handleResync,\n isResyncing,\n } = useVideoDetails(props)\n\n const isSaving = state === 'saving'\n\n // Avoid layout shifts in large screens' 2-column dialog by setting their `minHeight` to the container's\n const [containerHeight, setContainerHeight] = useState<number | null>(null)\n const contentsRef = useRef<HTMLDivElement>(null)\n useEffect(() => {\n if (!contentsRef.current || !('getBoundingClientRect' in contentsRef.current)) return\n\n setContainerHeight(contentsRef.current.getBoundingClientRect().height)\n }, [])\n\n return (\n <Dialog\n animate\n header={displayInfo.title}\n zOffset={DIALOGS_Z_INDEX}\n id=\"video-details-dialog\"\n onClose={handleClose}\n onClickOutside={handleClose}\n width={2}\n position=\"fixed\"\n footer={\n <Card padding={3}>\n <Flex justify=\"space-between\" align=\"center\">\n <Flex gap={2}>\n <Button\n icon={TrashIcon}\n fontSize={2}\n padding={3}\n mode=\"bleed\"\n text=\"Delete\"\n tone=\"critical\"\n onClick={() => setState('deleting')}\n disabled={isSaving || isResyncing}\n />\n <Button\n icon={SyncIcon}\n fontSize={2}\n padding={3}\n mode=\"bleed\"\n text=\"Resync\"\n tone=\"primary\"\n onClick={handleResync}\n disabled={isSaving || isResyncing}\n iconRight={isResyncing && Spinner}\n />\n </Flex>\n {modified && (\n <Button\n icon={CheckmarkIcon}\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Save and close\"\n tone=\"positive\"\n onClick={saveChanges}\n iconRight={isSaving && Spinner}\n disabled={isSaving || isResyncing}\n />\n )}\n </Flex>\n </Card>\n }\n >\n {/* DELETION DIALOG */}\n {state === 'deleting' && (\n <DeleteDialog\n asset={props.asset}\n cancelDelete={() => setState('idle')}\n referencesLoading={referencesLoading}\n references={references}\n succeededDeleting={() => {\n props.closeDialog()\n }}\n />\n )}\n\n {/* CONFIRM CLOSING DIALOG */}\n {state === 'closing' && (\n <Dialog\n animate\n header={'You have unsaved changes'}\n zOffset={DIALOGS_Z_INDEX}\n id=\"closing-video-details-dialog\"\n onClose={() => confirmClose(false)}\n onClickOutside={() => confirmClose(false)}\n width={1}\n position=\"fixed\"\n footer={\n <Card padding={3}>\n <Flex justify=\"space-between\" align=\"center\">\n <Button\n icon={ErrorOutlineIcon}\n fontSize={2}\n padding={3}\n text=\"Discard changes\"\n tone=\"critical\"\n onClick={() => confirmClose(true)}\n />\n {modified && (\n <Button\n icon={RevertIcon}\n fontSize={2}\n padding={3}\n mode=\"ghost\"\n text=\"Keep editing\"\n tone=\"primary\"\n onClick={() => confirmClose(false)}\n />\n )}\n </Flex>\n </Card>\n }\n >\n <Card padding={5}>\n <Stack style={{textAlign: 'center'}} gap={3}>\n <Heading size={2}>Unsaved changes will be lost</Heading>\n <Text size={2}>Are you sure you want to discard them?</Text>\n </Stack>\n </Card>\n </Dialog>\n )}\n <Card\n padding={4}\n sizing=\"border\"\n style={{\n containerType: 'inline-size',\n }}\n >\n <Flex\n sizing=\"border\"\n gap={4}\n direction={['column', 'column', 'row']}\n align=\"flex-start\"\n ref={contentsRef}\n style={\n typeof containerHeight === 'number'\n ? {\n minHeight: containerHeight,\n }\n : undefined\n }\n >\n <Stack gap={4} flex={1} sizing=\"border\">\n <VideoPlayer asset={props.asset} autoPlay={props.asset.autoPlay || false} />\n {tab === 'details' && (\n <>\n <TextTracksManager\n asset={props.asset}\n iconOnly\n collapseTracks\n tracks={\n displayInfo?.text_tracks ||\n props.asset.data?.tracks?.filter(\n (track): track is MuxTextTrack => track.type === 'text',\n ) ||\n []\n }\n />\n <Mezzanine asset={props.asset} />\n </>\n )}\n </Stack>\n <Stack gap={4} flex={1} sizing=\"border\">\n <TabList gap={2}>\n <Tab\n aria-controls=\"details-panel\"\n icon={EditIcon}\n id=\"details-tab\"\n label=\"Details\"\n onClick={() => setTab('details')}\n selected={tab === 'details'}\n />\n <Tab\n aria-controls=\"references-panel\"\n icon={SearchIcon}\n id=\"references-tab\"\n label={`Used by ${references ? `(${references.length})` : ''}`}\n onClick={() => setTab('references')}\n selected={tab === 'references'}\n />\n </TabList>\n <TabPanel\n aria-labelledby=\"details-tab\"\n id=\"details-panel\"\n hidden={tab !== 'details'}\n style={{wordBreak: 'break-word'}}\n >\n <Stack gap={4}>\n <AssetInput\n label=\"Video title or file name\"\n description=\"Not visible to users. Useful for finding videos later.\"\n value={filename || ''}\n onInput={(e) => setFilename(e.currentTarget.value)}\n disabled={state !== 'idle'}\n />\n <Stack gap={3}>\n {displayInfo?.duration && (\n <IconInfo\n text={`Duration: ${displayInfo.duration}`}\n icon={ClockIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_resolution && (\n <IconInfo\n text={`Max Resolution: ${displayInfo.max_stored_resolution}`}\n icon={ResolutionIcon}\n size={2}\n />\n )}\n {displayInfo?.max_stored_frame_rate && (\n <IconInfo\n text={`Frame rate: ${displayInfo.max_stored_frame_rate}`}\n icon={StopWatchIcon}\n size={2}\n />\n )}\n {displayInfo?.aspect_ratio && (\n <IconInfo\n text={`Aspect Ratio: ${displayInfo.aspect_ratio}`}\n icon={CropIcon}\n size={2}\n />\n )}\n <IconInfo\n text={`Uploaded on: ${displayInfo.createdAt.toLocaleDateString('en', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })}`}\n icon={CalendarIcon}\n size={2}\n />\n <IconInfo text={`Mux ID: \\n${displayInfo.id}`} icon={TagIcon} size={2} />\n <PlaybackIds playback_ids={displayInfo.playback_ids} />\n </Stack>\n </Stack>\n </TabPanel>\n <TabPanel\n aria-labelledby=\"references-tab\"\n id=\"references-panel\"\n hidden={tab !== 'references'}\n >\n <VideoReferences references={references} isLoaded={!referencesLoading} />\n </TabPanel>\n </Stack>\n </Flex>\n </Card>\n </Dialog>\n )\n}\n\nconst PlaybackIds = ({playback_ids}: {playback_ids?: MuxPlaybackId[]}) => {\n if (playback_ids) {\n return playback_ids.map((entry) => (\n <IconInfo\n key={entry.id}\n text={`Playback ID [${policyToText(entry.policy)}]: ${entry.id}`}\n icon={TagIcon}\n size={2}\n />\n ))\n }\n return <IconInfo text={'No Playback ID'} icon={TagIcon} size={2} />\n}\n\nconst policyToText = (policy: PlaybackPolicy) => {\n switch (policy) {\n case 'drm':\n return 'DRM'\n case 'signed':\n return 'Signed'\n case 'public':\n return 'Public'\n default:\n return policy\n }\n}\nexport default VideoDetails\n","import {CalendarIcon} from '@sanity/icons/Calendar'\nimport {ClockIcon} from '@sanity/icons/Clock'\nimport {TagIcon} from '@sanity/icons/Tag'\nimport {Inline, Stack, Text} from '@sanity/ui'\n\nimport getVideoMetadata from '../util/getVideoMetadata'\nimport type {VideoAssetDocument} from '../util/types'\nimport IconInfo from './IconInfo'\n\nconst VideoMetadata = (props: {asset: VideoAssetDocument}) => {\n if (!props.asset) {\n return null\n }\n\n const displayInfo = getVideoMetadata(props.asset)\n return (\n <Stack gap={2}>\n {displayInfo.title && (\n <Text\n size={1}\n weight=\"semibold\"\n style={{\n wordWrap: 'break-word',\n }}\n >\n {displayInfo.title}\n </Text>\n )}\n <Inline gap={3}>\n {displayInfo?.duration && (\n <IconInfo text={displayInfo.duration} icon={ClockIcon} size={1} muted />\n )}\n <IconInfo\n text={displayInfo.createdAt.toISOString().split('T')[0]!}\n icon={CalendarIcon}\n size={1}\n muted\n />\n {displayInfo.title != displayInfo.id.slice(0, 12) && (\n <IconInfo text={displayInfo.id.slice(0, 12)} icon={TagIcon} size={1} muted />\n )}\n </Inline>\n </Stack>\n )\n}\n\nexport default VideoMetadata\n","import {CheckmarkIcon} from '@sanity/icons/Checkmark'\nimport {EditIcon} from '@sanity/icons/Edit'\nimport {LockIcon} from '@sanity/icons/Lock'\nimport {PlayIcon} from '@sanity/icons/Play'\nimport {Button, Card, Stack, Text} from '@sanity/ui'\nimport {Tooltip} from '@sanity/ui/tooltip'\nimport {useCallback, useState} from 'react'\nimport {styled} from 'styled-components'\n\nimport {DRMWarningDialog, useDrmPlaybackWarningContext} from '../context/DrmPlaybackWarningContext'\nimport {THUMBNAIL_ASPECT_RATIO} from '../util/constants'\nimport {getPlaybackPolicy} from '../util/getPlaybackPolicy'\nimport {type VideoAssetDocument} from '../util/types'\nimport IconInfo from './IconInfo'\nimport {AudioIcon} from './icons/Audio'\nimport VideoMetadata from './VideoMetadata'\nimport VideoPlayer, {assetIsAudio} from './VideoPlayer'\nimport VideoThumbnail from './VideoThumbnail'\n\nconst PlayButton = styled.button`\n display: block;\n padding: 0;\n margin: 0;\n border: none;\n border-radius: 0.1875rem;\n position: relative;\n cursor: pointer;\n\n &::after {\n content: '';\n background: var(--card-fg-color);\n opacity: 0;\n display: block;\n position: absolute;\n inset: 0;\n z-index: 10;\n transition: 0.15s ease-out;\n border-radius: inherit;\n }\n\n > div[data-play] {\n z-index: 11;\n opacity: 0;\n transition: 0.15s 0.05s ease-out;\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n color: var(--card-fg-color);\n background: var(--card-bg-color);\n width: auto;\n height: 30%;\n aspect-ratio: 1;\n border-radius: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n box-sizing: border-box;\n > svg {\n display: block;\n width: 70%;\n height: auto;\n // Visual balance to center-align the icon\n transform: translateX(5%);\n }\n }\n\n &:hover,\n &:focus {\n &::after {\n opacity: 0.3;\n }\n > div[data-play] {\n opacity: 1;\n }\n }\n`\n\ntype RenderState = 'render-video' | 'pre-render-warn' | false\n\nexport default function VideoInBrowser({\n onSelect,\n onEdit,\n asset,\n}: {\n onSelect?: (asset: VideoAssetDocument) => void\n onEdit?: (asset: VideoAssetDocument) => void\n asset: VideoAssetDocument\n}) {\n const [renderVideo, setRenderVideo] = useState<RenderState>(false)\n const select = useCallback(() => onSelect?.(asset), [onSelect, asset])\n const edit = useCallback(() => onEdit?.(asset), [onEdit, asset])\n const {hasShownWarning} = useDrmPlaybackWarningContext()\n\n if (!asset) {\n return null\n }\n\n const playbackPolicy = getPlaybackPolicy(asset)\n const onClickPlay = () => {\n if (playbackPolicy?.policy === 'drm' && !hasShownWarning) {\n setRenderVideo('pre-render-warn')\n } else {\n setRenderVideo('render-video')\n }\n }\n return (\n <Card\n border\n padding={2}\n sizing=\"border\"\n radius={2}\n style={{\n position: 'relative',\n }}\n >\n {playbackPolicy?.policy === 'signed' && (\n <Tooltip\n animate\n content={\n <Card padding={2} radius={2}>\n <IconInfo icon={LockIcon} text=\"Signed playback policy\" size={2} />\n </Card>\n }\n placement=\"right\"\n fallbackPlacements={['top', 'bottom']}\n portal\n >\n <Card\n tone=\"caution\"\n style={{\n borderRadius: '100%',\n position: 'absolute',\n left: '1em',\n top: '1em',\n zIndex: 11,\n }}\n padding={2}\n border\n >\n <Text muted size={1}>\n <LockIcon />\n </Text>\n </Card>\n </Tooltip>\n )}\n {playbackPolicy?.policy === 'drm' && (\n <Tooltip\n animate\n content={\n <Card padding={2} radius={2}>\n <IconInfo icon={LockIcon} text=\"DRM playback policy\" size={2} />\n </Card>\n }\n placement=\"right\"\n fallbackPlacements={['top', 'bottom']}\n portal\n >\n <Card\n tone=\"caution\"\n style={{\n borderRadius: '0.25rem',\n position: 'absolute',\n left: '1em',\n top: '1em',\n zIndex: 11,\n }}\n padding={2}\n border\n >\n <Text muted size={1} weight=\"semibold\" style={{color: 'var(--card-icon-color)'}}>\n DRM\n </Text>\n </Card>\n </Tooltip>\n )}\n <Stack\n gap={3}\n height=\"fill\"\n style={{\n gridTemplateRows: 'min-content min-content 1fr',\n }}\n >\n {renderVideo === 'pre-render-warn' && (\n <DRMWarningDialog\n onClose={() => {\n setRenderVideo('render-video')\n }}\n />\n )}\n {renderVideo === 'render-video' ? (\n <VideoPlayer asset={asset} autoPlay forceAspectRatio={THUMBNAIL_ASPECT_RATIO} />\n ) : (\n <PlayButton onClick={onClickPlay}>\n <div data-play>\n <PlayIcon />\n </div>\n {assetIsAudio(asset) ? (\n <div\n style={{\n aspectRatio: THUMBNAIL_ASPECT_RATIO,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <AudioIcon width=\"3em\" height=\"3em\" />\n </div>\n ) : (\n <VideoThumbnail asset={asset} />\n )}\n </PlayButton>\n )}\n <VideoMetadata asset={asset} />\n <div\n style={{\n display: 'flex',\n width: '100%',\n alignItems: 'flex-end',\n justifyContent: 'flex-start',\n gap: '.35rem',\n }}\n >\n {onSelect && (\n <Button\n icon={CheckmarkIcon}\n fontSize={2}\n padding={2}\n mode=\"ghost\"\n text=\"Select\"\n style={{flex: 1}}\n tone=\"positive\"\n onClick={select}\n />\n )}\n <Button\n icon={EditIcon}\n fontSize={2}\n padding={2}\n mode=\"ghost\"\n text=\"Details\"\n style={{flex: 1}}\n onClick={edit}\n />\n </div>\n </Stack>\n </Card>\n )\n}\n","import {SearchIcon} from '@sanity/icons/Search'\nimport {Card, Flex, Grid, Inline, Label, Stack, Text, TextInput} from '@sanity/ui'\nimport {type InputEvent, useMemo, useState} from 'react'\n\nimport {DrmPlaybackWarningContextProvider} from '../context/DrmPlaybackWarningContext'\nimport useAssets from '../hooks/useAssets'\nimport type {PluginConfig, VideoAssetDocument} from '../util/types'\nimport ConfigureApi from './ConfigureApi'\nimport ImportVideosFromMux from './ImportVideosFromMux'\nimport PageSelector from './PageSelector'\nimport ResyncMetadata from './ResyncMetadata'\nimport {SelectSortOptions} from './SelectSortOptions'\nimport SpinnerBox from './SpinnerBox'\nimport type {VideoDetailsProps} from './VideoDetails/useVideoDetails'\nimport VideoDetails from './VideoDetails/VideoDetails'\nimport VideoInBrowser from './VideoInBrowser'\n\nexport interface VideosBrowserProps {\n config: PluginConfig\n onSelect?: (asset: VideoAssetDocument) => void\n}\n\nexport default function VideosBrowser({onSelect, config}: VideosBrowserProps) {\n const {assets, isLoading, searchQuery, setSearchQuery, setSort, sort} = useAssets()\n const [page, setPage] = useState<number>(0)\n const pageLimit = 20\n const pageTotal = Math.floor(assets.length / pageLimit) + 1\n const [editedAsset, setEditedAsset] = useState<VideoDetailsProps['asset'] | null>(null)\n const freshEditedAsset = useMemo(\n () => assets.find((a) => a._id === editedAsset?._id) || editedAsset,\n [editedAsset, assets],\n )\n\n const pageStart = page * pageLimit\n const pageEnd = pageStart + pageLimit\n\n const placement = onSelect ? 'input' : 'tool'\n return (\n <DrmPlaybackWarningContextProvider config={config}>\n <Stack padding={4} gap={4} style={{minHeight: '50vh'}}>\n <Flex justify=\"space-between\" align=\"center\">\n <Flex align=\"center\" gap={3}>\n <TextInput\n value={searchQuery}\n icon={SearchIcon}\n onInput={(e: InputEvent<HTMLInputElement>) => setSearchQuery(e.currentTarget.value)}\n placeholder=\"Search videos\"\n />\n <SelectSortOptions setSort={setSort} sort={sort} />\n <PageSelector page={page} setPage={setPage} total={pageTotal} />\n </Flex>\n {placement === 'tool' && (\n <Inline gap={2}>\n <ImportVideosFromMux />\n <ResyncMetadata />\n <ConfigureApi />\n </Inline>\n )}\n </Flex>\n <Stack gap={3}>\n {assets?.length > 0 && (\n <Label muted>\n {assets.length} video{assets.length > 1 ? 's' : null}{' '}\n {searchQuery ? `matching \"${searchQuery}\"` : 'found'}\n </Label>\n )}\n <Grid\n gap={2}\n style={{\n gridTemplateColumns: 'repeat(auto-fill, minmax(250px, 1fr))',\n }}\n >\n {assets.slice(pageStart, pageEnd).map((asset) => (\n <VideoInBrowser\n key={asset._id}\n asset={asset}\n onEdit={setEditedAsset}\n onSelect={onSelect}\n />\n ))}\n </Grid>\n </Stack>\n {isLoading && <SpinnerBox />}\n\n {!isLoading && assets.length === 0 && (\n <Card marginY={4} paddingX={4} paddingY={6} border radius={2} tone=\"transparent\">\n <Text align=\"center\" muted size={3}>\n {searchQuery ? `No videos found for \"${searchQuery}\"` : 'No videos in this dataset'}\n </Text>\n </Card>\n )}\n </Stack>\n {freshEditedAsset && (\n <VideoDetails closeDialog={() => setEditedAsset(null)} asset={freshEditedAsset} />\n )}\n </DrmPlaybackWarningContextProvider>\n )\n}\n","import type {Tool} from 'sanity'\n\nimport {MuxApiHostProvider} from '../context/MuxApiHostContext'\nimport type {PluginConfig} from '../util/types'\nimport ToolIcon from './icons/ToolIcon'\nimport VideosBrowser from './VideosBrowser'\n\nconst StudioTool: React.FC<PluginConfig> = (config) => {\n return (\n <MuxApiHostProvider muxApiHost={config.muxApiHost}>\n <VideosBrowser config={config} />\n </MuxApiHostProvider>\n )\n}\n\nexport const DEFAULT_TOOL_CONFIG = {\n icon: ToolIcon,\n title: 'Videos',\n}\n\nexport default function createStudioTool(config: PluginConfig): Tool {\n const toolConfig = typeof config.tool === 'object' ? config.tool : DEFAULT_TOOL_CONFIG\n return {\n name: 'mux',\n icon: toolConfig.icon || DEFAULT_TOOL_CONFIG.icon,\n title: toolConfig.title || DEFAULT_TOOL_CONFIG.title,\n component: (props: any) => <StudioTool {...config} {...props} />,\n }\n}\n","import {useCurrentUser} from 'sanity'\n\nimport {type PluginConfig} from '../util/types'\n\nexport const useAccessControl = (config: PluginConfig) => {\n const user = useCurrentUser()\n\n const hasConfigAccess =\n !config?.allowedRolesForConfiguration?.length ||\n user?.roles?.some((role) => config.allowedRolesForConfiguration.includes(role.name))\n\n return {hasConfigAccess}\n}\n","import {isReference} from 'sanity'\nimport {useDocumentValues} from 'sanity'\n\nimport type {Reference, VideoAssetDocument} from '../util/types'\n\nconst path = ['assetId', 'data', 'playbackId', 'status', 'thumbTime', 'filename']\nexport const useAssetDocumentValues = (asset: Reference | null | undefined) =>\n useDocumentValues<VideoAssetDocument | null | undefined>(\n isReference(asset) ? asset._ref : '',\n path,\n )\n","import {useMemo, useRef} from 'react'\nimport {useDataset, useProjectId} from 'sanity'\nimport useSWR from 'swr'\n\nimport {useClient} from '../hooks/useClient'\nimport {addKeysToMuxData} from '../util/addKeysToMuxData'\nimport {getMuxAddonClient} from '../util/muxAddonClient'\nimport {PLUGIN_VERSION_QUERY} from '../util/pluginVersion'\nimport type {MuxAsset, VideoAssetDocument} from '../util/types'\n\n// Poll MUX if it's preparing the main document or its own static renditions\nexport const useMuxPolling = (asset?: VideoAssetDocument) => {\n const client = useClient()\n const projectId = useProjectId()\n const dataset = useDataset()\n const isPreparingStaticRenditions = useMemo(() => {\n // Legacy: If static_renditions has a status field, it was created with mp4_support (deprecated)\n // We don't process this old format, just return false\n // Note: 'disabled' status is valid in the new format when no renditions were requested\n if (\n asset?.data?.static_renditions?.status &&\n asset?.data?.static_renditions?.status !== 'disabled'\n ) {\n return false\n }\n\n const files = asset?.data?.static_renditions?.files\n if (!files || files.length === 0) {\n return false\n }\n return files.some((file) => file.status === 'preparing')\n }, [asset?.data?.static_renditions?.status, asset?.data?.static_renditions?.files])\n\n const shouldFetch = useMemo(\n () => !!asset?.assetId && (asset?.status === 'preparing' || isPreparingStaticRenditions),\n [asset?.assetId, asset?.status, isPreparingStaticRenditions],\n )\n // Only log the first failure of a streak so a persistent error doesn't flood\n // the console on every interval.\n const errorLoggedRef = useRef(false)\n return useSWR(\n shouldFetch ? `/${projectId}/addons/mux/assets/${dataset}/data/${asset?.assetId}` : null,\n async () => {\n try {\n const {data} = await getMuxAddonClient(client).request<{data: MuxAsset}>({\n url: `/addons/mux/assets/${dataset}/data/${asset!.assetId}`,\n withCredentials: true,\n method: 'GET',\n query: PLUGIN_VERSION_QUERY,\n })\n if (!asset?._id || !data) return\n await client\n .patch(asset._id)\n .set({status: data.status, data: addKeysToMuxData(data)})\n .commit({returnDocuments: false})\n errorLoggedRef.current = false\n } catch (error) {\n // Input re-throws `poll.error`, so a background polling failure would\n // crash the whole field. Swallow it instead.\n if (!errorLoggedRef.current) {\n errorLoggedRef.current = true\n console.error('[sanity-plugin-mux-input] Mux polling failed', {\n assetId: asset?.assetId,\n documentId: asset?._id,\n error,\n })\n }\n }\n },\n {refreshInterval: 2000, refreshWhenHidden: true, dedupingInterval: 1000},\n )\n}\n","/* eslint-disable no-console */\nimport {Button, Card, Flex, Grid, Heading, Inline, Text} from '@sanity/ui'\nimport {useToast} from '@sanity/ui/toast'\nimport {memo, useCallback, useRef} from 'react'\nimport scrollIntoView from 'scroll-into-view-if-needed'\nimport {clear} from 'suspend-react'\nimport {useErrorBoundary} from 'use-error-boundary'\n\nimport {name} from '../util/constants'\nimport {type MuxInputProps} from '../util/types'\n\nexport interface Props extends Pick<MuxInputProps, 'schemaType'> {\n children: React.ReactNode\n}\nfunction ErrorBoundaryCard(props: Props) {\n const {children, schemaType} = props\n const {push: pushToast} = useToast()\n const errorRef = useRef(null)\n const {ErrorBoundary, didCatch, error, reset} = useErrorBoundary({\n // oxlint-disable-next-line no-unstable-nested-components\n onDidCatch: (err, errorInfo) => {\n console.group(err.toString())\n console.groupCollapsed('console.error')\n console.error(err)\n console.groupEnd()\n if (err.stack) {\n console.groupCollapsed('error.stack')\n console.log(err.stack)\n console.groupEnd()\n }\n if (errorInfo?.componentStack) {\n console.groupCollapsed('errorInfo.componentStack')\n console.log(errorInfo.componentStack)\n console.groupEnd()\n }\n console.groupEnd()\n pushToast({\n status: 'error',\n title: 'Plugin crashed',\n description: (\n <Flex align=\"center\">\n <Inline gap={1}>\n An error happened while rendering\n <Button\n padding={1}\n fontSize={1}\n style={{transform: 'translateY(1px)'}}\n mode=\"ghost\"\n text={schemaType.title}\n onClick={() => {\n if (errorRef.current) {\n scrollIntoView(errorRef.current, {\n behavior: 'smooth',\n scrollMode: 'if-needed',\n block: 'center',\n })\n }\n }}\n />\n </Inline>\n </Flex>\n ),\n })\n },\n })\n const handleRetry = useCallback(() => {\n // Purge request cache before retrying, otherwise the cached errors will rethrow\n clear([name])\n\n reset()\n }, [reset])\n\n if (didCatch) {\n return (\n <Card ref={errorRef} paddingX={[2, 3, 4, 4]} height=\"fill\" shadow={1} overflow=\"auto\">\n <Flex justify=\"flex-start\" align=\"center\" height=\"fill\">\n <Grid gridTemplateColumns={1} gap={[2, 3, 4, 4]}>\n <Heading as=\"h1\">\n The <code>{name}</code> plugin crashed\n </Heading>\n {error?.message && (\n <Card padding={3} tone=\"critical\" shadow={1} radius={2}>\n <Text>{error.message}</Text>\n </Card>\n )}\n <Inline>\n <Button onClick={handleRetry} text=\"Retry\" />\n </Inline>\n </Grid>\n </Flex>\n </Card>\n )\n }\n\n return <ErrorBoundary>{children}</ErrorBoundary>\n}\n\nexport default memo(ErrorBoundaryCard)\n","import {Box, Card, Flex, Spinner, Text} from '@sanity/ui'\n\nexport const InputFallback = () => {\n return (\n <div style={{padding: 1}}>\n <Card\n shadow={1}\n sizing=\"border\"\n style={{aspectRatio: '16/9', width: '100%', borderRadius: '1px'}}\n >\n <Flex align=\"center\" direction=\"column\" height=\"fill\" justify=\"center\">\n <Spinner muted />\n <Box marginTop={3}>\n <Text align=\"center\" muted size={1}>\n Loading…\n </Text>\n </Box>\n </Flex>\n </Card>\n </div>\n )\n}\n","import {PlugIcon} from '@sanity/icons/Plug'\nimport {Button, Card, Flex, Grid, Heading, Inline, Text} from '@sanity/ui'\nimport {useCallback} from 'react'\n\nimport {useAccessControl} from '../hooks/useAccessControl'\nimport type {SetDialogState} from '../hooks/useDialogState'\nimport {type PluginConfig} from '../util/types'\nimport MuxLogo from './MuxLogo'\n\ninterface OnboardProps {\n setDialogState: SetDialogState\n config: PluginConfig\n}\n\nexport default function Onboard(props: OnboardProps) {\n const {setDialogState} = props\n const handleOpen = useCallback(() => setDialogState('secrets'), [setDialogState])\n const {hasConfigAccess} = useAccessControl(props.config)\n\n return (\n <>\n <div style={{padding: 2}}>\n <Card\n display=\"flex\"\n sizing=\"border\"\n style={{\n aspectRatio: '16/9',\n width: '100%',\n boxShadow: 'var(--card-bg-color) 0 0 0 2px',\n }}\n paddingX={[2, 3, 4, 4]}\n radius={1}\n tone=\"transparent\"\n >\n <Flex justify=\"flex-start\" align=\"center\">\n <Grid gridTemplateColumns={1} gap={[2, 3, 4, 4]}>\n <Inline paddingY={1}>\n <div style={{height: '32px'}}>\n <MuxLogo />\n </div>\n </Inline>\n <Inline paddingY={1}>\n <Heading size={[0, 1, 2, 2]}>\n Upload and preview videos directly from your studio.\n </Heading>\n </Inline>\n <Inline paddingY={1}>\n {hasConfigAccess ? (\n <Button mode=\"ghost\" icon={PlugIcon} text=\"Configure API\" onClick={handleOpen} />\n ) : (\n <Card padding={[3, 3, 3]} radius={2} shadow={1} tone=\"critical\">\n <Text>\n You do not have access to configure the Mux API. Please contact your\n administrator.\n </Text>\n </Card>\n )}\n </Inline>\n </Grid>\n </Flex>\n </Card>\n </div>\n </>\n )\n}\n","import {UpChunk} from '@mux/upchunk'\nimport {Observable} from 'rxjs'\n\nexport function createUpChunkObservable(uuid: string, uploadUrl: string, source: File) {\n return new Observable<\n | {type: 'pause' | 'resume'; id: string}\n | {type: 'success'; id: string}\n | {type: 'progress'; percent: number}\n >((subscriber) => {\n const upchunk = UpChunk.createUpload({\n endpoint: uploadUrl,\n file: source,\n dynamicChunkSize: true, // changes the chunk size based on network speeds\n })\n\n const successHandler = () => {\n subscriber.next({\n type: 'success',\n id: uuid,\n })\n subscriber.complete()\n }\n\n const errorHandler = (data: CustomEvent) => subscriber.error(new Error(data.detail.message))\n\n const progressHandler = (data: CustomEvent) => {\n return subscriber.next({type: 'progress', percent: data.detail})\n }\n\n const offlineHandler = () => {\n upchunk.pause()\n subscriber.next({\n type: 'pause',\n id: uuid,\n })\n }\n\n const onlineHandler = () => {\n upchunk.resume()\n subscriber.next({\n type: 'resume',\n id: uuid,\n })\n }\n\n upchunk.on('success', successHandler)\n upchunk.on('error', errorHandler)\n upchunk.on('progress', progressHandler)\n upchunk.on('offline', offlineHandler)\n upchunk.on('online', onlineHandler)\n\n return () => upchunk.abort()\n })\n}\n","/**\n * Format Google Drive share links as Google Drive export links.\n * Supported formats:\n * - https://drive.google.com/uc?id=<ID>...\n * - https://drive.google.com/open?id=<ID>...\n * - https://drive.google.com/file/d/<ID>...\n * - https://drive.google.com/folder/<ID>...\n *\n * @param url Google Drive share link to format.\n * @returns Google Drive export link (URL passthrough if not share link).\n */\nexport function formatDriveShareLink(url: string): string {\n // Export link formatter.\n const formatExportLink = (id: string) => {\n return `https://drive.google.com/uc?export=download&id=${id}`\n }\n\n // URL formatting.\n try {\n // Parse URL.\n const trimmed = url.trim()\n const parsed = new URL(trimmed)\n\n // Enforce strict host name.\n if (parsed.hostname !== 'drive.google.com') {\n throw new Error('URL is not from Google Drive.')\n }\n\n // Look for ID in search parameters.\n const id = parsed.searchParams.get('id') || ''\n if (id.length) {\n return formatExportLink(id)\n }\n\n // Look for ID in path name.\n const path = parsed.pathname.split('/') || []\n\n // Path is /file/d/<ID>...\n if (path.includes('file') && path.includes('d')) {\n const index =\n path.findIndex((value: string) => {\n return value === 'd'\n }) + 1\n const fileId = path.at(index) || ''\n return formatExportLink(fileId)\n }\n\n // Path is /folder/<ID>...\n if (path.includes('folders')) {\n const index =\n path.findIndex((value: string) => {\n return value === 'folders'\n }) + 1\n const folderId = path.at(index) || ''\n return formatExportLink(folderId)\n }\n\n // URL not recognized.\n throw new Error('URL was not recognized.')\n } catch {\n // URL passthrough by default.\n return url\n }\n}\n","/**\n * Rounds the numeric part of a px string to the nearest integer.\n * Returns undefined if the value is not a valid px string or not a finite number.\n * Avoids sending 0px (and JS -0); snaps to ±1 instead.\n */\nexport function roundPxString(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n if (!trimmed.endsWith('px')) return undefined\n const n = Number(trimmed.slice(0, -2))\n if (!Number.isFinite(n)) return undefined\n let rounded = Math.round(n)\n // Avoid sending 0px (and JS -0); keep sign when negative.\n if (rounded === 0) rounded = n < 0 ? -1 : 1\n return `${rounded}px`\n}\n","import {uuid as generateUuid} from '@sanity/uuid'\nimport {concat, defer, from, type Observable, of, throwError} from 'rxjs'\nimport {catchError, mergeMap, switchMap} from 'rxjs/operators'\nimport type {SanityClient} from 'sanity'\n\nimport {createUpChunkObservable} from '../clients/upChunkObservable'\nimport {formatDriveShareLink} from '../util/formatDriveShareLink'\nimport {getMuxAddonClient} from '../util/muxAddonClient'\nimport {PLUGIN_VERSION_QUERY} from '../util/pluginVersion'\nimport {roundPxString} from '../util/roundPxString'\nimport type {MuxAsset, MuxNewAssetSettings, WatermarkConfig} from '../util/types'\nimport {getAsset} from './assets'\nimport {testSecretsObservable} from './secrets'\n\nfunction sanitizeOverlaySettingsInPlace(settings: MuxNewAssetSettings) {\n const inputs = settings.input\n if (!inputs) return\n for (const input of inputs) {\n const overlay = (input as {overlay_settings?: Record<string, unknown>}).overlay_settings\n if (!overlay) continue\n\n const hm = roundPxString(overlay['horizontal_margin'])\n const vm = roundPxString(overlay['vertical_margin'])\n const w = roundPxString(overlay['width'])\n\n if (hm) overlay['horizontal_margin'] = hm\n if (vm) overlay['vertical_margin'] = vm\n if (w) overlay['width'] = w\n }\n}\n\nfunction sanitizePxStringsInJson(json: string): string {\n return json.replace(/\"(-?\\d+(?:\\.\\d+)?)px\"/g, (_match, num) => {\n const n = Number(num)\n if (!Number.isFinite(n)) return _match\n let rounded = Math.round(n)\n if (rounded === 0) rounded = n < 0 ? -1 : 1\n return `\"${rounded}px\"`\n })\n}\n\nfunction cancelUpload(client: SanityClient, uuid: string) {\n return getMuxAddonClient(client).observable.request({\n url: `/addons/mux/uploads/${client.config().dataset}/${uuid}`,\n withCredentials: true,\n method: 'DELETE',\n query: PLUGIN_VERSION_QUERY,\n })\n}\n\nexport function uploadUrl({\n url,\n settings,\n client,\n}: {\n url: string\n settings: MuxNewAssetSettings\n client: SanityClient\n watermark?: WatermarkConfig\n}) {\n return testUrl(url).pipe(\n switchMap((validUrl) => {\n return concat(\n of({type: 'url' as const, url: validUrl}),\n testSecretsObservable(client).pipe(\n switchMap((json) => {\n if (!json || !json.status) {\n return throwError(() => new Error('Invalid credentials'))\n }\n const uuid = generateUuid()\n const muxBody = settings\n if (!muxBody.input) muxBody.input = [{type: 'video'}]\n muxBody.input[0]!.url = validUrl\n sanitizeOverlaySettingsInPlace(muxBody)\n\n const query: Record<string, string> = {\n muxBody: sanitizePxStringsInJson(JSON.stringify(muxBody)),\n }\n const filename = validUrl.split('/').slice(-1)[0]\n if (filename) {\n query['filename'] = filename\n }\n\n const dataset = client.config().dataset\n return defer(() =>\n getMuxAddonClient(client).observable.request({\n url: `/addons/mux/assets/${dataset}`,\n withCredentials: true,\n method: 'POST',\n headers: {\n 'MUX-Proxy-UUID': uuid,\n 'Content-Type': 'application/json',\n },\n query: {...query, ...PLUGIN_VERSION_QUERY},\n }),\n ).pipe(\n mergeMap((result) => {\n const asset =\n (result && result.results && result.results[0] && result.results[0].document) ||\n null\n\n if (!asset) {\n return throwError(() => new Error('No asset document returned'))\n }\n return of({type: 'success' as const, id: uuid, asset})\n }),\n )\n }),\n ),\n )\n }),\n )\n}\n\nexport function uploadFile({\n settings,\n client,\n file,\n watermark,\n}: {\n settings: MuxNewAssetSettings\n client: SanityClient\n file: File\n watermark?: WatermarkConfig\n}) {\n return testFile(file).pipe(\n switchMap((fileOptions) => {\n return concat(\n of({type: 'file' as const, file: fileOptions}),\n testSecretsObservable(client).pipe(\n switchMap((json) => {\n if (!json || !json.status) {\n return throwError(() => new Error('Invalid credentials'))\n }\n const uuid = generateUuid()\n const body = settings\n sanitizeOverlaySettingsInPlace(body)\n\n return concat(\n of({type: 'uuid' as const, uuid}),\n defer(() =>\n getMuxAddonClient(client).observable.request<{\n sanityAssetId: string\n upload: {\n cors_origin: string\n id: string\n new_asset_settings: MuxNewAssetSettings\n status: 'waiting'\n timeout: number\n url: string\n }\n }>({\n url: `/addons/mux/uploads/${client.config().dataset}`,\n withCredentials: true,\n method: 'POST',\n headers: {\n 'MUX-Proxy-UUID': uuid,\n 'Content-Type': 'application/json',\n },\n body,\n query: PLUGIN_VERSION_QUERY,\n }),\n ).pipe(\n mergeMap((result) => {\n return createUpChunkObservable(uuid, result.upload.url, file).pipe(\n // @TODO type the observable events\n mergeMap((event) => {\n if (event.type !== 'success') {\n return of(event)\n }\n return from(updateAssetDocumentFromUpload(client, uuid, watermark)).pipe(\n mergeMap((doc) => of({...event, asset: doc})),\n )\n }),\n catchError((err) => {\n // Delete asset document\n return cancelUpload(client, uuid).pipe(mergeMap(() => throwError(() => err)))\n }),\n )\n }),\n ),\n )\n }),\n ),\n )\n }),\n )\n}\n\ntype UploadResponse = {\n data: {\n asset_id: string\n cors_origin: string\n id: string\n new_asset_settings: {\n static_renditions?: {resolution: string}[]\n passthrough: string\n playback_policies: ['public' | 'signed' | 'drm']\n }\n status: string\n timeout: number\n }\n}\nfunction getUpload(client: SanityClient, assetId: string) {\n const {dataset} = client.config()\n return getMuxAddonClient(client).request<UploadResponse>({\n url: `/addons/mux/uploads/${dataset}/${assetId}`,\n withCredentials: true,\n method: 'GET',\n query: PLUGIN_VERSION_QUERY,\n })\n}\n\nfunction pollUpload(client: SanityClient, uuid: string): Promise<UploadResponse> {\n const maxTries = 10\n let pollInterval: number\n let tries = 0\n let assetId: string\n let upload: UploadResponse\n return new Promise((resolve, reject) => {\n pollInterval = (setInterval as typeof window.setInterval)(async () => {\n try {\n upload = await getUpload(client, uuid)\n } catch (err) {\n reject(err)\n return\n }\n assetId = upload && upload.data && upload.data.asset_id\n if (assetId) {\n clearInterval(pollInterval)\n resolve(upload)\n }\n if (tries > maxTries) {\n clearInterval(pollInterval)\n reject(new Error('Upload did not finish'))\n }\n tries++\n }, 2000)\n })\n}\n\nasync function updateAssetDocumentFromUpload(\n client: SanityClient,\n uuid: string,\n _watermark?: WatermarkConfig,\n) {\n let upload: UploadResponse\n let asset: {data: MuxAsset}\n try {\n upload = await pollUpload(client, uuid)\n } catch (err) {\n return Promise.reject(err)\n }\n try {\n asset = await getAsset(client, upload.data.asset_id)\n } catch (err) {\n return Promise.reject(err)\n }\n\n const doc = {\n _id: uuid,\n _type: 'mux.videoAsset',\n status: asset.data.status,\n data: asset.data,\n assetId: asset.data.id,\n playbackId: asset.data.playback_ids[0]?.id,\n uploadId: upload.data.id,\n }\n return client.createOrReplace(doc).then(() => {\n return doc\n })\n}\n\nfunction testFile(file: File) {\n if (typeof window !== 'undefined' && file instanceof window.File) {\n const fileOptions = optionsFromFile({}, file)\n return of(fileOptions)\n }\n return throwError(() => new Error('Invalid file'))\n}\n\nfunction testUrl(url: string): Observable<string> {\n const error = new Error('Invalid URL')\n if (typeof url !== 'string') {\n return throwError(() => error)\n }\n let formattedUrl = url.trim()\n formattedUrl = formatDriveShareLink(formattedUrl)\n let parsed\n try {\n parsed = new URL(formattedUrl)\n } catch {\n return throwError(() => error)\n }\n if (parsed && !parsed.protocol.match(/http:|https:/)) {\n return throwError(() => error)\n }\n return of(formattedUrl)\n}\n\nfunction optionsFromFile(opts: {preserveFilename?: boolean}, file: File) {\n if (typeof window === 'undefined' || !(file instanceof window.File)) {\n return undefined\n }\n return {\n name: opts.preserveFilename === false ? undefined : file.name,\n type: file.type,\n }\n}\n","import type {ServerError} from '@sanity/client'\n\nexport function isValidUrl(url: string): boolean {\n try {\n const parsed = new URL(url)\n return parsed && !!parsed.protocol.match(/http:|https:/)\n } catch {\n return false\n }\n}\n\n/**\n * We consider a server error one with status code 5XX.\n * Used mainly to handle unknown Proxy issues.\n */\nexport function isServerError(error: Error): error is ServerError {\n return (\n 'statusCode' in error &&\n typeof error.statusCode === 'number' &&\n 500 <= error.statusCode &&\n error.statusCode <= 600\n )\n}\n","/**\n * Utilities for extracting files from dataTransfer in a predictable cross-browser fashion.\n * Also recursively extracts files from a directory\n * Inspired by https://github.com/component/normalized-upload\n */\n\nexport function extractDroppedFiles(dataTransfer: DataTransfer) {\n const files = Array.from(dataTransfer.files || [])\n const items = Array.from(dataTransfer.items || [])\n if (files && files.length > 0) {\n return Promise.resolve(files)\n }\n return normalizeItems(items).then((arr) => arr.flat())\n}\n\nfunction normalizeItems(items: DataTransferItem[]) {\n return Promise.all(\n items.map((item) => {\n // directory\n if (item.kind === 'file' && item.webkitGetAsEntry) {\n let entry: FileSystemEntry | File[] | null\n // Edge throws\n try {\n entry = item.webkitGetAsEntry()\n } catch {\n return [item.getAsFile()]\n }\n if (!entry) {\n return []\n }\n return entry.isDirectory ? walk(entry) : [item.getAsFile()]\n }\n\n // file\n if (item.kind === 'file') {\n const file = item.getAsFile()\n return Promise.resolve(file ? [file] : [])\n }\n\n // others\n return new Promise((resolve) => item.getAsString(resolve)).then((str?: any) =>\n str ? [new File([str], 'unknown.txt', {type: item.type})] : [],\n )\n }),\n )\n}\n\nfunction isFile(entry: FileSystemEntry): entry is FileSystemFileEntry {\n return entry.isFile\n}\nfunction isDirectory(entry: FileSystemEntry): entry is FileSystemDirectoryEntry {\n return entry.isDirectory\n}\n\nfunction walk(entry: FileSystemEntry): any {\n if (isFile(entry)) {\n return new Promise((resolve) => entry.file(resolve)).then((file) => [file])\n }\n\n if (isDirectory(entry)) {\n const dir = entry.createReader()\n return new Promise<any>((resolve) => dir.readEntries(resolve))\n .then((entries: FileSystemEntry[]) => entries.filter((entr) => !entr.name.startsWith('.')))\n .then((entries) => Promise.all(entries.map(walk)).then((arr) => arr.flat()))\n }\n return Promise.resolve([])\n}\n","import {useCallback} from 'react'\nimport {PatchEvent, set, setIfMissing, unset} from 'sanity'\n\nimport type {SetDialogState} from '../hooks/useDialogState'\nimport type {MuxInputProps, PluginConfig, VideoAssetDocument} from '../util/types'\nimport VideosBrowser, {type VideosBrowserProps} from './VideosBrowser'\n\nexport interface Props extends Pick<MuxInputProps, 'onChange'> {\n asset?: VideoAssetDocument | null | undefined\n setDialogState: SetDialogState\n config: PluginConfig\n}\n\nexport default function SelectAssets({\n asset: selectedAsset,\n onChange,\n setDialogState,\n config,\n}: Props) {\n const handleSelect = useCallback<Required<VideosBrowserProps>['onSelect']>(\n (chosenAsset) => {\n if (!chosenAsset?._id) {\n onChange(PatchEvent.from([unset(['asset'])]))\n }\n if (chosenAsset._id !== selectedAsset?._id) {\n onChange(\n PatchEvent.from([\n setIfMissing({asset: {}, _type: 'mux.video'}),\n set({_type: 'reference', _weak: true, _ref: chosenAsset._id}, ['asset']),\n ]),\n )\n }\n setDialogState(false)\n },\n [onChange, setDialogState, selectedAsset],\n )\n\n return <VideosBrowser onSelect={handleSelect} config={config} />\n}\n","import {Dialog} from '@sanity/ui'\nimport {useCallback, useId} from 'react'\nimport {styled} from 'styled-components'\n\nimport type {SetDialogState} from '../hooks/useDialogState'\nimport SelectAsset, {type Props as SelectAssetProps} from './SelectAsset'\n\n/** To prevent Content Layout Shift (CLS), ensure that the dialog always occupies the entire available height. */\nconst StyledDialog = styled(Dialog)`\n > div[data-ui='DialogCard'] > div[data-ui='Card'] {\n height: 100%;\n }\n`\n\nexport default function InputBrowser({\n setDialogState,\n asset,\n onChange,\n config,\n}: Pick<SelectAssetProps, 'onChange' | 'asset' | 'config'> & {\n setDialogState: SetDialogState\n}) {\n const id = `InputBrowser${useId()}`\n const handleClose = useCallback(() => setDialogState(false), [setDialogState])\n return (\n <StyledDialog\n __unstable_autoFocus\n header=\"Select video\"\n id={id}\n onClose={handleClose}\n width={2}\n >\n <SelectAsset\n config={config}\n asset={asset}\n onChange={onChange}\n setDialogState={setDialogState}\n />\n </StyledDialog>\n )\n}\n","import {useCallback} from 'react'\nimport {PatchEvent, unset} from 'sanity'\n\nimport {deleteAssetOnMux} from '../actions/assets'\nimport {useClient} from '../hooks/useClient'\nimport type {MuxInputProps, VideoAssetDocument} from '../util/types'\n\nexport const useCancelUpload = (asset: VideoAssetDocument, onChange: MuxInputProps['onChange']) => {\n const client = useClient()\n return useCallback(() => {\n if (!asset) {\n return\n }\n onChange(PatchEvent.from(unset()))\n if (asset.assetId) {\n void deleteAssetOnMux(client, asset.assetId)\n }\n if (asset._id) {\n void client.delete(asset._id)\n }\n }, [asset, client, onChange])\n}\n","import {styled} from 'styled-components'\n\nexport const TopControls = styled.div`\n position: absolute;\n top: 0;\n right: 0;\n justify-content: flex-end;\n button {\n height: auto;\n }\n`\n","// Lifted from sanity/form/inputs/files/common/UploadProgress\n\nimport {Button, Card, Flex, Inline, Stack, Text} from '@sanity/ui'\nimport {Code} from '@sanity/ui/code'\nimport {LinearProgress} from 'sanity'\nimport {styled} from 'styled-components'\n\nconst CardWrapper = styled(Card)`\n min-height: 82px;\n box-sizing: border-box;\n`\n\nconst FlexWrapper = styled(Flex)`\n text-overflow: ellipsis;\n overflow: hidden;\n`\n\nconst LeftSection = styled(Stack)`\n position: relative;\n width: 60%;\n`\n\nconst CodeWrapper = styled(Code)`\n position: relative;\n width: 100%;\n\n code {\n overflow: hidden;\n text-overflow: ellipsis;\n position: relative;\n max-width: 200px;\n }\n`\n\nexport const UploadProgress = ({\n progress = 100,\n onCancel,\n filename,\n text = 'Uploading',\n}: {\n progress: number\n filename?: React.ReactNode\n onCancel?: React.MouseEventHandler<HTMLButtonElement>\n text?: React.ReactNode\n}) => {\n // Disable cancel button when upload is 90% or more complete\n // to prevent inconsistency between Mux and Sanity\n const isCancelDisabled = progress >= 90\n\n return (\n <CardWrapper tone=\"primary\" padding={4} border height=\"fill\">\n <FlexWrapper align=\"center\" justify=\"space-between\" height=\"fill\" direction=\"row\" gap={2}>\n <LeftSection>\n <Flex justify=\"center\" gap={[3, 3, 2, 2]} direction={['column', 'column', 'row']}>\n <Text size={1}>\n <Inline gap={2}>\n {text}\n <CodeWrapper size={1}>{filename ? filename : '...'}</CodeWrapper>\n </Inline>\n </Text>\n </Flex>\n\n <Card marginTop={3} radius={5} shadow={1}>\n <LinearProgress value={progress} />\n </Card>\n </LeftSection>\n\n {onCancel ? (\n <Button\n fontSize={2}\n text=\"Cancel upload\"\n mode=\"ghost\"\n tone=\"critical\"\n onClick={onCancel}\n disabled={isCancelDisabled}\n />\n ) : null}\n </FlexWrapper>\n </CardWrapper>\n )\n}\n","import {Card, Text} from '@sanity/ui'\nimport {useEffect, useMemo, useRef} from 'react'\n\nimport {useCancelUpload} from '../hooks/useCancelUpload'\nimport type {MuxInputProps, PluginConfig, VideoAssetDocument} from '../util/types'\nimport {TopControls} from './Player.styled'\nimport {UploadProgress} from './UploadProgress'\nimport VideoPlayer from './VideoPlayer'\n\ninterface Props extends Pick<MuxInputProps, 'onChange' | 'readOnly'> {\n buttons?: React.ReactNode\n asset: VideoAssetDocument\n config?: PluginConfig\n}\n\nconst Player = ({asset, buttons, readOnly, onChange, config}: Props) => {\n const isLoading = useMemo<boolean | string>(() => {\n if (asset?.status === 'preparing') {\n return 'Preparing the video'\n }\n if (asset?.status === 'waiting_for_upload') {\n return 'Waiting for upload to start'\n }\n if (asset?.status === 'waiting') {\n return 'Processing upload'\n }\n if (asset?.status === 'ready') {\n return false\n }\n if (typeof asset?.status === 'undefined') {\n return false\n }\n\n return true\n }, [asset])\n const isPreparingStaticRenditions = useMemo<boolean>(() => {\n // Legacy: If static_renditions has a status field, it was created with mp4_support (deprecated)\n // We don't process this old format, just return false\n // Note: 'disabled' status is valid in the new format when no renditions were requested\n if (\n asset?.data?.static_renditions?.status &&\n asset?.data?.static_renditions?.status !== 'disabled'\n ) {\n return false\n }\n\n // Check if any file in static_renditions is still preparing\n const files = asset?.data?.static_renditions?.files\n if (!files || files.length === 0) {\n return false\n }\n return files.some((file) => file.status === 'preparing')\n // oxlint-disable-next-line react/preserve-manual-memoization\n }, [asset?.data?.static_renditions?.status, asset?.data?.static_renditions?.files])\n const playRef = useRef<HTMLDivElement>(null)\n const muteRef = useRef<HTMLDivElement>(null)\n const handleCancelUpload = useCancelUpload(asset, onChange)\n\n useEffect(() => {\n const style = document.createElement('style')\n style.innerHTML = 'button svg { vertical-align: middle; }'\n\n if (playRef.current?.shadowRoot) {\n playRef.current.shadowRoot.appendChild(style)\n }\n if (muteRef?.current?.shadowRoot) {\n muteRef.current.shadowRoot.appendChild(style.cloneNode(true))\n }\n }, [])\n\n useEffect(() => {\n if (asset?.status === 'errored') {\n handleCancelUpload()\n // @TODO use better error handling\n throw new Error(asset.data?.errors?.messages?.join(' '))\n }\n }, [asset.data?.errors?.messages, asset?.status, handleCancelUpload])\n\n if (!asset || !asset.status) {\n return null\n }\n\n if (isLoading) {\n return (\n <UploadProgress\n progress={100}\n filename={asset?.filename}\n text={(isLoading !== true && isLoading) || 'Waiting for Mux to complete the upload'}\n onCancel={readOnly ? undefined : () => handleCancelUpload()}\n />\n )\n }\n\n return (\n <VideoPlayer asset={asset} hlsConfig={config?.hlsConfig}>\n {buttons && <TopControls slot=\"top-chrome\">{buttons}</TopControls>}\n {isPreparingStaticRenditions && (\n <Card\n padding={2}\n radius={1}\n style={{\n background: 'var(--card-fg-color)',\n position: 'absolute',\n top: '0.5em',\n left: '0.5em',\n }}\n >\n <Text size={1} style={{color: 'var(--card-bg-color)'}}>\n MUX is preparing static renditions, please stand by\n </Text>\n </Card>\n )}\n </VideoPlayer>\n )\n}\n\nexport default Player\n","// todo: get these utils from @sanity/ui instead\nexport function focusRingBorderStyle(border: {color: string; width: number}): string {\n return `inset 0 0 0 ${border.width}px ${border.color}`\n}\n\nexport function focusRingStyle(opts: {\n base?: {bg: string}\n border?: {color: string; width: number}\n focusRing: {offset: number; width: number}\n}): string {\n const {base, border, focusRing} = opts\n const focusRingOutsetWidth = focusRing.offset + focusRing.width\n const focusRingInsetWidth = 0 - focusRing.offset\n const bgColor = base ? base.bg : 'var(--card-bg-color)'\n\n return [\n focusRingInsetWidth > 0 && `inset 0 0 0 ${focusRingInsetWidth}px var(--card-focus-ring-color)`,\n border && focusRingBorderStyle(border),\n focusRingInsetWidth < 0 && `0 0 0 ${0 - focusRingInsetWidth}px ${bgColor}`,\n focusRingOutsetWidth > 0 && `0 0 0 ${focusRingOutsetWidth}px var(--card-focus-ring-color)`,\n ]\n .filter(Boolean)\n .join(',')\n}\n","import {MenuItem} from '@sanity/ui/menu'\nimport {css, styled} from 'styled-components'\n\nimport {focusRingStyle} from './withFocusRing/helpers'\n\nexport const FileButton = styled(MenuItem)(({theme}) => {\n // oxlint-disable-next-line no-deprecated -- deferred to a follow-up PR\n const {focusRing} = theme.sanity\n // oxlint-disable-next-line no-deprecated -- deferred to a follow-up PR\n const base = theme.sanity.color.base\n const border = {width: 1, color: 'var(--card-border-color)'}\n\n return css`\n position: relative;\n\n &:not([data-disabled='true']) {\n &:focus-within {\n box-shadow: ${focusRingStyle({base, border, focusRing})};\n }\n }\n\n & input {\n overflow: hidden;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n position: absolute;\n min-width: 0;\n display: block;\n appearance: none;\n padding: 0;\n margin: 0;\n border: 0;\n opacity: 0;\n }\n `\n})\n","import {Box, type ButtonProps, Flex, Text} from '@sanity/ui'\nimport {isValidElement, useId, useCallback} from 'react'\nimport {isValidElementType} from 'react-is'\n\nimport {FileButton} from './FileInputMenuItem.styled'\n\nexport interface FileInputMenuItemProps extends Omit<ButtonProps, 'onSelect'> {\n accept?: string\n capture?: 'user' | 'environment'\n multiple?: boolean\n onSelect?: (files: File[]) => void\n disabled?: boolean\n}\n\nexport function FileInputMenuItem(\n props: FileInputMenuItemProps &\n Omit<React.HTMLProps<HTMLButtonElement>, 'as' | 'ref' | 'type' | 'value' | 'onSelect'> & {\n ref?: React.Ref<HTMLInputElement>\n },\n) {\n const {\n icon: Icon,\n id: idProp,\n accept,\n capture,\n fontSize,\n multiple,\n onSelect,\n gap = 3,\n textAlign,\n text,\n disabled,\n ref,\n ...rest\n } = props\n const idHook = useId()\n const id = idProp || idHook\n\n const handleChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n if (onSelect && event.target.files) {\n onSelect(Array.from(event.target.files))\n }\n },\n [onSelect],\n )\n\n const content = (\n <Flex align=\"center\" justify=\"flex-start\">\n {/* Icon */}\n {Icon && (\n <Box marginRight={text ? gap : undefined}>\n <Text size={fontSize}>\n {isValidElement(Icon) && Icon}\n {isValidElementType(Icon) && <Icon />}\n </Text>\n </Box>\n )}\n\n {/* Text */}\n {text && (\n <Text align={textAlign} size={fontSize} textOverflow=\"ellipsis\">\n {text}\n </Text>\n )}\n </Flex>\n )\n\n return (\n <FileButton {...rest} htmlFor={id} disabled={disabled} ref={ref}>\n {content}\n\n {/* Visibly hidden input */}\n <input\n data-testid=\"file-button-input\"\n accept={accept}\n capture={capture}\n id={id}\n multiple={multiple}\n onChange={handleChange}\n type=\"file\"\n value=\"\"\n disabled={disabled}\n />\n </FileButton>\n )\n}\n","import {DownloadIcon} from '@sanity/icons/Download'\nimport {EllipsisHorizontalIcon} from '@sanity/icons/EllipsisHorizontal'\nimport {ImageIcon} from '@sanity/icons/Image'\nimport {LockIcon} from '@sanity/icons/Lock'\nimport {PlugIcon} from '@sanity/icons/Plug'\nimport {ResetIcon} from '@sanity/icons/Reset'\nimport {SearchIcon} from '@sanity/icons/Search'\nimport {SyncIcon} from '@sanity/icons/Sync'\nimport {TranslateIcon} from '@sanity/icons/Translate'\nimport {UploadIcon} from '@sanity/icons/Upload'\nimport {Box, Button, Card, Inline, Label, Text, useClickOutsideEvent} from '@sanity/ui'\nimport {Menu, MenuDivider, MenuItem} from '@sanity/ui/menu'\nimport {Popover} from '@sanity/ui/popover'\nimport {Tooltip} from '@sanity/ui/tooltip'\nimport {memo, useCallback, useEffect, useMemo, useState} from 'react'\nimport {PatchEvent, unset} from 'sanity'\nimport {styled} from 'styled-components'\n\nimport {useAccessControl} from '../hooks/useAccessControl'\nimport {type DialogState, type SetDialogState} from '../hooks/useDialogState'\nimport {useResyncAsset} from '../hooks/useResyncAsset'\nimport {getPlaybackPolicy} from '../util/getPlaybackPolicy'\nimport type {MuxInputProps, PluginConfig, VideoAssetDocument} from '../util/types'\nimport {FileInputMenuItem} from './FileInputMenuItem'\n\nconst LockCard = styled(Card)`\n position: absolute;\n top: 0;\n left: 0;\n opacity: 0.6;\n mix-blend-mode: screen;\n background: transparent;\n`\n\nconst LockButton = styled(Button)`\n background: transparent;\n color: white;\n`\n\n// @TODO: add support for audio type (asset._type) when uploading an audio file so we can hide the thumbnail option.\nconst isVideoAsset = (asset: VideoAssetDocument) => {\n return asset._type === 'mux.videoAsset'\n}\n\nfunction PlayerActionsMenu(\n props: Pick<MuxInputProps, 'onChange' | 'readOnly'> & {\n asset: VideoAssetDocument\n onSelect: (files: File[]) => void\n dialogState: DialogState\n setDialogState: SetDialogState\n config: PluginConfig\n accept: string\n },\n) {\n const {asset, readOnly, dialogState, setDialogState, onChange, onSelect, accept} = props\n const [open, setOpen] = useState(false)\n const [menuElement, setMenuRef] = useState<HTMLDivElement | null>(null)\n const isSigned = useMemo(() => getPlaybackPolicy(asset)?.policy === 'signed', [asset])\n const {hasConfigAccess} = useAccessControl(props.config)\n const {resyncAsset, isResyncing} = useResyncAsset({showToast: true})\n\n const onReset = useCallback(() => onChange(PatchEvent.from(unset([]))), [onChange])\n\n const handleResync = useCallback(async () => {\n setOpen(false)\n await resyncAsset(asset)\n }, [resyncAsset, asset])\n\n useEffect(() => {\n if (open && dialogState) {\n // oxlint-disable-next-line react/set-state-in-effect\n setOpen(false)\n }\n }, [dialogState, open])\n\n useClickOutsideEvent(\n () => setOpen(false),\n () => [menuElement],\n )\n\n return (\n <Inline gap={1} padding={2}>\n {isSigned && (\n <Tooltip\n animate\n content={\n <Box padding={2}>\n <Text muted size={1}>\n Signed playback policy\n </Text>\n </Box>\n }\n placement=\"right\"\n portal\n >\n <LockCard radius={2} margin={2} scheme=\"dark\" tone=\"positive\">\n <LockButton icon={LockIcon} mode=\"bleed\" tone=\"positive\" />\n </LockCard>\n </Tooltip>\n )}\n <Popover\n animate\n content={\n <Menu ref={setMenuRef}>\n <Box padding={2}>\n <Label muted size={1}>\n Replace\n </Label>\n </Box>\n <FileInputMenuItem\n accept={accept}\n icon={UploadIcon}\n onSelect={onSelect}\n text=\"Upload\"\n disabled={readOnly}\n fontSize={1}\n />\n <MenuItem\n icon={SearchIcon}\n text=\"Browse\"\n onClick={() => setDialogState('select-video')}\n />\n {isVideoAsset(asset) && (\n <>\n <MenuItem\n icon={ImageIcon}\n text=\"Thumbnail\"\n onClick={() => setDialogState('edit-thumbnail')}\n />\n <MenuItem\n icon={TranslateIcon}\n text=\"Captions\"\n onClick={() => setDialogState('edit-captions')}\n />\n <MenuItem\n icon={SyncIcon}\n text=\"Resync from Mux\"\n onClick={handleResync}\n disabled={readOnly || isResyncing}\n />\n </>\n )}\n <MenuDivider />\n <MenuItem\n icon={DownloadIcon}\n text=\"Mezzanine\"\n onClick={() => setDialogState('mezzanine')}\n />\n <MenuDivider />\n {hasConfigAccess && (\n <>\n <MenuItem\n icon={PlugIcon}\n text=\"Configure API\"\n onClick={() => setDialogState('secrets')}\n />\n <MenuDivider />\n </>\n )}\n <MenuItem\n tone=\"critical\"\n icon={ResetIcon}\n text=\"Clear field\"\n onClick={onReset}\n disabled={readOnly}\n />\n </Menu>\n }\n portal\n open={open}\n >\n <Button\n icon={EllipsisHorizontalIcon}\n mode=\"ghost\"\n fontSize={1}\n onClick={() => {\n setDialogState(false)\n setOpen(true)\n }}\n />\n </Popover>\n </Inline>\n )\n}\n\nexport default memo(PlayerActionsMenu)\n","import {useEffect, useState} from 'react'\n\nimport {type StagedUpload} from '../components/Uploader'\n\nexport function useFetchFileSize(stagedUpload: StagedUpload, maxFileSize?: number) {\n const [fileSize, setFileSize] = useState<number | null>(null)\n const [isLoadingFileSize, setIsLoadingFileSize] = useState(false)\n const [canSkipFileSizeValidation, setCanSkipFileSizeValidation] = useState(false)\n\n useEffect(() => {\n // Fetch URL Upload file size\n if (stagedUpload.type === 'url') {\n // oxlint-disable-next-line react/set-state-in-effect\n setIsLoadingFileSize(false)\n setCanSkipFileSizeValidation(false)\n setFileSize(null)\n const url = stagedUpload.url\n\n // Get file size from URL\n const fetchFileSize = async () => {\n setIsLoadingFileSize(true)\n try {\n const response = await fetch(url, {method: 'HEAD'})\n const contentLength = response.headers.get('content-length')\n const newFileSize = contentLength ? parseInt(contentLength, 10) : null\n\n setIsLoadingFileSize(false)\n if (newFileSize) {\n setFileSize(newFileSize)\n }\n if (newFileSize === null && maxFileSize !== undefined) {\n // Size unknown but size limit is configured - skip file size validation\n setCanSkipFileSizeValidation(true)\n }\n } catch {\n console.warn('Could not validate file size from URL')\n // Skip validation of file size, but still validate duration\n setCanSkipFileSizeValidation(true)\n setIsLoadingFileSize(false)\n }\n }\n\n void fetchFileSize()\n }\n if (stagedUpload.type === 'file') {\n setFileSize(stagedUpload.files[0]!.size)\n }\n }, [maxFileSize, stagedUpload, stagedUpload.type])\n\n return {\n fileSize,\n isLoadingFileSize,\n canSkipFileSizeValidation,\n }\n}\n","import {useEffect, useState} from 'react'\n\nimport {type StagedUpload} from '../components/Uploader'\n\nexport interface VideoAssetMetadata {\n width?: number\n height?: number\n isAudioOnly?: boolean\n duration?: number\n size?: number\n aspectRatio?: number\n}\n\nexport function useMediaMetadata(stagedUpload: StagedUpload) {\n const [videoAssetMetadata, setVideoAssetMetadata] = useState<VideoAssetMetadata | null>(null)\n const [isLoadingMetadata, setIsLoadingMetadata] = useState(false)\n useEffect(() => {\n let videoSrc = null\n // Validate file uploads\n if (stagedUpload.type === 'file') {\n const file = stagedUpload.files[0]\n videoSrc = URL.createObjectURL(file!)\n }\n\n // Validate URL uploads\n if (stagedUpload.type === 'url') {\n videoSrc = stagedUpload.url\n }\n\n // oxlint-disable-next-line react/set-state-in-effect\n setVideoAssetMetadata((old) => ({\n ...old,\n duration: undefined,\n width: undefined,\n height: undefined,\n }))\n\n if (!videoSrc) return () => null\n\n setIsLoadingMetadata(true)\n const videoElement = document.createElement('video')\n videoElement.preload = 'metadata'\n\n const metadataListeners = [\n () => {\n setIsLoadingMetadata(false)\n },\n () => {\n const duration = videoElement.duration\n const width = videoElement.videoWidth\n const height = videoElement.videoHeight\n const isAudioOnly = width <= 0 && height <= 0\n const aspectRatio = width / height\n setVideoAssetMetadata((old) => {\n return {\n ...old,\n duration: duration,\n width: width,\n height: height,\n isAudioOnly: isAudioOnly,\n aspectRatio: aspectRatio,\n }\n })\n },\n ]\n\n const cleanupVideo = (videoEl: HTMLVideoElement) => {\n const currentVideoSrc = videoEl?.src\n if (videoEl) {\n metadataListeners.forEach((listener) =>\n videoEl.removeEventListener('loadedmetadata', listener),\n )\n videoEl.onerror = null\n videoEl.src = ''\n videoEl.load()\n }\n if (currentVideoSrc?.startsWith('blob:')) {\n URL.revokeObjectURL(currentVideoSrc)\n }\n }\n metadataListeners.push(() => setTimeout(() => cleanupVideo(videoElement), 0))\n\n videoElement.onerror = () => {\n setIsLoadingMetadata(false)\n console.warn('Could not read video metadata for validation')\n cleanupVideo(videoElement)\n }\n\n metadataListeners.forEach((listener) =>\n videoElement.addEventListener('loadedmetadata', listener),\n )\n videoElement.src = videoSrc\n\n return () => {\n cleanupVideo(videoElement)\n }\n }, [stagedUpload.type, stagedUpload])\n\n return {\n videoAssetMetadata,\n setVideoAssetMetadata,\n isLoadingMetadata,\n }\n}\n","import {roundPxString} from './roundPxString'\nimport type {MuxOverlaySettings, WatermarkConfig} from './types'\n\n/**\n * Converts a draggable watermark position (x, y percentages) to Mux's overlay_settings format.\n *\n * @param watermark - The watermark configuration with position, size, and opacity\n * @returns Mux overlay_settings object\n * @see {@link https://www.mux.com/docs/guides/add-watermarks-to-your-videos}\n */\nexport function convertWatermarkToMuxOverlay(\n watermark: WatermarkConfig,\n options?: {\n /**\n * Video aspect ratio (width / height). Needed for correct vertical positioning,\n * especially on vertical videos.\n */\n videoAspectRatio?: number\n /**\n * Unit to emit for margins/width when generating overlay_settings from Canvas mode.\n * - 'px' will generate pixel strings according to Mux's scaling rules:\n * values are applied as if the video were scaled to 1920x1080 (horizontal)\n * or 1080x1920 (vertical).\n * - '%' preserves existing behavior.\n */\n units?: '%' | 'px'\n },\n): MuxOverlaySettings | null {\n if (!watermark.enabled || !watermark.imageUrl) {\n return null\n }\n\n const size = watermark.size || 20\n const opacity = watermark.opacity ?? 0.7\n\n /**\n * Convert a percentage to whole-pixel string, using Mux's base dimensions:\n * - Horizontal video: 1920x1080\n * - Vertical video: 1080x1920\n */\n const toPxString = (valuePercent: number, axis: 'x' | 'y') => {\n const videoAspectRatio = options?.videoAspectRatio ?? 16 / 9\n const isVertical = videoAspectRatio > 0 && videoAspectRatio < 1\n const baseW = isVertical ? 1080 : 1920\n const baseH = isVertical ? 1920 : 1080\n const base = axis === 'x' ? baseW : baseH\n const px = (valuePercent / 100) * base\n let rounded = Math.round(px)\n // Avoid sending 0px (and JS -0); keep sign for negative margins.\n if (rounded === 0) rounded = px < 0 ? -1 : 1\n return `${rounded}px`\n }\n\n const normalizeToPixels = (value: string | undefined, axis: 'x' | 'y'): string | undefined => {\n if (!value) return value\n const trimmed = value.trim()\n if (trimmed.endsWith('px')) {\n return roundPxString(trimmed)\n }\n if (trimmed.endsWith('%')) {\n const n = Number(trimmed.slice(0, -1))\n if (!Number.isFinite(n)) return value\n return toPxString(n, axis)\n }\n return value\n }\n\n // If user provided explicit overlay settings, use them (Mux-documented format).\n // When `options.units === 'px'`, we normalize both % and px to whole-pixel strings,\n // honoring vertical vs horizontal video bases.\n if (watermark.overlay_settings) {\n const widthValue = watermark.overlay_settings.width\n const widthNormalized =\n options?.units === 'px' ? normalizeToPixels(widthValue, 'x') : widthValue\n return {\n ...watermark.overlay_settings,\n horizontal_margin:\n options?.units === 'px'\n ? (normalizeToPixels(watermark.overlay_settings.horizontal_margin, 'x') ??\n watermark.overlay_settings.horizontal_margin)\n : watermark.overlay_settings.horizontal_margin,\n vertical_margin:\n options?.units === 'px'\n ? (normalizeToPixels(watermark.overlay_settings.vertical_margin, 'y') ??\n watermark.overlay_settings.vertical_margin)\n : watermark.overlay_settings.vertical_margin,\n width: widthNormalized ?? `${size}%`,\n opacity: watermark.overlay_settings.opacity ?? `${Math.round(opacity * 100)}%`,\n }\n }\n\n const position = watermark.position || {x: 50, y: 50}\n\n /**\n * Our UI stores watermark position as the *center point* in percentages.\n * Mux margins are interpreted relative to an *edge* (based on align).\n *\n * To make \"corner\" placements match what the user dragged, we convert from\n * center-position to top-left margins by subtracting half the watermark size.\n *\n * Note: `size` is a percentage of video width. Mux `width` is also expressed\n * as a percentage of the video width, so we can reuse it for horizontal math.\n * For vertical math, we approximate using the same percentage to keep behavior\n * consistent with the current draggable UI (which also uses `size` in both axes\n * for bounds).\n */\n // Allow negative margins to compensate for rounding / letterboxing edge-cases.\n // We still clamp to a sane range so values don't explode.\n const clampPercent = (value: number) => Math.max(-100, Math.min(100, value))\n\n // Mux accepts percentage strings; avoid sending an exact \"0%\" by nudging to 0.01%.\n // This also handles the JS -0 edge case and tiny floating point remnants.\n const toPercentString = (value: number) => {\n const epsilon = 1e-9\n const isZeroish = value === 0 || Object.is(value, -0) || Math.abs(value) < epsilon\n return `${isZeroish ? 0.01 : value}%`\n }\n\n const watermarkWidthPercentOfVideoWidth = size\n\n /**\n * Convert watermark height into % of video height.\n * height% = (watermarkWidthPx / imageAspectRatio) / videoHeightPx\n * = (size% * videoWidthPx / imageAspectRatio) / videoHeightPx\n * = size% * (videoWidthPx/videoHeightPx) / imageAspectRatio\n * = size% * videoAspectRatio / imageAspectRatio\n */\n const videoAspectRatio = options?.videoAspectRatio ?? 16 / 9\n const imageAspectRatio = watermark.imageAspectRatio ?? 1\n const watermarkHeightPercentOfVideoHeight = Math.max(\n 0,\n Math.min(100, (size * videoAspectRatio) / imageAspectRatio),\n )\n\n const halfWidth = watermarkWidthPercentOfVideoWidth / 2\n const halfHeight = watermarkHeightPercentOfVideoHeight / 2\n\n const leftMargin = clampPercent(\n Math.min(position.x - halfWidth, 100 - watermarkWidthPercentOfVideoWidth),\n )\n const topMargin = clampPercent(\n Math.min(position.y - halfHeight, 100 - watermarkHeightPercentOfVideoHeight),\n )\n\n const units = options?.units ?? '%'\n const marginX = units === 'px' ? toPxString(leftMargin, 'x') : toPercentString(leftMargin)\n const marginY = units === 'px' ? toPxString(topMargin, 'y') : toPercentString(topMargin)\n const width = units === 'px' ? toPxString(size, 'x') : `${size}%`\n\n const overlaySettings: MuxOverlaySettings = {\n vertical_align: 'top',\n vertical_margin: marginY,\n horizontal_align: 'left',\n horizontal_margin: marginX,\n width,\n opacity: `${Math.round(opacity * 100)}%`,\n }\n\n return overlaySettings\n}\n","// From: https://stackoverflow.com/questions/10420352/converting-file-size-in-bytes-to-human-readable-string\n/**\n * Format bytes as human-readable text.\n *\n * @param bytes Number of bytes.\n * @param si True to use metric (SI) units, aka powers of 1000. False to use\n * binary (IEC), aka powers of 1024.\n * @param dp Number of decimal places to display.\n *\n * @return Formatted string.\n */\nexport default function formatBytes(bytes: number, si = false, dp = 1) {\n const thresh = si ? 1000 : 1024\n\n if (Math.abs(bytes) < thresh) {\n return bytes + ' B'\n }\n\n const units = si\n ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']\n : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']\n let u = -1\n const r = 10 ** dp\n\n do {\n bytes /= thresh\n ++u\n } while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1)\n\n return bytes.toFixed(dp) + ' ' + units[u]\n}\n","import {CheckmarkCircleIcon} from '@sanity/icons/CheckmarkCircle'\nimport {ErrorOutlineIcon} from '@sanity/icons/ErrorOutline'\nimport {Box, Button, Card, Flex, Grid, Stack, Text, TextInput} from '@sanity/ui'\nimport {useCallback, useEffect, useRef, useState} from 'react'\nimport {styled} from 'styled-components'\n\nimport {convertWatermarkToMuxOverlay} from '../util/convertWatermarkToMux'\nimport type {MuxOverlaySettings, WatermarkConfig} from '../util/types'\n\nconst RangeInput = styled.input`\n width: 100%;\n height: 4px;\n border-radius: 2px;\n background: var(--card-border-color);\n outline: none;\n -webkit-appearance: none;\n appearance: none;\n\n &::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: var(--card-focus-ring-color, #2276fc);\n cursor: pointer;\n border: 2px solid white;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n }\n\n &::-moz-range-thumb {\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: var(--card-focus-ring-color, #2276fc);\n cursor: pointer;\n border: 2px solid white;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n }\n\n &:hover::-webkit-slider-thumb {\n background: var(--card-focus-ring-color, #1a5fc7);\n }\n\n &:hover::-moz-range-thumb {\n background: var(--card-focus-ring-color, #1a5fc7);\n }\n`\n\nconst WatermarkOverlay = styled.div<{$opacity: number}>`\n position: absolute;\n max-width: 200px;\n opacity: ${(props) => props.$opacity};\n cursor: move;\n user-select: none;\n z-index: 10;\n pointer-events: auto;\n\n img {\n width: 100%;\n height: auto;\n display: block;\n pointer-events: none;\n }\n\n &:hover {\n outline: 2px dashed rgba(255, 255, 255, 0.8);\n outline-offset: 4px;\n }\n`\n\ninterface DraggableWatermarkProps {\n watermark: WatermarkConfig\n onChange: (watermark: WatermarkConfig) => void\n containerRef?: React.RefObject<HTMLDivElement>\n videoElementRef?: React.RefObject<HTMLVideoElement>\n}\n\nexport default function DraggableWatermark({\n watermark,\n onChange,\n containerRef,\n videoElementRef,\n}: DraggableWatermarkProps) {\n const [isDragging, setIsDragging] = useState(false)\n const [dragStart, setDragStart] = useState({x: 0, y: 0})\n const [startPosition, setStartPosition] = useState({x: 0, y: 0})\n const watermarkRef = useRef<HTMLDivElement>(null)\n const debounceTimeoutRef = useRef<NodeJS.Timeout | null>(null)\n const [localPosition, setLocalPosition] = useState(watermark.position || {x: 50, y: 50})\n\n const position = localPosition\n const size = watermark.size || 20\n const opacity = watermark.opacity ?? 0.7\n\n const parseOpacityPercent = (value: string | undefined): number | null => {\n if (!value) return null\n const trimmed = value.trim()\n if (!trimmed.endsWith('%')) return null\n const num = Number(trimmed.slice(0, -1))\n if (!Number.isFinite(num)) return null\n return Math.max(0, Math.min(1, num / 100))\n }\n\n const getVideoContentBox = useCallback(() => {\n const container = containerRef?.current\n if (!container) return {x: 0, y: 0, width: 0, height: 0}\n\n const rect = container.getBoundingClientRect()\n const containerW = rect.width\n const containerH = rect.height\n\n const videoEl = videoElementRef?.current\n const videoW = videoEl?.videoWidth || 0\n const videoH = videoEl?.videoHeight || 0\n\n if (!videoW || !videoH || !containerW || !containerH) {\n return {x: 0, y: 0, width: containerW, height: containerH}\n }\n\n // object-fit: contain sizing\n const scale = Math.min(containerW / videoW, containerH / videoH)\n const contentW = videoW * scale\n const contentH = videoH * scale\n const offsetX = (containerW - contentW) / 2\n const offsetY = (containerH - contentH) / 2\n\n return {x: offsetX, y: offsetY, width: contentW, height: contentH}\n }, [containerRef, videoElementRef])\n\n const parseOverlayValue = (value: string | undefined): {n: number; unit: '%' | 'px'} | null => {\n if (!value) return null\n const trimmed = value.trim()\n const px = trimmed.endsWith('px')\n const pct = trimmed.endsWith('%')\n const num = Number(trimmed.replace(/px|%/g, ''))\n if (!Number.isFinite(num)) return null\n if (px) return {n: num, unit: 'px'}\n if (pct) return {n: num, unit: '%'}\n return null\n }\n\n const computeManualStyle = (overlay: MuxOverlaySettings) => {\n const rect = containerRef?.current?.getBoundingClientRect()\n const w = rect?.width ?? 0\n const h = rect?.height ?? 0\n const isVertical = h > w\n const baseW = isVertical ? 1080 : 1920\n const baseH = isVertical ? 1920 : 1080\n\n const hm = parseOverlayValue(overlay.horizontal_margin)\n const vm = parseOverlayValue(overlay.vertical_margin)\n const ww = parseOverlayValue(overlay.width)\n const manualOpacity = parseOpacityPercent(overlay.opacity)\n\n const toCss = (v: {n: number; unit: '%' | 'px'} | null, axis: 'x' | 'y') => {\n if (!v) return undefined\n if (v.unit === '%') return `${v.n}%`\n if (axis === 'x') return `${(v.n * w) / baseW}px`\n return `${(v.n * h) / baseH}px`\n }\n\n const computeHorizontalStyle = () => {\n if (overlay.horizontal_align === 'left') {\n return {left: toCss(hm, 'x'), right: undefined, transform: 'translate(0, 0)'}\n }\n if (overlay.horizontal_align === 'right') {\n return {right: toCss(hm, 'x'), left: undefined, transform: 'translate(0, 0)'}\n }\n return {left: '50%', right: undefined, transform: 'translate(-50%, 0)'}\n }\n\n const computeVerticalStyle = () => {\n if (overlay.vertical_align === 'top') {\n return {top: toCss(vm, 'y'), bottom: undefined}\n }\n if (overlay.vertical_align === 'bottom') {\n return {bottom: toCss(vm, 'y'), top: undefined}\n }\n return {top: '50%', bottom: undefined}\n }\n\n const hStyle = computeHorizontalStyle()\n const vStyle = computeVerticalStyle()\n\n let transform = hStyle.transform\n if (overlay.vertical_align === 'middle') {\n transform =\n overlay.horizontal_align === 'center' ? 'translate(-50%, -50%)' : 'translate(0, -50%)'\n }\n\n return {\n position: 'absolute' as const,\n ...hStyle,\n ...vStyle,\n transform,\n width: ww ? toCss(ww, 'x') : `${size}%`,\n opacity: manualOpacity ?? opacity,\n cursor: 'default',\n }\n }\n\n const debouncedOnChange = useCallback(\n (newWatermark: WatermarkConfig) => {\n if (debounceTimeoutRef.current) {\n clearTimeout(debounceTimeoutRef.current)\n }\n debounceTimeoutRef.current = setTimeout(() => {\n onChange(newWatermark)\n }, 300)\n },\n [onChange],\n )\n\n useEffect(() => {\n return () => {\n if (debounceTimeoutRef.current) {\n clearTimeout(debounceTimeoutRef.current)\n }\n }\n }, [])\n\n useEffect(() => {\n if (!isDragging && watermark.position) {\n // oxlint-disable-next-line react/set-state-in-effect\n setLocalPosition(watermark.position)\n }\n }, [watermark.position, isDragging])\n\n const handleMouseDown = useCallback(\n (e: React.MouseEvent) => {\n e.preventDefault()\n setIsDragging(true)\n setDragStart({x: e.clientX, y: e.clientY})\n setStartPosition({x: position.x, y: position.y})\n },\n [position],\n )\n\n const handleMouseMove = useCallback(\n (e: MouseEvent) => {\n if (!isDragging || !containerRef?.current) return\n\n const container = containerRef.current\n const rect = container.getBoundingClientRect()\n const content = getVideoContentBox()\n const contentW = content.width || rect.width\n const contentH = content.height || rect.height\n const dx = e.clientX - dragStart.x\n const dy = e.clientY - dragStart.y\n\n const deltaXPercent = (dx / contentW) * 100\n const deltaYPercent = (dy / contentH) * 100\n\n let newX = startPosition.x + deltaXPercent\n let newY = startPosition.y + deltaYPercent\n\n newX = Math.max(0, Math.min(100, newX))\n newY = Math.max(0, Math.min(100, newY))\n\n setLocalPosition({x: newX, y: newY})\n\n debouncedOnChange({\n ...watermark,\n position: {x: newX, y: newY},\n })\n },\n [\n isDragging,\n dragStart,\n startPosition,\n containerRef,\n watermark,\n debouncedOnChange,\n getVideoContentBox,\n ],\n )\n\n const handleMouseUp = useCallback(() => {\n setIsDragging(false)\n if (debounceTimeoutRef.current) {\n clearTimeout(debounceTimeoutRef.current)\n debounceTimeoutRef.current = null\n }\n onChange({\n ...watermark,\n position: localPosition,\n })\n }, [watermark, localPosition, onChange])\n\n useEffect(() => {\n if (isDragging) {\n document.addEventListener('mousemove', handleMouseMove)\n document.addEventListener('mouseup', handleMouseUp)\n return () => {\n document.removeEventListener('mousemove', handleMouseMove)\n document.removeEventListener('mouseup', handleMouseUp)\n }\n }\n return undefined\n }, [isDragging, handleMouseMove, handleMouseUp])\n\n if (!watermark.imageUrl) {\n return null\n }\n\n const hasManualOverlay = Boolean(watermark.overlay_settings)\n const opacityForRender = hasManualOverlay\n ? (parseOpacityPercent(watermark.overlay_settings?.opacity) ?? opacity)\n : opacity\n // oxlint-disable-next-line react/refs\n const contentBox = getVideoContentBox()\n const hasContentBox = contentBox.width > 0 && contentBox.height > 0\n\n const computeWatermarkStyle = () => {\n if (hasManualOverlay) {\n return computeManualStyle(watermark.overlay_settings!)\n }\n if (hasContentBox) {\n return {\n left: `${contentBox.x + (position.x / 100) * contentBox.width}px`,\n top: `${contentBox.y + (position.y / 100) * contentBox.height}px`,\n transform: 'translate(-50%, -50%)',\n width: `${Math.max(1, (size / 100) * contentBox.width)}px`,\n cursor: isDragging ? 'grabbing' : 'grab',\n }\n }\n return {\n left: `${position.x}%`,\n top: `${position.y}%`,\n transform: 'translate(-50%, -50%)',\n width: `${size}%`,\n cursor: isDragging ? 'grabbing' : 'grab',\n }\n }\n\n return (\n <WatermarkOverlay\n ref={watermarkRef}\n $opacity={opacityForRender}\n onMouseDown={hasManualOverlay ? undefined : handleMouseDown}\n // oxlint-disable-next-line react/refs\n style={computeWatermarkStyle()}\n >\n <img src={watermark.imageUrl} alt=\"Watermark\" draggable={false} />\n </WatermarkOverlay>\n )\n}\n\ninterface WatermarkControlsProps {\n watermark: WatermarkConfig\n onChange: (watermark: WatermarkConfig) => void\n onValidationChange?: (error: string | null) => void\n previewContainerRef?: React.RefObject<HTMLDivElement | null>\n previewVideoRef?: React.RefObject<HTMLVideoElement | null>\n}\n\nexport function WatermarkControls({\n watermark,\n onChange,\n onValidationChange,\n previewContainerRef,\n previewVideoRef,\n}: WatermarkControlsProps) {\n const [urlInput, setUrlInput] = useState(watermark.imageUrl || '')\n const [urlError, setUrlError] = useState<string | null>(null)\n const [isValidating, setIsValidating] = useState(false)\n const [isValid, setIsValid] = useState<boolean | null>(null)\n const validationTimeoutRef = useRef<NodeJS.Timeout | null>(null)\n const [mode, setMode] = useState<'canvas' | 'manual'>(\n watermark.overlay_settings ? 'manual' : 'canvas',\n )\n\n const isUpdatingRef = useRef(false)\n\n const isValidExtension = useCallback((extension: string) => {\n return extension.endsWith('.png') || extension.endsWith('.jpg') || extension.endsWith('.jpeg')\n }, [])\n\n const validateUrl = useCallback(\n (url: string) => {\n if (validationTimeoutRef.current) {\n clearTimeout(validationTimeoutRef.current)\n }\n\n if (!url) {\n setUrlError(null)\n setIsValid(null)\n setIsValidating(false)\n onValidationChange?.(null)\n isUpdatingRef.current = true\n onChange({\n ...watermark,\n enabled: false,\n imageUrl: undefined,\n overlay_settings: undefined,\n })\n return\n }\n\n setIsValidating(true)\n setIsValid(null)\n setUrlError(null)\n\n validationTimeoutRef.current = setTimeout(() => {\n try {\n const urlObj = new URL(url)\n const pathname = urlObj.pathname.toLowerCase()\n if (isValidExtension(pathname)) {\n setIsValid(true)\n setUrlError(null)\n onValidationChange?.(null)\n const img = new Image()\n img.onload = () => {\n const imageAspectRatio =\n img.naturalWidth && img.naturalHeight ? img.naturalWidth / img.naturalHeight : 1\n isUpdatingRef.current = true\n onChange({\n ...watermark,\n enabled: true,\n imageUrl: url,\n imageAspectRatio,\n })\n }\n img.onerror = () => {\n isUpdatingRef.current = true\n onChange({\n ...watermark,\n enabled: true,\n imageUrl: url,\n imageAspectRatio: watermark.imageAspectRatio,\n })\n }\n img.src = url\n } else {\n const errorMsg =\n 'Mux only supports PNG and JPG watermark images. Please use a .png or .jpg file.'\n setIsValid(false)\n setUrlError(errorMsg)\n onValidationChange?.(errorMsg)\n isUpdatingRef.current = true\n onChange({\n ...watermark,\n enabled: false,\n imageUrl: undefined,\n imageAspectRatio: undefined,\n overlay_settings: undefined,\n })\n }\n } catch {\n setIsValid(false)\n const errorMsg = 'Please enter a valid URL (e.g., https://example.com/watermark.png)'\n setUrlError(errorMsg)\n onValidationChange?.(errorMsg)\n isUpdatingRef.current = true\n onChange({\n ...watermark,\n enabled: false,\n imageUrl: undefined,\n imageAspectRatio: undefined,\n overlay_settings: undefined,\n })\n // oxlint-disable-next-line react/todo\n } finally {\n setIsValidating(false)\n }\n }, 500)\n },\n [watermark, onChange, onValidationChange, isValidExtension],\n )\n\n useEffect(() => {\n return () => {\n if (validationTimeoutRef.current) {\n clearTimeout(validationTimeoutRef.current)\n }\n }\n }, [])\n\n useEffect(() => {\n // oxlint-disable-next-line react/set-state-in-effect\n setMode(watermark.overlay_settings ? 'manual' : 'canvas')\n }, [watermark.overlay_settings])\n\n const handleUrlChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const url = e.target.value\n setUrlInput(url)\n\n if (watermark.imageUrl && url !== watermark.imageUrl) {\n isUpdatingRef.current = true\n onChange({\n ...watermark,\n enabled: false,\n imageUrl: undefined,\n imageAspectRatio: undefined,\n overlay_settings: undefined,\n })\n }\n\n validateUrl(url)\n }\n\n const normalizeZeroPercent = (value: string | undefined) => {\n if (!value) return value\n const trimmed = value.trim()\n if (!trimmed.endsWith('%')) return value\n const n = Number(trimmed.slice(0, -1))\n if (!Number.isFinite(n)) return value\n const epsilon = 1e-9\n if (n === 0 || Object.is(n, -0) || Math.abs(n) < epsilon) return '0.01%'\n return `${n}%`\n }\n\n const updateOverlaySettings = (next: Partial<MuxOverlaySettings>) => {\n const prev = watermark.overlay_settings\n const base: MuxOverlaySettings = prev ?? {\n vertical_align: 'bottom',\n vertical_margin: '2%',\n horizontal_align: 'right',\n horizontal_margin: '2%',\n width: `${watermark.size ?? 20}%`,\n opacity: `${Math.round((watermark.opacity ?? 0.7) * 100)}%`,\n }\n\n const merged: MuxOverlaySettings = {\n ...base,\n ...next,\n }\n\n onChange({\n ...watermark,\n enabled: true,\n overlay_settings: {\n ...merged,\n horizontal_margin:\n normalizeZeroPercent(merged.horizontal_margin) || merged.horizontal_margin,\n vertical_margin: normalizeZeroPercent(merged.vertical_margin) || merged.vertical_margin,\n },\n })\n }\n\n const getVideoContentBox = () => {\n const container = previewContainerRef?.current\n if (!container) return {x: 0, y: 0, width: 0, height: 0}\n\n const rect = container.getBoundingClientRect()\n const containerW = rect.width\n const containerH = rect.height\n\n const videoEl = previewVideoRef?.current\n const videoW = videoEl?.videoWidth || 0\n const videoH = videoEl?.videoHeight || 0\n\n if (!videoW || !videoH || !containerW || !containerH) {\n return {x: 0, y: 0, width: containerW, height: containerH}\n }\n\n const scale = Math.min(containerW / videoW, containerH / videoH)\n const contentW = videoW * scale\n const contentH = videoH * scale\n const offsetX = (containerW - contentW) / 2\n const offsetY = (containerH - contentH) / 2\n\n return {x: offsetX, y: offsetY, width: contentW, height: contentH}\n }\n\n return (\n <Stack gap={3}>\n <Stack gap={2}>\n <Text size={1} weight=\"medium\">\n Watermark Image URL\n </Text>\n <Text size={0} muted>\n Enter a URL to a PNG or JPG image. Mux will download this image and overlay it on your\n video.\n </Text>\n <Box style={{position: 'relative', width: '100%'}}>\n <input\n type=\"url\"\n value={urlInput}\n onChange={handleUrlChange}\n placeholder=\"https://example.com/watermark.png\"\n style={{\n padding: '8px 12px',\n paddingRight: (() => {\n if (urlInput) return '96px'\n if (isValid !== null) return '36px'\n return '12px'\n })(),\n border: (() => {\n if (urlError || isValid === false) return '1px solid #e74c3c'\n if (isValid === true) return '1px solid #4caf50'\n return '1px solid #ccc'\n })(),\n borderRadius: '4px',\n width: '100%',\n maxWidth: '100%',\n boxSizing: 'border-box',\n fontSize: '14px',\n }}\n />\n {(urlInput || isValidating || isValid !== null) && (\n <Box\n style={{\n position: 'absolute',\n right: '8px',\n top: '50%',\n transform: 'translateY(-50%)',\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n }}\n >\n {urlInput && (\n <Button\n text=\"Clear\"\n mode=\"bleed\"\n tone=\"critical\"\n onClick={() => {\n setUrlInput('')\n validateUrl('')\n }}\n disabled={isValidating}\n style={{fontSize: '11px', height: '24px'}}\n />\n )}\n {isValidating && (\n <Text size={0} muted>\n Validating...\n </Text>\n )}\n {isValid === true && !isValidating && (\n <CheckmarkCircleIcon style={{color: '#4caf50', fontSize: '18px'}} />\n )}\n {isValid === false && !isValidating && (\n <ErrorOutlineIcon style={{color: '#e74c3c', fontSize: '18px'}} />\n )}\n </Box>\n )}\n </Box>\n {urlError && (\n <Card padding={2} tone=\"critical\" radius={2}>\n <Flex align=\"center\" gap={2}>\n <ErrorOutlineIcon style={{color: '#e74c3c', flexShrink: 0}} />\n <Text size={0} style={{color: '#e74c3c'}}>\n {urlError}\n </Text>\n </Flex>\n </Card>\n )}\n </Stack>\n\n {watermark.imageUrl && (\n <Stack gap={2}>\n <Card padding={3} tone=\"transparent\" border radius={2}>\n <Flex\n align=\"center\"\n justify=\"space-between\"\n gap={3}\n style={{flexWrap: 'wrap', alignItems: 'flex-start'}}\n >\n <Stack gap={2} style={{minWidth: 240, flex: 1}}>\n <Text size={1} weight=\"medium\">\n Positioning mode\n </Text>\n <Text size={0} muted>\n Choose between dragging on the canvas or manually editing the Mux{' '}\n <code>overlay_settings</code> fields (as in{' '}\n <a\n href=\"https://www.mux.com/docs/guides/add-watermarks-to-your-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n the docs\n </a>\n ).\n </Text>\n </Stack>\n <Flex gap={2} style={{flexWrap: 'wrap'}}>\n <Button\n text=\"Canvas\"\n mode={mode === 'canvas' ? 'default' : 'ghost'}\n onClick={() => {\n setMode('canvas')\n onChange({...watermark, enabled: true, overlay_settings: undefined})\n }}\n />\n <Button\n text=\"Manual\"\n mode={mode === 'manual' ? 'default' : 'ghost'}\n onClick={() => {\n setMode('manual')\n const overlay = convertWatermarkToMuxOverlay({...watermark, enabled: true})\n updateOverlaySettings(overlay ?? {})\n }}\n />\n </Flex>\n </Flex>\n </Card>\n\n {mode === 'manual' && (\n <Card padding={3} tone=\"transparent\" border radius={2}>\n <Stack gap={3}>\n <Text size={1} weight=\"medium\">\n Mux overlay_settings\n </Text>\n <Grid gridTemplateColumns={[1, 2]} gap={3} style={{width: '100%'}}>\n <Stack gap={2} style={{minWidth: 0}}>\n <Text size={0} muted>\n horizontal_align\n </Text>\n <select\n value={watermark.overlay_settings?.horizontal_align || 'right'}\n onChange={(e) =>\n updateOverlaySettings({\n horizontal_align: (e.target.value ||\n 'right') as MuxOverlaySettings['horizontal_align'],\n })\n }\n style={{\n width: '100%',\n padding: '8px 10px',\n border: '1px solid #ccc',\n borderRadius: 4,\n }}\n >\n <option value=\"left\">left</option>\n <option value=\"center\">center</option>\n <option value=\"right\">right</option>\n </select>\n </Stack>\n <Stack gap={2} style={{minWidth: 0}}>\n <Text size={0} muted>\n horizontal_margin (e.g. 2% or 40px)\n </Text>\n <TextInput\n value={watermark.overlay_settings?.horizontal_margin || '2%'}\n onChange={(e) =>\n updateOverlaySettings({horizontal_margin: e.currentTarget.value})\n }\n />\n </Stack>\n <Stack gap={2} style={{minWidth: 0}}>\n <Text size={0} muted>\n vertical_align\n </Text>\n <select\n value={watermark.overlay_settings?.vertical_align || 'bottom'}\n onChange={(e) =>\n updateOverlaySettings({\n vertical_align: (e.target.value ||\n 'bottom') as MuxOverlaySettings['vertical_align'],\n })\n }\n style={{\n width: '100%',\n padding: '8px 10px',\n border: '1px solid #ccc',\n borderRadius: 4,\n }}\n >\n <option value=\"top\">top</option>\n <option value=\"middle\">middle</option>\n <option value=\"bottom\">bottom</option>\n </select>\n </Stack>\n <Stack gap={2} style={{minWidth: 0}}>\n <Text size={0} muted>\n vertical_margin (e.g. 2% or 40px)\n </Text>\n <TextInput\n value={watermark.overlay_settings?.vertical_margin || '2%'}\n onChange={(e) =>\n updateOverlaySettings({vertical_margin: e.currentTarget.value})\n }\n />\n </Stack>\n <Stack gap={2} style={{minWidth: 0}}>\n <Text size={0} muted>\n width (e.g. 25% or 80px)\n </Text>\n <TextInput\n value={watermark.overlay_settings?.width || `${watermark.size ?? 20}%`}\n onChange={(e) => updateOverlaySettings({width: e.currentTarget.value})}\n />\n </Stack>\n <Stack gap={2} style={{minWidth: 0}}>\n <Text size={0} muted>\n opacity (e.g. 90%)\n </Text>\n <TextInput\n value={\n watermark.overlay_settings?.opacity ||\n `${Math.round((watermark.opacity ?? 0.7) * 100)}%`\n }\n onChange={(e) => updateOverlaySettings({opacity: e.currentTarget.value})}\n />\n </Stack>\n </Grid>\n <Text size={0} muted>\n Margins and width accept either percentages or pixels, per the Mux guide.\n </Text>\n </Stack>\n </Card>\n )}\n\n {mode === 'canvas' && (\n <>\n <Box>\n <Text size={1} weight=\"medium\">\n {/* oxlint-disable-next-line react/refs */}\n {(() => {\n const sizePct = watermark.size || 20\n const contentW = getVideoContentBox().width\n if (!contentW) return `Size: ${sizePct}%`\n const px = Math.max(1, Math.round((sizePct / 100) * contentW))\n return `Size: ${px}px`\n })()}\n </Text>\n <RangeInput\n type=\"range\"\n // oxlint-disable-next-line react/refs\n value={(() => {\n const sizePct = watermark.size || 20\n const contentW = getVideoContentBox().width\n if (!contentW) return sizePct\n return Math.max(1, Math.round((sizePct / 100) * contentW))\n })()}\n // oxlint-disable-next-line react/refs\n min={(() => {\n const contentW = getVideoContentBox().width\n if (!contentW) return 5\n return Math.max(1, Math.round(contentW * 0.05))\n })()}\n // oxlint-disable-next-line react/refs\n max={(() => {\n const contentW = getVideoContentBox().width\n if (!contentW) return 50\n return Math.max(1, Math.round(contentW * 0.5))\n })()}\n step={1}\n onChange={(e) => {\n const raw = Number(e.target.value)\n const contentW = getVideoContentBox().width\n const nextPct = contentW ? (raw / contentW) * 100 : raw\n const clampedPct = Math.max(5, Math.min(50, nextPct))\n onChange({\n ...watermark,\n size: clampedPct,\n })\n }}\n />\n </Box>\n\n <Box>\n <Text size={1} weight=\"medium\">\n Opacity: {Math.round((watermark.opacity ?? 0.7) * 100)}%\n </Text>\n <RangeInput\n type=\"range\"\n value={watermark.opacity ?? 0.7}\n min={0}\n max={1}\n step={0.05}\n onChange={(e) =>\n onChange({\n ...watermark,\n opacity: Number(e.target.value),\n })\n }\n />\n </Box>\n </>\n )}\n\n <Card padding={2} tone=\"transparent\" border radius={2}>\n <Text size={0} muted>\n {mode === 'manual'\n ? 'Manual mode: edit the overlay_settings fields above'\n : '💡 Drag the watermark on the preview to position it'}\n </Text>\n </Card>\n </Stack>\n )}\n </Stack>\n )\n}\n","import {TranslateIcon} from '@sanity/icons/Translate'\nimport {Box, Card, Checkbox, Flex, Stack, Text} from '@sanity/ui'\nimport {Autocomplete} from '@sanity/ui/autocomplete'\nimport {uuid} from '@sanity/uuid'\nimport LanguagesList from 'iso-639-1'\nimport {type Dispatch} from 'react'\nimport {FormField} from 'sanity'\n\nimport {type PluginConfig, SUPPORTED_MUX_LANGUAGES, type UploadTextTrack} from '../util/types'\n\nconst ALL_LANGUAGE_CODES = LanguagesList.getAllCodes().map((code) => ({\n value: code,\n label: LanguagesList.getNativeName(code),\n}))\n\nconst SUBTITLE_LANGUAGES: Record<\n Extract<UploadTextTrack, {language_code: any}>['type'],\n {value: string; label: string}[]\n> = {\n autogenerated: SUPPORTED_MUX_LANGUAGES.map((lang) => ({\n value: lang.code,\n label: lang.label,\n })),\n subtitles: ALL_LANGUAGE_CODES,\n captions: ALL_LANGUAGE_CODES,\n}\n\ntype TrackSubAction =\n | {subAction: 'add'; value: Partial<UploadTextTrack>}\n | {subAction: 'update'; value: Partial<UploadTextTrack>}\n | {subAction: 'delete'}\n\nexport type TrackAction = {action: 'track'; id: string} & TrackSubAction\n\nexport default function TextTracksEditor({\n tracks,\n dispatch,\n defaultLang,\n}: {\n /**\n * Although the schema for tracks is an array, which we'll eventually support to allow uploading\n * multiple custom subtitles, for now we only support a single auto-generated track.\n */\n tracks: (Partial<UploadTextTrack> & {_id: string})[]\n dispatch: Dispatch<TrackAction>\n defaultLang: PluginConfig['defaultAutogeneratedSubtitleLang']\n}) {\n const track = tracks[0]\n return (\n <FormField title=\"Auto-generated subtitle or caption\" path={[]}>\n <Stack gap={2}>\n <Flex align=\"center\">\n <Checkbox\n id=\"include-autogenerated-track\"\n style={{display: 'block'}}\n checked={!!track?.language_code}\n onChange={() => {\n if (track) {\n dispatch({action: 'track', id: track._id, subAction: 'delete'})\n } else {\n dispatch({\n action: 'track',\n id: uuid(),\n subAction: 'add',\n value: {\n type: 'autogenerated',\n name: defaultLang || undefined,\n language_code: defaultLang || undefined,\n },\n })\n }\n }}\n />\n <Box flex={1} paddingLeft={3}>\n <Text>\n <label htmlFor=\"checkbox\">Generate captions</label>\n </Text>\n </Box>\n </Flex>\n {track && (\n <Autocomplete\n id={`text-tract-editor--language`}\n value={track.language_code}\n onChange={(newValue) =>\n dispatch({\n action: 'track',\n id: track._id,\n subAction: 'update',\n value: {\n language_code: newValue,\n name: LanguagesList.getNativeName(newValue),\n },\n })\n }\n options={SUBTITLE_LANGUAGES[track.type!]}\n icon={TranslateIcon}\n placeholder=\"Select language\"\n filterOption={(query, option) =>\n option.label.toLowerCase().indexOf(query.toLowerCase()) > -1 ||\n option.value.toLowerCase().indexOf(query.toLowerCase()) > -1\n }\n openButton\n renderValue={(value) =>\n SUBTITLE_LANGUAGES[track.type!].find((l) => l.value === value)?.label || value\n }\n renderOption={(option) => (\n <Card data-as=\"button\" padding={3} radius={2} tone=\"inherit\">\n <Text size={2} textOverflow=\"ellipsis\">\n {option.label} ({option.value})\n </Text>\n </Card>\n )}\n />\n )}\n </Stack>\n </FormField>\n )\n}\n","import {Checkbox, Flex, Grid, Text} from '@sanity/ui'\nimport {type ActionDispatch, type CSSProperties, type ReactNode, useState} from 'react'\n\nimport {type UploadConfigurationStateAction} from '../UploadConfiguration'\n\nexport default function PlaybackPolicyOption({\n id,\n checked,\n optionName,\n description,\n dispatch,\n action,\n disabled,\n}: {\n id: string\n checked: boolean\n optionName: string\n description: string | ReactNode\n dispatch: ActionDispatch<[action: UploadConfigurationStateAction]>\n action?: 'public_policy' | 'signed_policy' | 'drm_policy'\n disabled?: boolean\n}) {\n const [scale, setScale] = useState(1)\n\n const boxStyle: CSSProperties = {\n outline: '0.01rem solid grey',\n transform: `scale(${scale})`,\n transition: 'transform 0.1s ease-in-out',\n cursor: disabled ? 'not-allowed' : 'pointer',\n borderRadius: '0.25rem',\n }\n\n const triggerAnimation = () => {\n setScale(0.98)\n setTimeout(() => {\n setScale(1)\n }, 100)\n }\n\n const handleBoxClick = () => {\n if (!action) return\n triggerAnimation()\n dispatch({\n action,\n value: !checked,\n })\n }\n\n const descriptionJsx =\n typeof description === 'string' ? (\n <Text size={2} muted>\n {description}\n </Text>\n ) : (\n description\n )\n return (\n <label>\n <Flex gap={3} padding={3} style={boxStyle}>\n <Checkbox\n id={id}\n required\n checked={checked}\n onChange={handleBoxClick}\n disabled={disabled}\n />\n <Grid gap={3}>\n <Text size={3} weight=\"bold\">\n {optionName}\n </Text>\n {descriptionJsx}\n </Grid>\n </Flex>\n </label>\n )\n}\n","import {WarningFilledIcon} from '@sanity/icons/WarningFilled'\nimport {Box, Flex, Text} from '@sanity/ui'\nimport {type CSSProperties} from 'react'\n\nexport default function PlaybackPolicyWarning() {\n const textStyle: CSSProperties = {\n color: '#13141A',\n fontWeight: 500,\n }\n\n const boxStyle: CSSProperties = {\n outline: '0.01rem solid grey',\n backgroundColor: '#979cb0',\n borderRadius: '0.5rem',\n width: 'max-content',\n color: '#13141A',\n }\n\n return (\n <Box padding={2} style={boxStyle}>\n <Flex align=\"center\" gap={2}>\n <WarningFilledIcon />\n <Text size={1} style={textStyle}>\n Please select at least one Playback Policy\n </Text>\n </Flex>\n </Box>\n )\n}\n","import {Grid, Text} from '@sanity/ui'\nimport {Code} from '@sanity/ui/code'\nimport {type ActionDispatch} from 'react'\n\nimport {type Secrets, type UploadConfig} from '../../util/types'\nimport {type UploadConfigurationStateAction} from '../UploadConfiguration'\nimport PlaybackPolicyOption from './PlaybackPolicyOption'\nimport PlaybackPolicyWarning from './PlaybackPolicyWarning'\n\nexport default function PlaybackPolicy({\n id,\n config,\n secrets,\n dispatch,\n}: {\n id: string\n config: UploadConfig\n secrets: Secrets\n dispatch: ActionDispatch<[action: UploadConfigurationStateAction]>\n}) {\n const noPolicySelected = !(config.public_policy || config.signed_policy || config.drm_policy)\n const drmPolicyDisabled = !secrets.drmConfigId\n return (\n <Grid gap={3}>\n <Text weight=\"bold\">Advanced Playback Policies</Text>\n <PlaybackPolicyOption\n id={`${id}--public`}\n checked={config.public_policy}\n optionName=\"Public\"\n description={\n <>\n <Text size={2} muted>\n Playback IDs are accessible by constructing an HLS URL like\n </Text>\n <Code>{'https://stream.mux.com/{PLAYBACK_ID}'}</Code>\n </>\n }\n dispatch={dispatch}\n action=\"public_policy\"\n />\n {secrets.enableSignedUrls && (\n <PlaybackPolicyOption\n id={`${id}--signed`}\n checked={config.signed_policy}\n optionName=\"Signed\"\n description={\n <>\n <Text size={2} muted>\n Playback IDs should be used with tokens\n </Text>\n <Code>{'https://stream.mux.com/{PLAYBACK_ID}?token={TOKEN}'}</Code>\n <Text size={2} muted>\n See{' '}\n <a\n href=\"https://www.mux.com/docs/guides/secure-video-playback\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Secure video playback\n </a>{' '}\n for details about creating tokens.\n </Text>\n </>\n }\n // See Secure video playback for details about creating tokens.\"\n dispatch={dispatch}\n action=\"signed_policy\"\n />\n )}\n {drmPolicyDisabled ? (\n <PlaybackPolicyOption\n id={`${id}--drm`}\n checked={false}\n optionName=\"DRM - Disabled\"\n description={\n <>\n <Text size={2} muted>\n To enable DRM add your DRM Configuration Id to your plugin configuration in the API\n Credentials view.{' '}\n <a\n href=\"https://www.mux.com/support/human\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Contact us\n </a>{' '}\n to get started using DRM.\n </Text>\n </>\n }\n dispatch={dispatch}\n disabled\n />\n ) : (\n <PlaybackPolicyOption\n id={`${id}--drm`}\n checked={config.drm_policy}\n optionName=\"DRM\"\n description={\n <>\n <Text size={2} muted>\n Playback IDs should be used with tokens as with Signed playback, but require extra\n configuration.\n </Text>\n <Code>{'https://stream.mux.com/{PLAYBACK_ID}?token={TOKEN}'}</Code>\n <Text size={2} muted>\n See{' '}\n <a\n href=\"https://www.mux.com/docs/guides/protect-videos-with-drm#play-drm-protected-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Protect videos with DRM\n </a>{' '}\n for details about configuring your player for DRM playback and{' '}\n <a\n href=\"https://www.mux.com/docs/guides/secure-video-playback\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Secure video playback\n </a>{' '}\n for details about creating tokens.\n </Text>\n </>\n }\n dispatch={dispatch}\n action=\"drm_policy\"\n />\n )}\n {noPolicySelected && <PlaybackPolicyWarning />}\n </Grid>\n )\n}\n","import {Flex, Radio, Text} from '@sanity/ui'\nimport {type ActionDispatch} from 'react'\nimport {FormField} from 'sanity'\n\nimport {type UploadConfig} from '../../util/types'\nimport {type UploadConfigurationStateAction} from '../UploadConfiguration'\n\nexport const RESOLUTION_TIERS = [\n {value: '1080p', label: '1080p'},\n {value: '1440p', label: '1440p (2k)'},\n {value: '2160p', label: '2160p (4k)'},\n] as const satisfies {value: UploadConfig['max_resolution_tier']; label: string}[]\n\nexport const ResolutionTierSelector = ({\n id,\n config,\n dispatch,\n maxSupportedResolution,\n}: {\n id: string\n config: UploadConfig\n dispatch: ActionDispatch<[action: UploadConfigurationStateAction]>\n maxSupportedResolution: number\n}) => {\n return (\n <FormField\n path={[]}\n title=\"Resolution Tier\"\n description={\n <>\n The maximum{' '}\n <a\n href=\"https://docs.mux.com/api-reference#video/operation/create-direct-upload\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n resolution_tier\n </a>{' '}\n your asset is encoded, stored, and streamed at.\n </>\n }\n >\n <Flex gap={3} wrap={'wrap'}>\n {RESOLUTION_TIERS.map(({value, label}, index) => {\n const inputId = `${id}--type-${value}`\n\n if (index > maxSupportedResolution) return null\n\n return (\n <Flex key={value} align=\"center\" gap={2}>\n <Radio\n checked={config.max_resolution_tier === value}\n name=\"asset-resolutiontier\"\n onChange={(e) =>\n dispatch({\n action: 'max_resolution_tier',\n value: e.currentTarget.value as UploadConfig['max_resolution_tier'],\n })\n }\n value={value}\n id={inputId}\n />\n <Text as=\"label\" htmlFor={inputId}>\n {label}\n </Text>\n </Flex>\n )\n })}\n </Flex>\n </FormField>\n )\n}\n","import {Checkbox, Flex, Label, Radio, Stack, Text} from '@sanity/ui'\nimport {type ActionDispatch, useMemo, useState} from 'react'\nimport {FormField} from 'sanity'\n\nimport {type StaticRenditionResolution, type UploadConfig} from '../../util/types'\nimport {type UploadConfigurationStateAction} from '../UploadConfiguration'\n\nconst ADVANCED_RESOLUTIONS: {value: StaticRenditionResolution; label: string}[] = [\n {value: '270p', label: '270p'},\n {value: '360p', label: '360p'},\n {value: '480p', label: '480p'},\n {value: '540p', label: '540p'},\n {value: '720p', label: '720p'},\n {value: '1080p', label: '1080p'},\n {value: '1440p', label: '1440p'},\n {value: '2160p', label: '2160p'},\n]\n\nexport const StaticRenditionSelector = ({\n id,\n config,\n dispatch,\n}: {\n id: string\n config: UploadConfig\n dispatch: ActionDispatch<[action: UploadConfigurationStateAction]>\n}) => {\n // Determine if user is in advanced mode based on selected renditions\n const isAdvancedMode = useMemo(() => {\n const specificResolutions = config.static_renditions.filter(\n (r) => r !== 'highest' && r !== 'audio-only',\n )\n return specificResolutions.length > 0\n }, [config.static_renditions])\n\n const [renditionMode, setRenditionMode] = useState<'standard' | 'advanced'>(\n isAdvancedMode ? 'advanced' : 'standard',\n )\n\n // Helper to toggle a rendition\n const toggleRendition = (rendition: StaticRenditionResolution) => {\n const current = config.static_renditions\n const hasRendition = current.includes(rendition)\n\n if (hasRendition) {\n dispatch({\n action: 'static_renditions',\n value: current.filter((r) => r !== rendition),\n })\n } else {\n dispatch({\n action: 'static_renditions',\n value: [...current, rendition],\n })\n }\n }\n\n // When switching modes, clear renditions that don't apply\n const handleModeChange = (mode: 'standard' | 'advanced') => {\n setRenditionMode(mode)\n if (mode === 'standard') {\n // Remove specific resolutions, keep only highest and audio-only\n dispatch({\n action: 'static_renditions',\n value: config.static_renditions.filter((r) => r === 'highest' || r === 'audio-only'),\n })\n } else {\n // Remove highest, keep specific resolutions and audio-only\n dispatch({\n action: 'static_renditions',\n value: config.static_renditions.filter((r) => r !== 'highest'),\n })\n }\n }\n return (\n <Stack gap={3}>\n <FormField\n path={[]}\n title=\"Static Renditions\"\n description=\"Generate downloadable MP4 or M4A files. Note: Mux will not upscale to produce MP4 renditions - renditions that would cause upscaling are skipped.\"\n >\n <Stack gap={3}>\n {/* Mode Selector */}\n <Flex gap={3}>\n <Flex align=\"center\" gap={2}>\n <Radio\n checked={renditionMode === 'standard'}\n name=\"rendition-mode\"\n onChange={() => handleModeChange('standard')}\n value=\"standard\"\n id={`${id}--mode-standard`}\n />\n <Text as=\"label\" htmlFor={`${id}--mode-standard`}>\n Standard\n </Text>\n </Flex>\n <Flex align=\"center\" gap={2}>\n <Radio\n checked={renditionMode === 'advanced'}\n name=\"rendition-mode\"\n onChange={() => handleModeChange('advanced')}\n value=\"advanced\"\n id={`${id}--mode-advanced`}\n />\n <Text as=\"label\" htmlFor={`${id}--mode-advanced`}>\n Advanced\n </Text>\n </Flex>\n </Flex>\n\n {/* Standard Mode Options */}\n {renditionMode === 'standard' && (\n <Stack gap={2}>\n <Flex align=\"center\" gap={2} padding={[0, 2]}>\n <Checkbox\n id={`${id}--highest`}\n style={{display: 'block'}}\n checked={config.static_renditions.includes('highest')}\n onChange={() => toggleRendition('highest')}\n />\n <Text as=\"label\" htmlFor={`${id}--highest`}>\n Highest Resolution (up to 4K)\n </Text>\n </Flex>\n <Flex align=\"center\" gap={2} padding={[0, 2]}>\n <Checkbox\n id={`${id}--audio-only-standard`}\n style={{display: 'block'}}\n checked={config.static_renditions.includes('audio-only')}\n onChange={() => toggleRendition('audio-only')}\n />\n <Text as=\"label\" htmlFor={`${id}--audio-only-standard`}>\n Audio Only (M4A)\n </Text>\n </Flex>\n </Stack>\n )}\n\n {/* Advanced Mode Options */}\n {renditionMode === 'advanced' && (\n <Stack gap={2}>\n <Label size={1} muted>\n Select specific resolutions:\n </Label>\n <Flex gap={2} wrap=\"wrap\">\n {ADVANCED_RESOLUTIONS.map(({value, label}) => {\n const inputId = `${id}--resolution-${value}`\n return (\n <Flex key={value} align=\"center\" gap={2}>\n <Checkbox\n id={inputId}\n style={{display: 'block'}}\n checked={config.static_renditions.includes(value)}\n onChange={() => toggleRendition(value)}\n />\n <Text as=\"label\" htmlFor={inputId} size={1}>\n {label}\n </Text>\n </Flex>\n )\n })}\n </Flex>\n <Flex align=\"center\" gap={2} padding={[2, 2, 0, 2]}>\n <Checkbox\n id={`${id}--audio-only-advanced`}\n style={{display: 'block'}}\n checked={config.static_renditions.includes('audio-only')}\n onChange={() => toggleRendition('audio-only')}\n />\n <Text as=\"label\" htmlFor={`${id}--audio-only-advanced`}>\n Audio Only (M4A)\n </Text>\n </Flex>\n </Stack>\n )}\n </Stack>\n </FormField>\n </Stack>\n )\n}\n","import {DocumentVideoIcon} from '@sanity/icons/DocumentVideo'\nimport {ErrorOutlineIcon} from '@sanity/icons/ErrorOutline'\nimport {UploadIcon} from '@sanity/icons/Upload'\nimport {Box, Button, Card, Dialog, Flex, Label, Radio, Stack, Text} from '@sanity/ui'\nimport {uuid} from '@sanity/uuid'\nimport LanguagesList from 'iso-639-1'\nimport {memo, useEffect, useId, useReducer, useRef, useState} from 'react'\nimport {FormField} from 'sanity'\n\nimport {useFetchFileSize} from '../hooks/useFetchFileSize'\nimport {useMediaMetadata, type VideoAssetMetadata} from '../hooks/useMediaMetadata'\nimport {convertWatermarkToMuxOverlay} from '../util/convertWatermarkToMux'\nimport formatBytes from '../util/formatBytes'\nimport {formatSeconds} from '../util/formatSeconds'\nimport {\n type AutogeneratedTextTrack,\n type CustomTextTrack,\n isAutogeneratedTrack,\n isCustomTextTrack,\n type MuxNewAssetSettings,\n type PluginConfig,\n type Secrets,\n type StaticRenditionResolution,\n type SupportedMuxLanguage,\n type UploadConfig,\n type UploadTextTrack,\n type WatermarkConfig,\n} from '../util/types'\nimport DraggableWatermark, {WatermarkControls} from './DraggableWatermark'\nimport TextTracksEditor, {type TrackAction} from './TextTracksEditor'\nimport PlaybackPolicy from './uploadConfiguration/PlaybackPolicy'\nimport {\n RESOLUTION_TIERS,\n ResolutionTierSelector,\n} from './uploadConfiguration/ResolutionTierSelector'\nimport {StaticRenditionSelector} from './uploadConfiguration/StaticRenditionSelector'\nimport type {StagedUpload} from './Uploader'\n\nexport type UploadConfigurationStateAction =\n | {action: 'video_quality'; value: UploadConfig['video_quality']}\n | {action: 'max_resolution_tier'; value: UploadConfig['max_resolution_tier']}\n | {action: 'static_renditions'; value: UploadConfig['static_renditions']}\n | {action: 'normalize_audio'; value: UploadConfig['normalize_audio']}\n | {action: 'signed_policy'; value: UploadConfig['signed_policy']}\n | {action: 'public_policy'; value: UploadConfig['public_policy']}\n | {action: 'drm_policy'; value: UploadConfig['drm_policy']}\n | {action: 'watermark'; value: WatermarkConfig}\n | TrackAction\n\nconst VIDEO_QUALITY_LEVELS = [\n {value: 'basic', label: 'Basic'},\n {value: 'plus', label: 'Plus'},\n {value: 'premium', label: 'Premium'},\n] as const satisfies {value: UploadConfig['video_quality']; label: string}[]\n\n/**\n * Sanitizes static renditions configuration to ensure 'highest' is not mixed with specific resolutions.\n * If both are present, only 'highest' (and 'audio-only' if present) will be kept.\n */\nfunction sanitizeStaticRenditions(\n renditions: StaticRenditionResolution[],\n): StaticRenditionResolution[] {\n const hasHighest = renditions.includes('highest')\n const hasSpecificResolutions = renditions.some((r) => r !== 'highest' && r !== 'audio-only')\n\n if (hasHighest && hasSpecificResolutions) {\n return renditions.filter((r) => r === 'highest' || r === 'audio-only')\n }\n\n return renditions\n}\n\n/**\n * The modal for configuring a staged upload. Handles triggering of the asset\n * upload, even if no modal needs to be shown.\n *\n * @returns\n */\nexport default function UploadConfiguration({\n stagedUpload,\n secrets,\n pluginConfig,\n startUpload,\n onClose,\n}: {\n stagedUpload: StagedUpload\n secrets: Secrets\n pluginConfig: PluginConfig\n startUpload: (settings: MuxNewAssetSettings, watermark: WatermarkConfig | undefined) => void\n onClose: () => void\n}) {\n const id = useId()\n const [watermarkValidationError, setWatermarkValidationError] = useState<string | null>(null)\n const watermarkPreviewContainerRef = useRef<HTMLDivElement>(null)\n const watermarkPreviewVideoRef = useRef<HTMLVideoElement>(null)\n const autoTextTracks = useRef<NonNullable<UploadConfig['text_tracks']>>(\n pluginConfig.video_quality === 'plus' && pluginConfig.defaultAutogeneratedSubtitleLang\n ? [\n {\n _id: uuid(),\n type: 'autogenerated',\n language_code: pluginConfig.defaultAutogeneratedSubtitleLang,\n name: LanguagesList.getNativeName(pluginConfig.defaultAutogeneratedSubtitleLang),\n } satisfies AutogeneratedTextTrack,\n ]\n : [],\n ).current\n\n const [config, dispatch] = useReducer(\n (prev: UploadConfig, action: UploadConfigurationStateAction) => {\n switch (action.action) {\n case 'video_quality':\n // If video quality level switches to basic, remove plus-only features\n if (action.value === 'basic') {\n return Object.assign({}, prev, {\n video_quality: action.value,\n static_renditions: [],\n max_resolution_tier: '1080p',\n text_tracks: prev.text_tracks?.filter(({type}) => type !== 'autogenerated'),\n public_policy: true,\n signed_policy: false,\n drm_policy: false,\n })\n // If video quality level switches to plus, add back in default plus features\n }\n return Object.assign({}, prev, {\n video_quality: action.value,\n static_renditions: sanitizeStaticRenditions(pluginConfig.static_renditions || []),\n max_resolution_tier: pluginConfig.max_resolution_tier,\n text_tracks: [...autoTextTracks, ...(prev.text_tracks || [])],\n })\n\n case 'static_renditions':\n case 'max_resolution_tier':\n case 'normalize_audio':\n case 'signed_policy':\n return Object.assign({}, prev, {[action.action]: action.value})\n case 'public_policy':\n return Object.assign({}, prev, {[action.action]: action.value})\n case 'drm_policy':\n return Object.assign({}, prev, {[action.action]: action.value})\n case 'watermark':\n return Object.assign({}, prev, {watermark: action.value})\n // Updating individual tracks\n case 'track': {\n const text_tracks = [...prev.text_tracks]\n const target_track_i = text_tracks.findIndex(({_id}) => _id === action.id)\n switch (action.subAction) {\n case 'add':\n // Exit early if track already exists\n if (target_track_i !== -1) break\n text_tracks.push({\n _id: action.id,\n ...action.value,\n } as AutogeneratedTextTrack)\n break\n case 'update':\n if (target_track_i === -1) break\n text_tracks[target_track_i] = {\n ...text_tracks[target_track_i],\n ...action.value,\n } as UploadTextTrack\n break\n case 'delete':\n if (target_track_i === -1) break\n text_tracks.splice(target_track_i, 1)\n break\n }\n return Object.assign({}, prev, {text_tracks})\n }\n default:\n return prev\n }\n },\n {\n video_quality: pluginConfig.video_quality,\n max_resolution_tier: pluginConfig.max_resolution_tier,\n static_renditions: sanitizeStaticRenditions(pluginConfig.static_renditions || []),\n signed_policy: secrets.enableSignedUrls && pluginConfig.defaultSigned,\n public_policy: pluginConfig.defaultPublic,\n drm_policy: pluginConfig.defaultDrm && !!secrets.drmConfigId,\n normalize_audio: pluginConfig.normalize_audio,\n text_tracks: autoTextTracks,\n } as UploadConfig,\n )\n\n // Video validations\n const [validationError, setValidationError] = useState<string | null>(null)\n const MAX_FILE_SIZE = pluginConfig.maxAssetFileSize\n const MAX_DURATION_SECONDS = pluginConfig.maxAssetDuration\n\n const {fileSize, isLoadingFileSize, canSkipFileSizeValidation} = useFetchFileSize(\n stagedUpload,\n MAX_FILE_SIZE,\n )\n const {videoAssetMetadata, setVideoAssetMetadata, isLoadingMetadata} =\n useMediaMetadata(stagedUpload)\n\n useEffect(() => {\n if (fileSize) {\n setVideoAssetMetadata((old) => ({...old, size: fileSize}))\n }\n }, [fileSize, setVideoAssetMetadata])\n\n useEffect(() => {\n const validateDuration = (duration: number) => {\n if (MAX_DURATION_SECONDS && duration > MAX_DURATION_SECONDS) {\n setValidationError(\n `Video duration (${formatSeconds(duration)}) exceeds maximum allowed duration of ${formatSeconds(MAX_DURATION_SECONDS)}`,\n )\n return false\n }\n return true\n }\n\n const validateFileSize = (size: number): boolean => {\n if (MAX_FILE_SIZE === undefined || size <= MAX_FILE_SIZE) {\n return true\n }\n\n setValidationError(\n `File size (${formatBytes(size)}) exceeds maximum allowed size of ${formatBytes(MAX_FILE_SIZE)}`,\n )\n return false\n }\n\n const validateDrmAvailability = (isAudioOnly: boolean) => {\n if (config.drm_policy && isAudioOnly) {\n setValidationError('Audio-only asset cannot be DRM protected')\n return false\n }\n return true\n }\n\n let valid = true\n if (videoAssetMetadata?.size) {\n valid = valid && (canSkipFileSizeValidation || validateFileSize(videoAssetMetadata.size))\n }\n if (videoAssetMetadata?.duration) {\n valid = valid && validateDuration(videoAssetMetadata.duration)\n }\n if (videoAssetMetadata?.isAudioOnly != undefined) {\n valid = valid && validateDrmAvailability(videoAssetMetadata.isAudioOnly)\n }\n if (valid) {\n setValidationError(null)\n }\n }, [\n MAX_FILE_SIZE,\n MAX_DURATION_SECONDS,\n canSkipFileSizeValidation,\n videoAssetMetadata?.duration,\n videoAssetMetadata?.size,\n videoAssetMetadata?.height,\n videoAssetMetadata?.width,\n videoAssetMetadata,\n config.drm_policy,\n validationError,\n ])\n\n // If user-provided config is disabled, begin the upload immediately with\n // the developer-specified values from the schema or config or defaults.\n // This can include auto-generated subtitles!\n const {disableTextTrackConfig, disableUploadConfig} = pluginConfig\n const skipConfig = disableTextTrackConfig && disableUploadConfig\n useEffect(() => {\n if (skipConfig) {\n const {settings, watermark} = formatUploadConfig(config, secrets, {\n videoAspectRatio: videoAssetMetadata?.aspectRatio,\n })\n startUpload(settings, watermark)\n }\n // oxlint-disable-next-line react/rule-suppression\n // oxlint-disable-next-line react/exhaustive-deps -- intentionally mount-only: start upload once with developer-specified config\n }, [])\n if (skipConfig) return null\n\n const basicConfig = config.video_quality !== 'plus' && config.video_quality !== 'premium'\n const playbackPolicySelected = config.public_policy || config.signed_policy || config.drm_policy\n const maxSupportedResolution = RESOLUTION_TIERS.findIndex(\n (rt) => rt.value === pluginConfig.max_resolution_tier,\n )\n return (\n <Dialog\n animate\n open\n id=\"upload-configuration\"\n zOffset={1000}\n width={1}\n header=\"Configure Mux Upload\"\n onClose={onClose}\n >\n <Stack padding={4} gap={2}>\n {(validationError || watermarkValidationError) && (\n <Card padding={3} tone=\"critical\" radius={2} marginBottom={2}>\n <Flex gap={2} align=\"flex-start\">\n <ErrorOutlineIcon width={20} height={20} />\n <Stack gap={2}>\n <Text size={1} weight=\"semibold\">\n Validation Error\n </Text>\n <Text size={1}>{validationError || watermarkValidationError}</Text>\n </Stack>\n </Flex>\n </Card>\n )}\n <Label size={3}>FILE TO UPLOAD</Label>\n <Card\n tone=\"transparent\"\n border\n padding={3}\n paddingY={4}\n style={{borderRadius: '0.1865rem'}}\n >\n <Flex gap={2}>\n <DocumentVideoIcon fontSize=\"2em\" />\n <Stack gap={2}>\n <Text textOverflow=\"ellipsis\" as=\"h2\" size={3}>\n {stagedUpload.type === 'file' ? stagedUpload.files[0]!.name : stagedUpload.url}\n </Text>\n <Text as=\"p\" size={1} muted>\n {stagedUpload.type === 'file'\n ? `Direct File Upload (${formatBytes(stagedUpload.files[0]!.size)})`\n : (() => {\n if (videoAssetMetadata?.size) {\n return `File From URL (${formatBytes(videoAssetMetadata.size)})`\n }\n if (isLoadingFileSize) {\n return 'File From URL (Loading size...)'\n }\n return 'File From URL (Unknown size)'\n })()}\n </Text>\n {stagedUpload.type === 'file' && (\n <Stack gap={1}>\n {isLoadingMetadata && (\n <Text as=\"p\" size={1} muted>\n Reading video metadata...\n </Text>\n )}\n {videoAssetMetadata?.duration && !validationError && (\n <Text as=\"p\" size={1} muted>\n Duration: {formatSeconds(videoAssetMetadata.duration)}\n </Text>\n )}\n </Stack>\n )}\n </Stack>\n </Flex>\n </Card>\n {!disableUploadConfig && (\n <Stack gap={3} paddingBottom={2}>\n <FormField\n path={[]}\n title=\"Video Quality Level\"\n description={\n <>\n The video quality level informs the cost, quality, and available platform features\n for the asset.{' '}\n <a\n href=\"https://docs.mux.com/guides/use-encoding-tiers\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n See the Mux guide for more details.\n </a>\n </>\n }\n >\n <Flex gap={3}>\n {VIDEO_QUALITY_LEVELS.map(({value, label}) => {\n const inputId = `${id}--encodingtier-${value}`\n return (\n <Flex key={value} align=\"center\" gap={2}>\n <Radio\n checked={config.video_quality === value}\n name=\"asset-encodingtier\"\n onChange={(e) =>\n dispatch({\n action: 'video_quality' as const,\n value: e.currentTarget.value as UploadConfig['video_quality'],\n })\n }\n value={value}\n id={inputId}\n />\n <Text as=\"label\" htmlFor={inputId}>\n {label}\n </Text>\n </Flex>\n )\n })}\n </Flex>\n </FormField>\n\n {!basicConfig && (\n <>\n <FormField title=\"Additional Configuration\" path={[]}>\n <Stack gap={3}>\n <PlaybackPolicy id={id} config={config} secrets={secrets} dispatch={dispatch} />\n {maxSupportedResolution > 0 && (\n <ResolutionTierSelector\n id={id}\n config={config}\n dispatch={dispatch}\n maxSupportedResolution={maxSupportedResolution}\n />\n )}\n <StaticRenditionSelector id={id} config={config} dispatch={dispatch} />\n {!disableTextTrackConfig && (\n <TextTracksEditor\n tracks={config.text_tracks}\n dispatch={dispatch}\n defaultLang={pluginConfig.defaultAutogeneratedSubtitleLang}\n />\n )}\n </Stack>\n </FormField>\n <WatermarkSection\n config={config}\n dispatch={dispatch}\n stagedUpload={stagedUpload}\n videoAssetMetadata={videoAssetMetadata}\n watermarkPreviewContainerRef={watermarkPreviewContainerRef}\n watermarkPreviewVideoRef={watermarkPreviewVideoRef}\n onValidationChange={setWatermarkValidationError}\n />\n </>\n )}\n </Stack>\n )}\n\n <Box marginTop={4}>\n <Button\n disabled={\n (!basicConfig && !playbackPolicySelected) ||\n validationError !== null ||\n isLoadingMetadata ||\n (isLoadingFileSize && !canSkipFileSizeValidation)\n }\n icon={UploadIcon}\n text=\"Upload\"\n tone=\"positive\"\n onClick={() => {\n if (!validationError) {\n const {settings, watermark} = formatUploadConfig(config, secrets, {\n videoAspectRatio: videoAssetMetadata?.aspectRatio,\n })\n startUpload(settings, watermark)\n }\n }}\n />\n </Box>\n </Stack>\n </Dialog>\n )\n}\n\nfunction setAdvancedPlaybackPolicy(\n config: UploadConfig,\n secrets: Secrets,\n): MuxNewAssetSettings['advanced_playback_policies'] {\n const advanced_playback_policies: MuxNewAssetSettings['advanced_playback_policies'] = []\n if (config.public_policy) {\n advanced_playback_policies.push({policy: 'public'})\n }\n if (config.signed_policy) {\n advanced_playback_policies.push({policy: 'signed'})\n }\n if (config.drm_policy) {\n if (secrets.drmConfigId)\n advanced_playback_policies.push({\n policy: 'drm',\n drm_configuration_id: secrets.drmConfigId ?? undefined,\n })\n else {\n console.error('Selected DRM Policy but missing DRM Configuration Id')\n }\n }\n return advanced_playback_policies\n}\n\nfunction formatUploadConfig(\n config: UploadConfig,\n secrets: Secrets,\n options?: {videoAspectRatio?: number | null},\n): {\n settings: MuxNewAssetSettings\n watermark?: WatermarkConfig\n} {\n const generated_subtitles = config.text_tracks\n .filter<AutogeneratedTextTrack>(isAutogeneratedTrack)\n .map<{name: string; language_code: SupportedMuxLanguage}>((track) => ({\n name: track.name,\n language_code: track.language_code,\n }))\n\n const inputs: NonNullable<MuxNewAssetSettings['input']> = [\n {\n type: 'video',\n generated_subtitles: generated_subtitles.length > 0 ? generated_subtitles : undefined,\n },\n ...config.text_tracks.filter<CustomTextTrack>(isCustomTextTrack).reduce(\n (acc, track) => {\n if (track.language_code && track.file && track.name) {\n acc.push({\n url: track.file.contents,\n type: 'text',\n text_type: track.type === 'subtitles' ? 'subtitles' : undefined,\n language_code: track.language_code,\n name: track.name,\n closed_captions: track.type === 'captions',\n })\n }\n return acc\n },\n [] as NonNullable<MuxNewAssetSettings['input']>,\n ),\n ]\n\n if (config.watermark?.imageUrl) {\n const watermarkForMux: WatermarkConfig = {...config.watermark, enabled: true}\n const overlaySettings = convertWatermarkToMuxOverlay(watermarkForMux, {\n videoAspectRatio: options?.videoAspectRatio ?? undefined,\n units: 'px',\n })\n if (overlaySettings) {\n inputs.push({\n url: config.watermark.imageUrl,\n overlay_settings: overlaySettings,\n })\n }\n }\n\n return {\n settings: {\n input: inputs,\n static_renditions:\n config.static_renditions.length > 0\n ? config.static_renditions.map((resolution) => ({resolution}))\n : undefined,\n advanced_playback_policies: setAdvancedPlaybackPolicy(config, secrets),\n max_resolution_tier: config.max_resolution_tier,\n video_quality: config.video_quality,\n normalize_audio: config.normalize_audio,\n },\n watermark: config.watermark?.imageUrl ? {...config.watermark, enabled: true} : undefined,\n }\n}\n\nfunction WatermarkSection({\n config,\n dispatch,\n stagedUpload,\n videoAssetMetadata,\n watermarkPreviewContainerRef,\n watermarkPreviewVideoRef,\n onValidationChange,\n}: {\n config: UploadConfig\n dispatch: (action: UploadConfigurationStateAction) => void\n stagedUpload: StagedUpload\n videoAssetMetadata: VideoAssetMetadata | null\n watermarkPreviewContainerRef: React.RefObject<HTMLDivElement | null>\n watermarkPreviewVideoRef: React.RefObject<HTMLVideoElement | null>\n onValidationChange: (error: string | null) => void\n}) {\n if (videoAssetMetadata?.isAudioOnly !== false) return null\n return (\n <FormField\n path={[]}\n title=\"Watermark\"\n description={\n <>\n Add a watermark overlay to your video using Mux's native watermark support.{' '}\n <a\n href=\"https://www.mux.com/docs/guides/add-watermarks-to-your-videos\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Learn more about Mux watermarks.\n </a>\n </>\n }\n >\n <Stack gap={3}>\n <WatermarkControls\n watermark={config.watermark || {enabled: false}}\n onChange={(watermark) => {\n dispatch({action: 'watermark', value: watermark})\n }}\n onValidationChange={onValidationChange}\n previewContainerRef={watermarkPreviewContainerRef}\n previewVideoRef={watermarkPreviewVideoRef}\n />\n {config.watermark?.imageUrl &&\n stagedUpload.type === 'file' &&\n // Canvas preview is only shown in \"Canvas\" mode (no explicit overlay_settings)\n !config.watermark.overlay_settings && (\n <WatermarkPreview\n stagedUpload={stagedUpload}\n watermark={config.watermark}\n videoAspectRatio={videoAssetMetadata.aspectRatio}\n onWatermarkChange={(watermark) => {\n dispatch({action: 'watermark', value: watermark})\n }}\n previewContainerRef={watermarkPreviewContainerRef}\n videoRef={watermarkPreviewVideoRef}\n />\n )}\n </Stack>\n </FormField>\n )\n}\n\n// Memoized preview component to prevent unnecessary re-renders\nconst WatermarkPreview = memo(function WatermarkPreview({\n stagedUpload,\n watermark,\n onWatermarkChange,\n videoAspectRatio,\n previewContainerRef,\n videoRef,\n}: {\n stagedUpload: StagedUpload\n watermark: WatermarkConfig\n onWatermarkChange: (watermark: WatermarkConfig) => void\n videoAspectRatio?: number | null\n previewContainerRef: React.RefObject<HTMLDivElement | null>\n videoRef: React.RefObject<HTMLVideoElement | null>\n}) {\n // Initialize video source only once\n useEffect(() => {\n if (videoRef.current && stagedUpload.type === 'file') {\n const file = stagedUpload.files[0]\n const url = URL.createObjectURL(file!)\n videoRef.current.src = url\n\n return () => {\n URL.revokeObjectURL(url)\n }\n }\n return undefined\n }, [stagedUpload, videoRef])\n\n const isVertical =\n videoAspectRatio !== null && videoAspectRatio !== undefined && videoAspectRatio < 1\n\n return (\n <Card\n tone=\"transparent\"\n border\n style={{\n overflow: 'hidden',\n // For vertical videos, center the preview and limit its width\n display: 'flex',\n justifyContent: 'center',\n }}\n >\n {/* Inner container that exactly matches the video aspect ratio - no padding, no letterbox */}\n <div\n ref={previewContainerRef}\n style={{\n position: 'relative',\n // For vertical videos: limit width so the preview doesn't get too tall\n // For horizontal videos: use full width\n width: isVertical ? 'auto' : '100%',\n aspectRatio: videoAspectRatio ? String(videoAspectRatio) : '16/9',\n ...(isVertical ? {height: '400px', maxHeight: '50vh'} : {minHeight: '200px'}),\n overflow: 'hidden',\n }}\n >\n <video\n ref={videoRef}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n objectFit: 'fill',\n display: 'block',\n }}\n />\n <DraggableWatermark\n watermark={watermark}\n onChange={onWatermarkChange}\n containerRef={previewContainerRef as React.RefObject<HTMLDivElement>}\n videoElementRef={videoRef as React.RefObject<HTMLVideoElement>}\n />\n </div>\n </Card>\n )\n})\n","import {rem} from '@sanity/ui'\nimport type {ComponentType} from 'react'\nimport {css, styled} from 'styled-components'\n\nimport {focusRingBorderStyle, focusRingStyle} from './helpers'\n\nexport function withFocusRing<Props extends object>(component: ComponentType<Props>) {\n // `$border` is the only consumer-facing addition; `theme` comes from styled-components\n // (injected via DefaultTheme / ExecutionContext) and must not appear on public props.\n return styled(component)<{$border?: boolean}>(({$border, theme}) => {\n const border = {\n width: $border ? 1 : 0,\n color: 'var(--card-border-color)',\n }\n\n return css`\n --card-focus-box-shadow: ${focusRingBorderStyle(border)};\n\n border-radius: ${rem(\n // oxlint-disable-next-line no-deprecated -- deferred to a follow-up PR\n theme.sanity.radius[1]!,\n )};\n outline: none;\n box-shadow: var(--card-focus-box-shadow);\n\n &:focus {\n --card-focus-box-shadow: ${focusRingStyle({\n base:\n // oxlint-disable-next-line no-deprecated -- deferred to a follow-up PR\n theme.sanity.color.base,\n border,\n focusRing:\n // oxlint-disable-next-line no-deprecated -- deferred to a follow-up PR\n theme.sanity.focusRing,\n })};\n }\n `\n })\n}\n","import {Card, type CardTone} from '@sanity/ui'\nimport {useCallback, useRef} from 'react'\nimport {styled} from 'styled-components'\n\nimport {withFocusRing} from './withFocusRing'\n\nconst UploadCardWithFocusRing = withFocusRing(Card)\n\ninterface UploadCardProps {\n tone?: CardTone\n children: React.ReactNode\n onPaste: React.ClipboardEventHandler<HTMLInputElement>\n onDrop: React.DragEventHandler<HTMLDivElement>\n onDragOver: React.DragEventHandler<HTMLDivElement>\n onDragLeave: React.DragEventHandler<HTMLDivElement>\n onDragEnter: React.DragEventHandler<HTMLDivElement>\n}\nexport function UploadCard({\n children,\n tone,\n onPaste,\n onDrop,\n onDragEnter,\n onDragLeave,\n onDragOver,\n ref,\n}: UploadCardProps & {ref?: React.Ref<HTMLDivElement>}) {\n const inputRef = useRef<HTMLInputElement>(null)\n const handleKeyDown = useCallback<React.KeyboardEventHandler<HTMLDivElement>>((event) => {\n const target = event.target as HTMLElement\n\n // Don't steal focus when pasting into the VTT input\n if (target.closest('#vtt-url')) {\n return\n }\n\n if ((event.ctrlKey || event.metaKey) && event.key === 'v') {\n inputRef.current!.focus()\n }\n }, [])\n\n return (\n <UploadCardWithFocusRing\n tone={tone}\n ref={ref}\n padding={0}\n radius={2}\n shadow={0}\n tabIndex={0}\n onKeyDown={handleKeyDown}\n onPaste={onPaste}\n onDrop={onDrop}\n onDragEnter={onDragEnter}\n onDragLeave={onDragLeave}\n onDragOver={onDragOver}\n >\n <HiddenInput ref={inputRef} />\n {children}\n </UploadCardWithFocusRing>\n )\n}\n\nconst HiddenInput = styled.input.attrs({type: 'text'})`\n position: absolute;\n border: 0;\n color: white;\n opacity: 0;\n\n &:focus {\n outline: none;\n }\n`\n","import {Button, type ButtonProps} from '@sanity/ui'\nimport {useCallback, useId, useRef} from 'react'\nimport {styled} from 'styled-components'\n\nconst HiddenInput = styled.input`\n overflow: hidden;\n width: 0.1px;\n height: 0.1px;\n opacity: 0;\n position: absolute;\n z-index: -1;\n`\n\nconst Label = styled.label`\n position: relative;\n`\n\nexport interface FileInputButtonProps extends Omit<ButtonProps, 'onSelect'> {\n onSelect: (files: FileList) => void\n accept: string\n}\nexport const FileInputButton = ({onSelect, accept, ...props}: FileInputButtonProps) => {\n const inputId = `FileSelect${useId()}`\n const inputRef = useRef<HTMLInputElement>(null)\n const handleSelect = useCallback<React.ChangeEventHandler<HTMLInputElement>>(\n (event) => {\n if (onSelect) {\n onSelect(event.target.files!)\n }\n },\n [onSelect],\n )\n const handleButtonClick = useCallback(() => inputRef.current?.click(), [])\n return (\n <Label htmlFor={inputId}>\n <HiddenInput\n accept={accept}\n ref={inputRef}\n tabIndex={0}\n type=\"file\"\n id={inputId}\n onChange={handleSelect}\n value=\"\"\n />\n <Button\n onClick={handleButtonClick}\n mode=\"default\"\n tone=\"primary\"\n style={{width: '100%'}}\n {...props}\n />\n </Label>\n )\n}\n","import {DocumentVideoIcon} from '@sanity/icons/DocumentVideo'\nimport {PlugIcon} from '@sanity/icons/Plug'\nimport {SearchIcon} from '@sanity/icons/Search'\nimport {UploadIcon} from '@sanity/icons/Upload'\nimport {Button, Card, Flex, Inline, Text} from '@sanity/ui'\nimport {useCallback} from 'react'\n\nimport {useAccessControl} from '../hooks/useAccessControl'\nimport type {SetDialogState} from '../hooks/useDialogState'\nimport {type PluginConfig} from '../util/types'\nimport {FileInputButton, type FileInputButtonProps} from './FileInputButton'\n\nfunction formatAcceptString(accept: string): string {\n return accept\n .split(',')\n .map((type) => type.trim().replace('/*', ''))\n .join(' or ')\n}\n\ninterface UploadPlaceholderProps {\n setDialogState: SetDialogState\n readOnly: boolean\n hovering: boolean\n needsSetup: boolean\n onSelect: FileInputButtonProps['onSelect']\n config: PluginConfig\n accept: string\n}\nexport default function UploadPlaceholder(props: UploadPlaceholderProps) {\n const {setDialogState, readOnly, onSelect, hovering, needsSetup, accept} = props\n const handleBrowse = useCallback(() => setDialogState('select-video'), [setDialogState])\n const handleConfigureApi = useCallback(() => setDialogState('secrets'), [setDialogState])\n const {hasConfigAccess} = useAccessControl(props.config)\n\n return (\n <Card\n sizing=\"border\"\n tone={readOnly ? 'transparent' : 'inherit'}\n border\n radius={2}\n paddingX={3}\n paddingY={1}\n style={hovering ? {borderColor: 'transparent'} : undefined}\n >\n <Flex\n align=\"center\"\n justify=\"space-between\"\n gap={4}\n direction={['column', 'column', 'row']}\n paddingY={2}\n sizing=\"border\"\n >\n <Flex align=\"center\" justify=\"flex-start\" gap={2} flex={1}>\n <Flex justify=\"center\">\n <Text muted>\n <DocumentVideoIcon />\n </Text>\n </Flex>\n <Flex justify=\"center\">\n <Text size={1} muted>\n Drag {formatAcceptString(accept)} file or paste URL here\n </Text>\n </Flex>\n </Flex>\n <Inline gap={2}>\n <FileInputButton\n accept={accept}\n mode=\"bleed\"\n tone=\"default\"\n icon={UploadIcon}\n text=\"Upload\"\n onSelect={onSelect}\n />\n <Button mode=\"bleed\" icon={SearchIcon} text=\"Select\" onClick={handleBrowse} />\n\n {hasConfigAccess && (\n <Button\n padding={3}\n radius={3}\n tone={needsSetup ? 'critical' : undefined}\n onClick={handleConfigureApi}\n icon={PlugIcon}\n mode=\"bleed\"\n title=\"Configure plugin credentials\"\n />\n )}\n </Inline>\n </Flex>\n </Card>\n )\n}\n","import {ErrorOutlineIcon} from '@sanity/icons/ErrorOutline'\nimport {Button, type CardTone, Flex, Text} from '@sanity/ui'\nimport {useToast} from '@sanity/ui/toast'\nimport {useCallback, useEffect, useReducer, useRef, useState} from 'react'\nimport {type Observable, Subject, Subscription} from 'rxjs'\nimport {takeUntil, tap} from 'rxjs/operators'\nimport type {SanityClient} from 'sanity'\nimport {PatchEvent, set, setIfMissing} from 'sanity'\n\nimport {uploadFile, uploadUrl} from '../actions/upload'\nimport {DialogStateProvider} from '../context/DialogStateContext'\nimport {type DialogState, type SetDialogState} from '../hooks/useDialogState'\nimport {isServerError, isValidUrl} from '../util/asserters'\nimport {extractDroppedFiles} from '../util/extractFiles'\nimport {hasPlaybackPolicy} from '../util/getPlaybackPolicy'\nimport type {\n MuxInputProps,\n MuxNewAssetSettings,\n PluginConfig,\n Secrets,\n VideoAssetDocument,\n} from '../util/types'\nimport InputBrowser from './InputBrowser'\nimport Player from './Player'\nimport PlayerActionsMenu from './PlayerActionsMenu'\nimport UploadConfiguration from './UploadConfiguration'\nimport {UploadCard} from './Uploader.styled'\nimport UploadPlaceholder from './UploadPlaceholder'\nimport {UploadProgress} from './UploadProgress'\n\ninterface Props extends Pick<MuxInputProps, 'onChange' | 'readOnly'> {\n config: PluginConfig\n client: SanityClient\n secrets: Secrets\n asset: VideoAssetDocument | null | undefined\n dialogState: DialogState\n setDialogState: SetDialogState\n needsSetup: boolean\n}\n\nexport type StagedUpload = {type: 'file'; files: FileList | File[]} | {type: 'url'; url: string}\ntype UploadStatus = {\n progress: number\n file?: {name: string | undefined; type: string}\n uuid?: string\n url?: string\n}\n\ninterface State {\n stagedUpload: StagedUpload | null\n uploadStatus: UploadStatus | null\n error: Error | null\n}\n\nconst INITIAL_STATE: State = {\n stagedUpload: null,\n uploadStatus: null,\n error: null,\n}\n\ntype UploadFileEvent = ReturnType<typeof uploadFile> extends Observable<infer T> ? T : never\ntype UploadUrlEvent = ReturnType<typeof uploadUrl> extends Observable<infer T> ? T : never\ntype UploaderStateAction =\n | {action: 'stageUpload'; input: NonNullable<State['stagedUpload']>}\n | {action: 'commitUpload'}\n | ({action: 'progressInfo'} & (\n | Extract<UploadFileEvent, {type: 'uuid' | 'file'}>\n | Extract<UploadUrlEvent, {type: 'url'}>\n ))\n | {action: 'progress'; percent: number}\n | {action: 'error'; error: Error; settings: MuxNewAssetSettings}\n | {action: 'complete' | 'reset'}\n\n/**\n * The main interface for inputting a Mux Video. It handles staging an upload\n * file, setting its configuration, displaying upload progress, and showing\n * the preview player.\n */\nexport default function Uploader(props: Props) {\n const toast = useToast()\n const containerRef = useRef<HTMLDivElement>(null)\n\n const dragEnteredEls = useRef<EventTarget[]>([])\n const [dragState, setDragState] = useState<'valid' | 'invalid' | null>(null)\n\n const cancelUploadButton = useRef(\n (() => {\n const events$ = new Subject()\n return {\n observable: events$.asObservable(),\n handleClick: (event: React.MouseEvent<HTMLButtonElement>) => events$.next(event),\n }\n })(),\n ).current\n\n const uploadRef = useRef<Subscription | null>(null)\n const uploadingDocumentId = useRef<string | null>(null)\n const [state, dispatch] = useReducer(\n // oxlint-disable-next-line react/refs\n (prev: State, action: UploaderStateAction) => {\n switch (action.action) {\n case 'stageUpload':\n return Object.assign({}, INITIAL_STATE, {stagedUpload: action.input})\n case 'commitUpload':\n return Object.assign({}, prev, {uploadStatus: {progress: 0}})\n case 'progressInfo': {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {type, action: _, ...payload} = action\n return Object.assign({}, prev, {\n uploadStatus: {\n ...prev.uploadStatus,\n progress: prev.uploadStatus!.progress,\n ...payload,\n },\n } satisfies Pick<typeof prev, 'uploadStatus'>)\n }\n case 'progress':\n return Object.assign({}, prev, {\n uploadStatus: {\n ...prev.uploadStatus,\n progress: action.percent,\n },\n } satisfies Pick<typeof prev, 'uploadStatus'>)\n case 'reset':\n case 'complete':\n // Clear upload observable on completion\n uploadRef.current?.unsubscribe()\n uploadRef.current = null\n uploadingDocumentId.current = null\n return INITIAL_STATE\n case 'error': {\n // Clear upload observable on error\n uploadRef.current?.unsubscribe()\n uploadRef.current = null\n uploadingDocumentId.current = null\n\n let error = action.error\n if (isServerError(action.error) && hasPlaybackPolicy(action.settings, 'drm')) {\n error = new Error(\n 'Unknown Error while uploading DRM protected content. Make sure your DRM configuration ID is valid and set correctly',\n )\n }\n\n return Object.assign({}, INITIAL_STATE, {error: error})\n }\n default:\n return prev\n }\n },\n {\n stagedUpload: null,\n uploadStatus: null,\n error: null,\n },\n )\n\n // Make sure we close out the upload observer on dismount\n // and cleanup orphaned documents if upload was in progress\n useEffect(() => {\n const cleanup = () => {\n // Cancel subscription\n if (uploadRef.current && !uploadRef.current.closed) {\n uploadRef.current.unsubscribe()\n }\n\n // Delete orphaned document if upload was in progress and document is different from the saved asset\n if (uploadingDocumentId.current && props.asset?._id !== uploadingDocumentId.current) {\n const docId = uploadingDocumentId.current\n uploadingDocumentId.current = null\n\n props.client.delete(docId).catch((err) => {\n console.warn('Failed to cleanup orphaned upload document:', err)\n })\n }\n }\n\n const handleBeforeUnload = () => {\n cleanup()\n }\n\n window.addEventListener('beforeunload', handleBeforeUnload)\n window.addEventListener('pagehide', handleBeforeUnload)\n\n return () => {\n window.removeEventListener('beforeunload', handleBeforeUnload)\n window.removeEventListener('pagehide', handleBeforeUnload)\n cleanup()\n }\n }, [props.client, props.asset?._id])\n\n /* -------------------------------------------------------------------------- */\n /* Uploading */\n /* -------------------------------------------------------------------------- */\n\n /**\n * Begins a file or URL upload with the staged files or URL.\n *\n * Should only be called from the UploadConfiguration component, which provides\n * the Mux configuration for the direct asset upload.\n *\n * @param settings The Mux new_asset_settings object to send to Sanity\n * @param watermark Optional watermark configuration\n * @returns\n */\n const startUpload = (\n settings: MuxNewAssetSettings,\n watermark?: import('../util/types').WatermarkConfig,\n ) => {\n const {stagedUpload} = state\n if (!stagedUpload || uploadRef.current) return\n dispatch({action: 'commitUpload'})\n let uploadObservable: Observable<UploadFileEvent | UploadUrlEvent>\n switch (stagedUpload.type) {\n case 'url':\n uploadObservable = uploadUrl({\n client: props.client,\n url: stagedUpload.url,\n settings,\n watermark,\n })\n break\n case 'file':\n uploadObservable = uploadFile({\n client: props.client,\n file: stagedUpload.files[0]!,\n settings,\n watermark,\n }).pipe(\n takeUntil(\n cancelUploadButton.observable.pipe(\n tap(() => {\n if (uploadingDocumentId.current) {\n void props.client.delete(uploadingDocumentId.current)\n uploadingDocumentId.current = null\n }\n }),\n ),\n ),\n )\n break\n }\n uploadRef.current = uploadObservable.subscribe({\n next: (event) => {\n switch (event.type) {\n case 'uuid':\n // Track the document ID for cleanup on unmount\n uploadingDocumentId.current = event.uuid\n dispatch({action: 'progressInfo', ...event})\n break\n case 'file':\n case 'url':\n dispatch({action: 'progressInfo', ...event})\n break\n case 'progress':\n dispatch({action: 'progress', percent: event.percent})\n break\n case 'success':\n dispatch({action: 'progress', percent: 100})\n uploadingDocumentId.current = null\n props.onChange(\n PatchEvent.from([\n setIfMissing({asset: {}}),\n set({_type: 'reference', _weak: true, _ref: event.asset._id}, ['asset']),\n ]),\n )\n break\n case 'pause':\n case 'resume':\n default:\n break\n }\n },\n complete: () => dispatch({action: 'complete'}),\n error: (error) => dispatch({action: 'error', error, settings}),\n })\n }\n\n const invalidFileToast = useCallback(() => {\n toast.push({\n status: 'error',\n title: `Invalid file type. Accepted types: ${props.config.acceptedMimeTypes?.join(', ')}`,\n })\n }, [props.config.acceptedMimeTypes, toast])\n\n /**\n * Validates if any file in the provided FileList or File array has an unsupported MIME type\n * @param files - FileList or File array to validate\n * @returns true if any file has an invalid MIME type, false if all files are valid\n */\n const isInvalidFile = (files: FileList | File[]) => {\n const isInvalid = Array.from(files).some((file) => {\n return !props.config.acceptedMimeTypes?.some((acceptedType) => {\n // Convert mime type pattern to regex (e.g., 'audio/*' -> /^audio\\/.*$/)\n const pattern = `^${acceptedType.replace('*', '.*')}$`\n return new RegExp(pattern).test(file.type)\n })\n })\n\n return isInvalid\n }\n\n /* -------------------------- Upload Initialization ------------------------- */\n // The below populate the uploadInput state field, which then triggers the\n // upload configuration, or the startUpload function if no config is required.\n\n // Stages an upload from the file selector\n const handleUpload = (files: FileList | File[]) => {\n if (isInvalidFile(files)) return\n dispatch({\n action: 'stageUpload',\n input: {type: 'file', files},\n })\n }\n\n // Stages and validates an upload from pasting an asset URL\n const handlePaste: React.ClipboardEventHandler<HTMLInputElement> = (event) => {\n const target = event.target as HTMLElement\n\n // Ignore paste coming from the VTT URL input\n if (target.closest('#vtt-url')) {\n return\n }\n\n event.preventDefault()\n event.stopPropagation()\n const clipboardData =\n event.clipboardData || (window as Window & {clipboardData?: DataTransfer}).clipboardData\n const url = clipboardData?.getData('text')?.trim()\n if (!isValidUrl(url)) {\n toast.push({status: 'error', title: 'Invalid URL for Mux video input.'})\n return\n }\n dispatch({action: 'stageUpload', input: {type: 'url', url: url}})\n }\n\n // Stages and validates an upload from dragging+dropping files or folders\n const handleDrop: React.DragEventHandler<HTMLDivElement> = (event) => {\n event.preventDefault()\n event.stopPropagation()\n if (dragState === 'invalid') {\n invalidFileToast()\n setDragState(null)\n return\n }\n setDragState(null)\n void extractDroppedFiles(event.nativeEvent.dataTransfer!).then((files) => {\n dispatch({\n action: 'stageUpload',\n input: {type: 'file', files},\n })\n })\n }\n\n /* ------------------------------- Drag State ------------------------------- */\n\n const handleDragOver: React.DragEventHandler<HTMLDivElement> = (event) => {\n event.preventDefault()\n event.stopPropagation()\n }\n\n const handleDragEnter: React.DragEventHandler<HTMLDivElement> = (event) => {\n event.stopPropagation()\n dragEnteredEls.current.push(event.target)\n const type = event.dataTransfer.items?.[0]?.type\n const mimeTypes = props.config.acceptedMimeTypes\n\n // Check if the dragged file type matches any of the accepted mime types\n const isValidType = mimeTypes?.some((acceptedType) => {\n // Convert mime type pattern to regex (e.g., 'video/*' -> /^video\\/.*$/)\n const pattern = `^${acceptedType.replace('*', '.*')}$`\n return new RegExp(pattern).test(type!)\n })\n\n setDragState(isValidType ? 'valid' : 'invalid')\n }\n\n const handleDragLeave: React.DragEventHandler<HTMLDivElement> = (event) => {\n event.stopPropagation()\n const idx = dragEnteredEls.current.indexOf(event.target)\n if (idx > -1) {\n dragEnteredEls.current.splice(idx, 1)\n }\n if (dragEnteredEls.current.length === 0) {\n setDragState(null)\n }\n }\n\n /* -------------------------------- Rendering ------------------------------- */\n\n // Upload has errored\n if (state.error !== null) {\n const error = state.error\n return (\n <Flex gap={3} direction=\"column\" justify=\"center\" align=\"center\">\n <Text size={5} muted>\n <ErrorOutlineIcon />\n </Text>\n <Text>Something went wrong</Text>\n {error instanceof Error && error.message && (\n <Text size={1} muted weight=\"semibold\" style={{textAlign: 'center'}}>\n {error.message}\n </Text>\n )}\n <Button text=\"Upload another file\" onClick={() => dispatch({action: 'reset'})} />\n </Flex>\n )\n }\n\n // Upload is in progress\n if (state.uploadStatus !== null) {\n const {uploadStatus} = state\n return (\n <UploadProgress\n // oxlint-disable-next-line react/refs\n onCancel={cancelUploadButton.handleClick}\n progress={uploadStatus.progress}\n filename={uploadStatus.file?.name || uploadStatus.url}\n />\n )\n }\n\n // Upload needs configuration\n if (state.stagedUpload !== null) {\n return (\n <UploadConfiguration\n stagedUpload={state.stagedUpload}\n pluginConfig={props.config}\n secrets={props.secrets}\n startUpload={startUpload}\n onClose={() => dispatch({action: 'reset'})}\n />\n )\n }\n\n // Default: No staged upload\n let tone: CardTone | undefined\n if (dragState) tone = dragState === 'valid' ? 'positive' : 'critical'\n\n const acceptMimeString = props.config?.acceptedMimeTypes?.length\n ? props.config.acceptedMimeTypes.join(',')\n : 'video/*, audio/*'\n\n return (\n <>\n <UploadCard\n tone={tone}\n onDrop={handleDrop}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDragEnter={handleDragEnter}\n onPaste={handlePaste}\n ref={containerRef}\n >\n {props.asset ? (\n <DialogStateProvider\n dialogState={props.dialogState}\n setDialogState={props.setDialogState}\n >\n <Player\n readOnly={props.readOnly}\n asset={props.asset}\n onChange={props.onChange}\n config={props.config}\n buttons={\n <PlayerActionsMenu\n accept={acceptMimeString}\n asset={props.asset}\n dialogState={props.dialogState}\n setDialogState={props.setDialogState}\n onChange={props.onChange}\n onSelect={handleUpload}\n readOnly={props.readOnly}\n config={props.config}\n />\n }\n />\n </DialogStateProvider>\n ) : (\n <UploadPlaceholder\n accept={acceptMimeString}\n hovering={dragState !== null}\n onSelect={handleUpload}\n readOnly={!!props.readOnly}\n setDialogState={props.setDialogState}\n needsSetup={props.needsSetup}\n config={props.config}\n />\n )}\n </UploadCard>\n {props.dialogState === 'select-video' && (\n <InputBrowser\n config={props.config}\n asset={props.asset}\n onChange={props.onChange}\n setDialogState={props.setDialogState}\n />\n )}\n </>\n )\n}\n","import {Card} from '@sanity/ui'\nimport {memo, Suspense} from 'react'\n\nimport {useAccessControl} from '../hooks/useAccessControl'\nimport {useAssetDocumentValues} from '../hooks/useAssetDocumentValues'\nimport {useClient} from '../hooks/useClient'\nimport {useDialogState} from '../hooks/useDialogState'\nimport {useMuxPolling} from '../hooks/useMuxPolling'\nimport {useSecretsDocumentValues} from '../hooks/useSecretsDocumentValues'\nimport type {MuxInputProps, PluginConfig} from '../util/types'\nimport {ConfigureApiDialog} from './ConfigureApi'\nimport ErrorBoundaryCard from './ErrorBoundaryCard'\nimport {InputFallback} from './Input.styled'\nimport Onboard from './Onboard'\nimport Uploader from './Uploader'\n\nexport interface InputProps extends MuxInputProps {\n config: PluginConfig\n}\nconst Input = (props: InputProps) => {\n const client = useClient()\n const secretDocumentValues = useSecretsDocumentValues()\n const assetDocumentValues = useAssetDocumentValues(props.value?.asset)\n const poll = useMuxPolling(props.readOnly ? undefined : assetDocumentValues?.value || undefined)\n const [dialogState, setDialogState] = useDialogState()\n const {hasConfigAccess} = useAccessControl(props.config)\n\n const error = secretDocumentValues.error || assetDocumentValues.error || poll.error /*||\n // @TODO move errored logic to Uploader, where handleRemoveVideo can be called\n (assetDocumentValues.value?.status === 'errored'\n ? new Error(assetDocumentValues.value.data?.errors?.messages?.join(' '))\n : undefined)\n // */\n if (error) {\n // @TODO deal with it more gracefully\n throw error\n }\n const isLoading = secretDocumentValues.isLoading || assetDocumentValues.isLoading\n\n return (\n <Card>\n <ErrorBoundaryCard schemaType={props.schemaType}>\n <Suspense fallback={<InputFallback />}>\n {isLoading ? (\n <InputFallback />\n ) : (\n <>\n {secretDocumentValues.value.needsSetup && !assetDocumentValues.value ? (\n <Onboard setDialogState={setDialogState} config={props.config} />\n ) : (\n <Uploader\n {...props}\n config={props.config}\n onChange={props.onChange}\n client={client}\n secrets={secretDocumentValues.value.secrets}\n asset={assetDocumentValues.value}\n dialogState={dialogState}\n setDialogState={setDialogState}\n needsSetup={secretDocumentValues.value.needsSetup}\n />\n )}\n\n {dialogState === 'secrets' && hasConfigAccess && (\n <ConfigureApiDialog\n setDialogState={setDialogState}\n secrets={secretDocumentValues.value.secrets}\n />\n )}\n </>\n )}\n </Suspense>\n </ErrorBoundaryCard>\n </Card>\n )\n}\n\nexport default memo(Input)\n","import Input from './components/Input'\nimport VideoThumbnail from './components/VideoThumbnail'\nimport {MuxApiHostProvider} from './context/MuxApiHostContext'\nimport type {MuxInputProps, PluginConfig, VideoAssetDocument} from './util/types'\n\nexport function muxVideoCustomRendering(config: PluginConfig) {\n return {\n components: {\n input: (props: MuxInputProps) => (\n <MuxApiHostProvider muxApiHost={config.muxApiHost}>\n <Input config={{...config, ...props.schemaType.options}} {...props} />\n </MuxApiHostProvider>\n ),\n },\n preview: {\n select: {\n filename: 'asset.filename',\n playbackId: 'asset.playbackId',\n status: 'asset.status',\n assetId: 'asset.assetId',\n thumbTime: 'asset.thumbTime',\n data: 'asset.data',\n },\n prepare: (asset: Partial<VideoAssetDocument>) => {\n const {filename, playbackId, status} = asset\n return {\n title: filename || playbackId || '',\n subtitle: status ? `status: ${status}` : null,\n media: asset.playbackId ? <VideoThumbnail asset={asset} width={64} /> : null,\n }\n },\n },\n }\n}\n","export const muxVideoSchema = {\n name: 'mux.video',\n type: 'object',\n title: 'Video asset reference',\n fields: [\n {\n title: 'Video',\n name: 'asset',\n type: 'reference',\n weak: true,\n to: [{type: 'mux.videoAsset'}],\n },\n ],\n}\n\nconst muxTrack = {\n name: 'mux.track',\n type: 'object',\n fields: [\n {type: 'string', name: 'id'},\n {type: 'string', name: 'type'},\n {type: 'number', name: 'max_width'},\n {type: 'number', name: 'max_frame_rate'},\n {type: 'number', name: 'duration'},\n {type: 'number', name: 'max_height'},\n {type: 'string', name: 'language_code'},\n {type: 'string', name: 'name'},\n {type: 'string', name: 'status'},\n {type: 'string', name: 'text_source'},\n {type: 'string', name: 'text_type'},\n ],\n}\n\nconst muxPlaybackId = {\n name: 'mux.playbackId',\n type: 'object',\n fields: [\n {type: 'string', name: 'id'},\n {type: 'string', name: 'policy'},\n ],\n}\n\nconst muxStaticRenditionFile = {\n name: 'mux.staticRenditionFile',\n type: 'object',\n fields: [\n {type: 'string', name: 'name'},\n {type: 'string', name: 'ext'},\n {type: 'number', name: 'height'},\n {type: 'number', name: 'width'},\n {type: 'number', name: 'bitrate'},\n {type: 'string', name: 'filesize'},\n {type: 'string', name: 'type'},\n {type: 'string', name: 'status'},\n {type: 'string', name: 'resolution_tier'},\n {type: 'string', name: 'resolution'},\n {type: 'string', name: 'id'},\n {type: 'string', name: 'passthrough'},\n ],\n}\n\nconst muxStaticRenditions = {\n name: 'mux.staticRenditions',\n type: 'object',\n fields: [\n {type: 'string', name: 'status'},\n {\n name: 'files',\n type: 'array',\n of: [{type: 'mux.staticRenditionFile'}],\n },\n ],\n}\n\nconst muxMasterFile = {\n name: 'mux.masterFile',\n type: 'object',\n fields: [\n {type: 'string', name: 'status'},\n {type: 'string', name: 'url'},\n ],\n}\n\nconst muxAssetData = {\n name: 'mux.assetData',\n title: 'Mux asset data',\n type: 'object',\n fields: [\n {\n type: 'string',\n name: 'resolution_tier',\n },\n {\n type: 'string',\n name: 'upload_id',\n },\n {\n type: 'string',\n name: 'created_at',\n },\n {\n type: 'string',\n name: 'id',\n },\n {\n type: 'string',\n name: 'status',\n },\n {\n type: 'string',\n name: 'max_stored_resolution',\n },\n {\n type: 'string',\n name: 'passthrough',\n },\n {\n type: 'string',\n name: 'encoding_tier',\n },\n {\n type: 'string',\n name: 'video_quality',\n },\n {\n type: 'string',\n name: 'master_access',\n },\n {\n type: 'string',\n name: 'aspect_ratio',\n },\n {\n type: 'number',\n name: 'duration',\n },\n {\n type: 'number',\n name: 'max_stored_frame_rate',\n },\n {\n type: 'string',\n name: 'mp4_support',\n },\n {\n type: 'string',\n name: 'max_resolution_tier',\n },\n {\n name: 'tracks',\n type: 'array',\n of: [{type: 'mux.track'}],\n },\n {\n name: 'playback_ids',\n type: 'array',\n of: [{type: 'mux.playbackId'}],\n },\n {\n name: 'static_renditions',\n type: 'mux.staticRenditions',\n },\n {\n name: 'master',\n type: 'mux.masterFile',\n },\n ],\n}\n\nconst muxVideoAsset = {\n name: 'mux.videoAsset',\n type: 'document',\n title: 'Video asset',\n fields: [\n {\n type: 'string',\n name: 'status',\n },\n {\n type: 'string',\n name: 'assetId',\n },\n {\n type: 'string',\n name: 'playbackId',\n },\n {\n type: 'string',\n name: 'filename',\n },\n {\n type: 'number',\n name: 'thumbTime',\n },\n {\n type: 'mux.assetData',\n name: 'data',\n },\n ],\n}\n\nexport const schemaTypes = [\n muxTrack,\n muxPlaybackId,\n muxStaticRenditionFile,\n muxStaticRenditions,\n muxMasterFile,\n muxAssetData,\n muxVideoAsset,\n]\n","import '@sanity/ui/styles.css'\nimport {definePlugin} from 'sanity'\n\nimport createStudioTool, {DEFAULT_TOOL_CONFIG} from '../components/StudioTool'\nimport {muxVideoCustomRendering} from '../plugin'\nimport {muxVideoSchema, schemaTypes} from '../schema'\nimport {normalizeMuxApiHost} from '../util/muxAddonClient'\nimport type {PluginConfig, StaticRenditionResolution} from '../util/types'\nexport type {VideoAssetDocument} from '../util/types'\n\nexport const defaultConfig: PluginConfig = {\n static_renditions: [],\n // oxlint-disable-next-line no-deprecated -- kept for backwards-compatible defaults until next major\n mp4_support: 'none',\n video_quality: 'plus',\n max_resolution_tier: '1080p',\n normalize_audio: false,\n defaultPublic: true,\n defaultSigned: false,\n defaultDrm: false,\n tool: DEFAULT_TOOL_CONFIG,\n allowedRolesForConfiguration: [],\n acceptedMimeTypes: ['video/*', 'audio/*'],\n}\n\n/**\n * Converts legacy mp4_support configuration to static_renditions format\n */\nfunction convertLegacyConfig(config: Partial<PluginConfig>): {\n static_renditions: StaticRenditionResolution[]\n} {\n // If static_renditions is already provided, use it\n if (config.static_renditions && config.static_renditions.length > 0) {\n return {static_renditions: config.static_renditions}\n }\n\n // Convert legacy mp4_support to static_renditions\n // oxlint-disable-next-line no-deprecated -- migrate legacy plugin option until next major\n if (config.mp4_support === 'standard') {\n return {static_renditions: ['highest']}\n }\n\n return {static_renditions: []}\n}\n\nexport const muxInput = definePlugin<Partial<PluginConfig> | void>((userConfig) => {\n // TODO: Remove this on next major version when we end support for encoding_tier\n if (typeof userConfig === 'object' && 'encoding_tier' in userConfig) {\n // oxlint-disable-next-line no-deprecated -- migrate legacy plugin option until next major\n const deprecated_encoding_tier = userConfig.encoding_tier\n if (!userConfig.video_quality) {\n if (deprecated_encoding_tier === 'baseline') {\n userConfig.video_quality = 'basic'\n }\n if (deprecated_encoding_tier === 'smart') {\n userConfig.video_quality = 'plus'\n }\n }\n }\n const config: PluginConfig = {\n ...defaultConfig,\n ...userConfig,\n ...convertLegacyConfig(userConfig || {}),\n }\n if (config.muxApiHost !== undefined) {\n // Fail early on an invalid value (including an empty string), instead of on the first Mux request\n config.muxApiHost = normalizeMuxApiHost(config.muxApiHost)\n }\n return {\n name: 'mux-input',\n schema: {\n types: [\n ...schemaTypes,\n {\n ...muxVideoSchema,\n ...muxVideoCustomRendering(config),\n },\n ],\n },\n tools: config.tool === false ? undefined : [createStudioTool(config)],\n }\n})\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,MAAM,oBAAoB,cAAkC,KAAA,CAAS;AAErE,SAAgB,mBAAA,IAMb;eANgC,EACjC,YACA,aAFiCA,IAO1BC;CAAP,OAAuD,EAAA,OAAA,YAAA,EAAA,OAAb,cAAnC,KAAA,oBAACC,kBAAAA,UAAD;EAA4B,OAAO;EAAa;CAAqC,CAAA,GAArC,EAAA,KAAA,UAAb,EAAA,KAAA,oCAAnCD;AACT;AAEA,SAAgB,gBAAgB;CAC9B,OAAO,WAAW,iBAAiB;AACrC;;;;;ACZA,MAAM,iBAAA;eACJG;CAAAA,2DAAC,KAAA,oBAAA,OAAD;EACE,QAAO;EACP,MAAK;EACL,aAAY;EACZ,SAAQ;EACR,QAAO;EACP,OAAM;EACN,OAAM;EAEN,UAAA,oBAAC,QAAD,EAAM,GAAE,iIAAkI,CAAA;CACvI,CAAA,2BAVLA;GCAI,sCAAsC,6CAOtC,4BAA4B,cAAqD;CACrF,iBAAiB;CACjB,oCACS;AAEX,CAAC,GAOY,qCAAA,OAGiC;eAHI,EAChD,QACA,aAFgDE,IAI1C,kBAAkB,QAAQ,6BAA6B,IAE3DC;yCAAmB,KAAA,mBAAA,OAAO,aAAa,QAAQ,mCAAmC,MAAM,QAAxF,EAAA,KAAA;CACF,IAAM,CAAC,2BAA2B,gCAAgC,SAASe,EAAS,GAE7Cd;qDAAC,MAAA,MAAe;EAErD,AADA,OAAO,aAAa,QAAQ,qCAAqC,EAAE,SAAS,CAAC,GAC7E,6BAA6B,CAAC;CAChC;CAHA,IAAM,qBAAqBC,IAMlBC;CACY,AAAA,EAAA,OAAA,yCADZ,KAAA;EACL,iBAAiB;EACjB,8BAA8B;CAChC,GAFmB,EAAA,KAAA;CAFrB,IAAM,QAAQC,IASZC;CADF,OAEK,EAAA,OAAA,YAAA,EAAA,OADwC,SAA3C,KAAA,oBAACC,0BAAAA,UAAD;EAA2C;EACxC;CACiC,CAAA,GADjC,EAAA,KAAA,UADwC,EAAA,KAAA,+BAA3CD;AAIJ,GAEa,qCACK,WAAW,yBACpB,GAGI,oBAAA,OAAyD;gBAArC,EAAC,YAADE,IACzB,EAAC,iCAAgC,6BAA6B,GACnDC;CAEf,AAAA,EAAA,OAAA,WAAA,EAAA,OADA,gCADe,WAAM;EAErB,AADA,6BAA6B,EAAI,GACjC,QAAQ;CACV,GADE,EAAA,KAAA,SADA,EAAA,KAAA;CADF,IAAM,WAAWA,IAWXC;CAC+C,AAAA,EAAA,OAAA,wBAD/C,KAAA,oBAAC,OAAD;EAAO,SAAS;EACd,UAAA,oBAAC,QAAD;GAAQ,MAAK;GAAQ,MAAK;GAAU,SAAS;GAAU,MAAK;EAAM,CAAA;CAC7D,CAAA,GADwC,EAAA,KAAA;CAKhCC,IAAAA;;EAAC;EAAG;EAAG;CAAC;CAAvBC,IAAAA;qDAAC,KAAA,oBAAA,MAAD;EAAM,SAASD;EAAW,QAAQ;EAChC,UAAA,oBAAC,OAAD;GAAO,KAAK;GACV,UAAA,oBAAC,MAAD;IAAM,MAAM;IAAG,QAAO;IACpB,UAAA;GAEI,CAAA;EACD,CAAA;CACH,CAAA;CACSA,IAAAA;;EAAC;EAAG;EAAG;CAAC;CATzBE,IAAAA;qDAAC,KAAA,qBAAA,OAAD;EAAO,KAAK;EAAG,SAAS;EAAxB,UAAA,CACED,IAQA,oBAAC,MAAD;GAAM,SAASD;GAAW,QAAQ;GAAG,MAAK;GACxC,UAAA,oBAAC,OAAD;IAAO,KAAK;IACV,UAAA,oBAAC,MAAD;KAAM,MAAM;KAAG,QAAO;KACpB,UAAA;IAEI,CAAA;GACD,CAAA;EACH,CAAA,CACD;;CA5BTG,IAAAA;CADF,OAIa,EAAA,OAAA,YAAA,EAAA,QAGPJ,MANJ,KAAA,oBAAC,QAAD;EACE,MAAA;EACA,IAAG;EACH,SAAS;EACT,QAAO;EACP,QACEA;EAKFG,UAAAA;CAkBM,CAAA,GA1BG,EAAA,KAAA,UAGPH,EAAAA,MAAAA,8BANJI;AA+BJ,GC1FM,kCAAkB,IAAI,QAAoC;;;;;AAMhE,SAAgB,oBAAoB,YAA4B;CAC9D,IAAI;CACJ,IAAI;EACF,MAAM,IAAI,IAAI,UAAU;CAC1B,QAAQ;EACN,MAAU,MACR,yGAAyG,WAAW,EACtH;CACF;CACA,IAAI,IAAI,aAAa,WAAW,IAAI,aAAa,UAC/C,MAAU,MACR,0EAA0E,WAAW,EACvF;CAEF,IAAK,IAAI,YAAY,IAAI,aAAa,OAAQ,IAAI,UAAU,IAAI,MAC9D,MAAU,MACR,wIAAwI,WAAW,EACrJ;CAEF,OAAO,IAAI;AACb;;;;;;;;AASA,SAAS,qBAAqB,QAAsB,YAAkC;CACpF,OAAO,OAAO,WAAW;EACvB,SAAS,oBAAoB,UAAU;EAEvC,oBAAoB;EACpB,QAAQ;CACV,CAAC;AACH;;;;;AAMA,SAAgB,eAAe,QAAsB,YAAkC;CACrF,IAAM,eAAe,OAAO,WAAW,CAAC,CAAC;CAEzC,OADA,gBAAgB,IAAI,cAAc,qBAAqB,QAAQ,UAAU,CAAC,GACnE;AACT;;;;;AAMA,SAAgB,kBAAkB,QAAoC;CACpE,OAAO,gBAAgB,IAAI,MAAM,KAAK;AACxC;AC3DA,MAAa,qBAAqB;AAElC,SAAgBM,cAAY;eACKH;qDAAC,KAAA,EAAA,YAAY,mBAAkB;CAA9D,IAAM,SAASK,UAAgBL,EAAgC,GACzD,aAAa,cAAc,GAIxBC;CADT,OACqC,EAAA,OAAA,UAAA,EAAA,OAA5B,cAAa,KAAA,aAAA,eAAe,QAAQ,UAAU,IAAI,QAAtB,EAAA,KAAA,QAA5B,EAAA,KAAA,oCADFC;AAIT;ACdA,MAAM,gBAAgB,yCAChB,mBAAmB;AAEzB,SAAS,SAAS,QAA0B;CAC1C,QAAQ,OAAO,MAAM,aAAa,KAAK,CAAC,EAAA,CAAG,KAAK,UAAU,MAAM,QAAQ,kBAAkB,EAAE,CAAC;AAC/F;AAEA,SAAS,aAAa,OAAyC;CAE7D,OAAO,MAAM,QAAQ,KAAK,MAAM,OAC9B,IAAI,IAAI,OAAO,IAAI,KAAK,IACjB,MACN,CAAA,CAAM;AACX;;;;;;;;;;;;AAaA,SAAS,sBAAsB,OAAyB;CACtD,IAAM,gBAAgB,CAAC,GACjB,gBAAgB,MAAM,QAAQ,eAAe,UAC7C,MAAM,KAAK,CAAC,CAAC,SAAS,KACxB,cAAc,KAAK,KAAK,GACjB,MAEF,KACR,GAGK,cAAc,cAAc,KAAK,QAAQ,KAAK,QAAQ,GAAG,CAAC,CAAC,GAO3D,iBAAiB,KAAK,QAAQ,SAAS,QAAQ,aAAa,CAAC,CAAC,CAAC;CAErE,OAAO,CAAC,GAAG,aAAa,GAAG,cAAc;AAC3C;;;;;AAMA,SAAS,kBAAkB,OAAiB,gBAAyB;CACnE,IAAM,cAAc,iBAAiB,CAAC,YAAY,SAAS,IAAI,CAAC,UAAU;CAK1E,OAJoB,MACjB,KAAK,OAAO,MAAM,YAAY,KAAK,eAAe,GAAG,WAAW,WAAW,GAAG,CAAC,CAAC,CAChF,QAAQ,eAAe,WAAW,SAAS,CAEvC,CAAA,CAAY,KAAK,eAAe,IAAI,WAAW,KAAK,MAAM,EAAE,EAAE;AACvE;AAEA,SAAgB,mBAAmB,OAAe;CAChD,IAAM,QAAQ,sBAAsB,KAAK;CAEzC,OAAO;EACL,QAAQ,kBAAkB,OAAO,MAAM,UAAU,CAAC;EAClD,QAAQ,EACN,GAAG,aAAa,KAAK,EACvB;CACF;AACF;AC/DA,MAAa,qBAAqB;CAChC,aAAa;EAAC,MAAM;EAAmB,OAAO;CAAc;CAC5D,YAAY;EAAC,MAAM;EAAkB,OAAO;CAAwB;CACpE,aAAa;EAAC,MAAM;EAAgB,OAAO;CAAmB;CAC9D,cAAc;EAAC,MAAM;EAAiB,OAAO;CAAmB;AAClE,GAIM,oBAAoB,iCAOvB,EAAC,eAAe,MAAM,kBAAiB;CACxC,IAAM,SAAS,mBAAmB,WAAW,GACvC,SAAS,CAAC,+BAA6B,GAAG,OAAO,MAAM,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,MAAM,GAEpF,eAAe,mBAAmB,KAAK,CAAC;CAC9C,OAAO,cAAc,YACR,KAAK,OAAO,YAAY,aAAa,IAChD,OAAO,QACP,EACE,YAAY,mBACd,CACF;AACF,CAAC;AAED,SAAwB,YAAY;gBAC5B,gBAAgB,iBAAiB,GACjC,CAAC,MAAM,WAAW,SAAqB,aAAa,GACpD,CAAC,aAAa,kBAAkB,SAAS,EAAE,GAGhCI;CAAC,AAAA,EAAA,OAAA,iBAAA,EAAA,OAAqB,eAAA,EAAA,OAAN,QAAhB,KAAA;EAAC;EAAe;EAAM;CAAW,GAAhC,EAAA,KAAA,eAAqB,EAAA,KAAA,aAAN,EAAA,KAAA;CADjC,IAAM,CAACC,IAAqB,aAAa,kBACvCC,EACF,GAFOD;4BAAiB,KAAA,OAAA,KAAA,IAAA,CAAC,IAAlBA;0BAOHE;CAA4B,AAAA,EAAA,OAAA,8BAA5B,KAAA,QAA4B,cAAc,CAAC,CAAC,IAC1CC,QAKF,GAN4B,EAAA,KAAA;CAHhC,IAAM,SAASC,IAaRC;CAAP,OACE,EAAA,OAAA,UAAA,EAAA,OACA,aAAA,EAAA,QAEA,eAAA,EAAA,QADA,QAHK,KAAA;EACL;EACA;EACA;EACA;EACA;EACA;CACF,GANE,EAAA,KAAA,QACA,EAAA,KAAA,WAEA,EAAA,MAAA,aADA,EAAA,MAAA,gCAHKA;AAQT;AAjBQ,SAAAE,SAAC,UAAA;CACE,OAAA;EACC,GAAI,SAAS,SAAS,SAAS;EAC/B,KAAK,SAAS;CAChB;;AC/CV,SAAgB,iBAAiB;CAC/B,OAAO,SAAsB,EAAK;AACpC;ACXA,MCDa,uBAAuB,EAClC,eAAe,QACjB;ACYA,SAAgB,YACd,QACA,OACA,WACA,kBACA,cACA,mBACA,aAC0B;CAC1B,IAAM,MAAuB;EAC3B,KAAK;EACL,OAAO;EACP;EACA;EACA;EACA;EACA;EACA;CACF;CAIA,OAHA,IAAI,eAAe,mBAAmB,eAAe,IACrD,IAAI,oBAAoB,mBAAmB,oBAAoB,IAExD,OAAO,gBAAgB,GAAG;AACnC;AAEA,eAAsB,kBAAkB,QAAsB;CAC5D,IAAI;EACF,IAAM,EAAC,YAAW,OAAO,OAAO;EAShC,OAAO,MARW,kBAAkB,MAAM,CAAC,CAAC,QAEzC;GACD,KAAK,4BAA4B;GACjC,iBAAiB;GACjB,QAAQ;GACR,OAAO;EACT,CAAC;CAEH,SAAS,OAAY;EACnB,QAAQ,MAAM,+BAA+B,KAAK;EAClD,IAAM,UACJ,MAAM,UAAU,eAAe,MAC3B,6GACA,MAAM;EACZ,MAAU,MAAM,SAAS,EAAC,OAAO,MAAK,CAAC;CACzC;AACF;AAEA,SAAgB,YAAY,QAAsB;CAChD,IAAM,EAAC,YAAW,OAAO,OAAO;CAChC,OAAO,kBAAkB,MAAM,CAAC,CAAC,QAA2B;EAC1D,KAAK,uBAAuB,QAAQ;EACpC,iBAAiB;EACjB,QAAQ;EACR,OAAO;CACT,CAAC;AACH;AAEA,eAAsB,qBACpB,QACA,cACA,mBACA;CACA,IAAI,EAAE,gBAAgB,oBACpB,OAAO;CAGT,IAAM,EAAC,YAAW,OAAO,OAAO;CAChC,IAAI;EACF,IAAM,MAAM,MAAM,kBAAkB,MAAM,CAAC,CAAC,QAAkD;GAC5F,KAAK,4BAA4B,QAAQ,GAAG;GAC5C,iBAAiB;GACjB,QAAQ;GACR,OAAO;EACT,CAAC;EAID,OAAO,CAAC,EAAE,IAAI,QAAQ,IAAI,KAAK;CACjC,SAAS,GAAG;EAEV,OADA,QAAQ,MAAM,+BAA+B,cAAc,4BAA4B,CAAC,GACjF;CACT;AACF;AAEA,SAAgB,sBAAsB,QAAsB;CAC1D,IAAM,EAAC,YAAW,OAAO,OAAO;CAChC,OAAO,YACL,kBAAkB,MAAM,CAAC,CAAC,WAAW,QAA2B;EAC9D,KAAK,uBAAuB,QAAQ;EACpC,iBAAiB;EACjB,QAAQ;EACR,OAAO;CACT,CAAC,CACH;AACF;ACxGA,MAAa,kBAAkB,QAAsB,YAC5C,YACL,OAAO,EACL,OACA,WACA,kBACA,kBAIsB;CACtB,IAAI,EAAC,cAAc,sBAAqB;CAExC,IAAI;EAWF,IAVA,MAAM,YACJ,QACA,OACA,WACA,kBACA,cACA,mBACA,WACF,GAEI,EAAC,MADe,YAAY,MAAM,EAAA,EAC1B,UAAU,SAAS,WAE7B,MAAU,MAAM,iBAAiB;CAErC,SAAS,KAAK;EAEZ,MADA,QAAQ,MAAM,uCAAuC,GAAG,GAClD;CACR;CAEA,IAAI,oBAOE,CAAC,MAN6B,qBAChC,QACA,cACA,iBACF,GAGE,IAAI;EACF,IAAM,EAAC,SAAQ,MAAM,kBAAkB,MAAM;EAG7C,AAFA,eAAe,KAAK,IACpB,oBAAoB,KAAK,aACzB,MAAM,YACJ,QACA,OACA,WACA,kBACA,cACA,mBACA,eAAe,EACjB;CACF,SAAS,KAAU;EAGjB,MADA,QAAQ,IAAI,gDAAgD,KAAK,OAAO,GAClE;CACR;CAGJ,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;CACF;AACF,GACA,CAAC,QAAQ,OAAO,CAClB,GC7EW,OAAO,aAGP,UAAU,2BAIV,kBAAkB,KAMlB,yBAAyB,KAAK,GCPrCa,SAAO;CACX;CACA;CACA;CACA;CACA;CACA;AACF,GACa,iCAAiC;gBACtC,EAAC,OAAO,WAAW,UAAS,kBAChC,eACAA,MACF,GAEQ,SAAS,EAAQ,OAEd,KAAA,OAAO,SAAS,MACZ,KAAA,OAAO,aAAa,MACb,KAAA,OAAO,oBAAoB,IAC/B,KAAA,OAAO,gBAAgB,MAClB,KAAA,OAAO,qBAAqB,MAClC,KAAA,OAAO,eAAe,MANZZ;CAChBC,AAAAA,EAAAA,OAAAA,MAAAA,EAAAA,OACIC,MAAAA,EAAAA,OACOC,MAAAA,EAAAA,OACJC,MAAAA,EAAAA,OACKC,MAAAA,EAAAA,OACNC,MANU,KAAA;EACvB,OAAOL;EACP,WAAWC;EACX,kBAAkBC;EAClB,cAAcC;EACd,mBAAmBC;EACnB,aAAaC;CACf,GANSL,EAAAA,KAAAA,IACIC,EAAAA,KAAAA,IACOC,EAAAA,KAAAA,IACJC,EAAAA,KAAAA,IACKC,EAAAA,KAAAA,IACNC,EAAAA,KAAAA;CANf,IAAM,UAAmBN,IASP,KAAA,CAAC,QACL,KAAA,CAAC,SAAS,SAAS,CAAC,SAAS,WAFpCO;CAGL,AAAA,EAAA,OAAA,WAAA,EAAA,OAFgBC,MAAAA,EAAAA,OACJC,MAFP,KAAA;EACL,gBAAgBD;EAChB,YAAYC;EACZ;CACF,GADE,EAAA,KAAA,SAFgBD,EAAAA,KAAAA,IACJC,EAAAA,KAAAA;CAZhB,IAAM,QAAQC,IAiBPC;CAAP,OAAiC,EAAA,QAAA,SAAA,EAAA,QAAzB,SAAA,EAAA,QAAO,aAAR,MAAA;EAAC;EAAO;EAAW,OAAO;CAAK,GAAL,EAAA,MAAA,OAAzB,EAAA,MAAA,OAAO,EAAA,MAAA,uCAARA;AACT;AClBA,SAAS,KAAK,EAAC,OAAO,WAAW,kBAAkB,eAA8B;CAC/E,OAAO;EACL,YAAY;EACZ,OAAO;EAGP,OAAO,SAAS;EAChB,WAAW,aAAa;EACxB,kBAAkB,oBAAoB;EACtC,aAAa,eAAe;CAC9B;AACF;AACA,SAAS,QAAQ,OAAc,QAAgB;CAC7C,QAAQ,QAAQ,MAAhB;EACE,KAAK,UACH,OAAO;GAAC,GAAG;GAAO,YAAY;GAAM,OAAO;EAAI;EACjD,KAAK,SACH,OAAO;GAAC,GAAG;GAAO,YAAY;GAAO,OAAO,OAAO;EAAO;EAC5D,KAAK,SACH,OAAO,KAAK,OAAO,OAAO;EAC5B,KAAK,UACH,OAAO;GAAC,GAAG;IAAQ,OAAO,QAAQ,OAAO,OAAO,QAAQ;EAAK;EAC/D,SACE,MAAU,MAAM,wBAAyB,QAA8B,MAAM;CACjF;AACF;AAEA,MAAa,uBAAuB,YAAqB,WAAW,SAAS,SAAS,IAAI,GClC7E,MAAM;AAEnB,SAAgB,YAAY,QAA+B;CACzD,IAAM,EAAC,WAAW,YAAW,OAAO,OAAO;CAC3C,OAAO,QAAQ,YAAY;EACzB,IAAM,OAAO,MAAM,OAAO,MACb,sKAQX,EAAC,IAAG,CACN;EACA,OAAO;GACL,OAAO,MAAM,SAAS;GACtB,WAAW,MAAM,aAAa;GAC9B,kBAAkB,EAAQ,MAAM,oBAAqB;GACrD,cAAc,MAAM,gBAAgB;GACpC,mBAAmB,MAAM,qBAAqB;GAC9C,aAAa,MAAM,eAAe;EACpC;CACF,GAAG;EAAC;EAAS;EAAK;EAAW;CAAO,CAAC;AACvC;AC/BA,SAAwB,QAAA,IAA8B;gBAAtB,EAAC,QAAA,OAADG,IAAC,SAAA,OAAA,KAAA,IAAS,KAATC,IACzB,KAAK,MAAM,GAEX,YADQ,YACI,CAAA,CAAM,MAAM,QAAQ,UAAU,SAC1C,UAAU,GAAiB,GAAG,SAEHC;qDAC/B,KAAA,EAAA,UAAU,UACZ;CAFA,IAAM,YAA2BA,IAOb,KAAA,GAAG,OAAO,KAAnBC;CAASC,AAAAA,EAAAA,OAAAA,kBAAT,KAAA,EAAC,QAAQA,GAAa,GAAbA,EAAAA,KAAAA;CAOdC,IAAAA,IAIAC,IAIAC;qDARA,KAAA,oBAAC,QAAD;EACE,GAAE;EACF,OAAO;CACR,CAAA,GACD,KAAA,oBAAC,QAAD;EACE,GAAE;EACF,OAAO;CACR,CAAA,GACD,KAAA,oBAAC,QAAD;EACE,GAAE;EACF,OAAO;CACR,CAAA;CAZHC,IAAAA;CAAsB,AAAA,EAAA,OAAA,yBAAtB,KAAA,qBAAC,KAAD;EAAG,IAAG;EAAU,MAAM;EAAtB,UAAA;GACEH;GAIAC;GAIAC;EAIC;KAbmB,EAAA,KAAA;CARxBE,IAAAA;CADF,OAGWN,EAAAA,OAAAA,MAAAA,EAAAA,OAMPK,MAAAA,EAAAA,QAPiB,WADnB,KAAA,oBAAC,OAAD;EACE,mBAAiB;EACjB,OAAOL;EACP,SAAQ;EACR,SAAQ;EACR,OAAM;EACN,UAAS;EAETK,UAAAA;CAcG,CAAA,GApBIL,EAAAA,KAAAA,IAMPK,EAAAA,KAAAA,IAPiB,EAAA,MAAA,mCADnBC;AAwBJ;ACrCA,MAAM,OAAO,OAAO,KAAA,WAAA;;;AAAI,CAAA,CAAA,yFAOX,eAAA;eACXE;CAAAA,2DACE,KAAA,qBAAAE,UAAA,EAAA,UAAA,CAAA,oBAAC,MAAD,EAAA,UACE,oBAAC,SAAD,EAAS,QAAQ,GAAK,CAAA,EAClB,CAAA,GACN,iBACA,EAAA,CAAA,2BALFF;;ACAF,SAASS,YAAU,OAAc;gBACzB,EAAC,UAAU,OAAO,aAAa,YAAW,OAQnCN;+BAAS,KAAA,SAAA,oBAAC,MAAD,EAAA,UAAI,WAAY,CAAA,GAAzB,EAAA,KAAA;CADHC,IAAAA;CAA0B,AAAA,EAAA,OAAA,WAAA,EAAA,OACvBD,MADH,KAAA,oBAAC,MAAD;EAAM,IAAG;EAAQ,SAAS;EAAS,QAAO;EAAW,MAAM;EACxDA,UAAAA;CACG,CAAA,GAFoB,EAAA,KAAA,SACvBA,EAAAA,KAAAA;CAGFE,IAAAA;qCACC,KAAA,eAAA,oBAAC,MAAD;EAAM,OAAA;EAAM,MAAM;EACf,UAAA;CACG,CAAA,GAHP,EAAA,KAAA;CAPPC,IAAAA;CAGMF,AAAAA,EAAAA,OAAAA,MAAAA,EAAAA,OAICC,MAPP,KAAA,oBAAC,MAAD;EAAM,OAAM;EACV,UAAA,oBAAC,KAAD;GAAK,MAAM;GAAG,UAAU;GACtB,UAAA,qBAAC,OAAD;IAAO,KAAK;IAAZ,UAAA,CACED,IAICC,EAKI;;EACJ,CAAA;CACD,CAAA,GAXAD,EAAAA,KAAAA,IAICC,EAAAA,KAAAA;CAQPE,IAAAA;CAAM,AAAA,EAAA,QAAA,yBAAN,KAAA,oBAAC,OAAD,EAAM,SAAc,CAAA,GAAd,EAAA,MAAA;CAhBRC,IAAAA;CADF,OAEIF,EAAAA,QAAAA,MAAAA,EAAAA,QAeAC,MAhBF,KAAA,qBAAC,OAAD;EAAO,KAAK;EAAZ,UAAA,CACED,IAeAC,EACK;KAhBLD,EAAAA,MAAAA,IAeAC,EAAAA,MAAAA,8BAhBFC;AAmBJ;AAEA,IAAA,oBAAe,KAAKC,WAAS;ACN7B,MAAM,aAAa;CAAC;CAAS;CAAa;CAAoB;AAAa;AAG3E,SAAgB,mBAAA,IAAuE;gBAApD,EAAC,SAAS,mBAAVE,IAC3B,SAASyD,YAAU,GACnB,CAAC,OAAO,YAAY,oBAAoB,OAAO,GAC/C,sBAAoC,QAAQ,SAAS,QAAQ,WACnCxD;CAAM,AAAA,EAAA,OAAA,8BAAN,WAAM,eAAe,EAAK,GAApB,EAAA,KAAA;CAAtC,IAAM,cAAcC,IACd,QAEF,QAAQ,UAAU,MAAM,SACxB,QAAQ,cAAc,MAAM,aAC5B,QAAQ,qBAAqB,MAAM,oBACnC,QAAQ,gBAAgB,MAAM,aAG5B,KAAK,eAAe,MAAM,KAExBC;CAA6B,AAAA,EAAA,OAAA,kBAA7B,KAAA,WAAW,KAAK,UAAU,GAAG,GAAG,GAAG,OAAO,GAAb,EAAA,KAAA;CADrC,IAAM,CAAC,SAAS,aAAa,oBAAoB,iBACzCA,IAGF,aAAa,OAAyB,IAAI,GAC1C,oBAAoB,eAAe,QAAQ,OAAO,GAClD,SAAS,OAAO,EAAK,GAGzBC;CASqC,AAAA,EAAA,OAAA,UAAA,EAAA,OAJjC,YAAA,EAAA,OAEA,qBAAA,EAAA,OAKI,kBAAA,EAAA,OANsD,SAN9D,MAAC,UAAwC;EAGvC,IAFA,MAAM,eAAe,GAEjB,CAAC,OAAO,WAAW,MAAM,cAAc,eAAe,GAAG;GAE3D,AADA,OAAO,UAAU,IACjB,SAAS,EAAC,MAAM,SAAQ,CAAC;GACzB,IAAM,EAAC,OAAO,WAAW,kBAAkB,gBAAe;GAC1D,kBAAkB;IAAC;IAAO;IAAW;IAAkB;GAAW,CAAC,CAAC,CACjE,MAAM,iBAAiB;IACtB,IAAM,EAAC,WAAW,YAAW,OAAO,OAAO;IAG3C,AAFA,MAAM;KAAC;KAASsD;KAAW;KAAW;IAAO,CAAC,GAC9C,cAAc,QAAQ,QAAQ,YAAY,GAAG;KAAC;KAASA;KAAW;KAAW;IAAO,CAAC,GACrF,eAAe,EAAK;GACtB,CAAC,CAAC,CACD,OAAO,QAAQ,SAAS;IAAC,MAAM;IAAS,SAAS,IAAI;GAAO,CAAC,CAAC,CAAC,CAC/D,cAAc;IACb,OAAO,UAAU;GACnB,CAAC;EACL;CACF,GAVqC,EAAA,KAAA,QAJjC,EAAA,KAAA,UAEA,EAAA,KAAA,mBAKI,EAAA,KAAA,gBANsD,EAAA,KAAA;CAPhE,IAAM,eAAerD,IAwBnBC;CACE,AAAA,EAAA,QAAA,yBADF,MAAC,YAAyC;EACxC,SAAS;GACP,MAAM;GACN,SAAS;IAAC,MAAM;IAAS,OAAOC,QAAM,cAAc;GAAK;EAC3D,CAAC;CACH,GAJE,EAAA,MAAA;CAFJ,IAAM,oBAAoBC,IAUxBC;CACE,AAAA,EAAA,QAAA,yBADF,MAAC,YAAyC;EACxC,SAAS;GACP,MAAM;GACN,SAAS;IAAC,MAAM;IAAa,OAAOF,QAAM,cAAc;GAAK;EAC/D,CAAC;CACH,GAJE,EAAA,MAAA;CAFJ,IAAM,wBAAwBG,IAU5BC;CACE,AAAA,EAAA,QAAA,yBADF,MAAC,YAAyC;EACxC,SAAS;GACP,MAAM;GACN,SAAS;IAAC,MAAM;IAAoB,OAAOJ,QAAM,cAAc;GAAO;EACxE,CAAC;CACH,GAJE,EAAA,MAAA;CAFJ,IAAM,+BAA+BK,IAUnCC;CACE,AAAA,EAAA,QAAA,yBADF,MAAC,YAAyC;EACxC,SAAS;GACP,MAAM;GACN,SAAS;IAAC,MAAM;IAAe,OAAON,QAAM,cAAc;GAAK;EACjE,CAAC;CACH,GAJE,EAAA,MAAA;CAFJ,IAAM,0BAA0BO,IAUtBC,IAIPC;CAJH,qDAAU,WAAM;EACd,AAAI,WAAW,WACb,WAAW,QAAQ,MAAM;CAE7B,GAAG,KAAA,CAAC,UAAU,uDAJd,UAAUD,IAIPC,EAAY;CAQHC,IAAAA;sDAAC,MAAA,oBAAA,QAAD,CAAS,CAAA;CAQVC,IAAAA;CAAC,AAAA,EAAA,QAAA,qCAAD,MAAA,CAAC,uBACA,oBAAC,MAAD;EAAM,SAAS;GAAC;GAAG;GAAG;EAAC;EAAG,QAAQ;EAAG,QAAQ;EAAG,MAAK;EACnD,UAAA,qBAAC,OAAD;GAAO,KAAK;GAAZ,UAAA,CACE,qBAAC,MAAD;IAAM,MAAM;IAAZ,UAAA;KACE;KAAyC;KACzC,oBAAC,KAAD;MACE,MAAK;MACL,QAAO;MACP,KAAI;MAEJ,UAAA;KACC,CAAA;KACH;IACI;GACN,CAAA,GAAA,qBAAC,MAAD;IAAM,MAAM;IAAZ,UAAA;KACE;KAAoC,oBAAC,UAAD,EAAA,UAAQ,aAAkB,CAAA;KAC9D;KAAkB,oBAAC,UAAD,EAAA,UAAQ,WAAgB,CAAA;KAAC;KAC3C,oBAAC,MAAD,CAAK,CAAA;KACL;KACA,oBAAC,MAAD,CAAK,CAAA;KACL;IAEI;GACD,CAAA,CAAA;;CACH,CAAA,GAxBN,EAAA,MAAA;CAgCS,IAAA,MAAA,MAAM,SAAS,IACZ,MAAA,CAAC,CAAC,MAAM,aAAa,MAAM,kBANvCC;CAGY,AAAA,EAAA,QAAA,qBAAA,EAAA,QAEHC,OAAAA,EAAAA,QACGC,OAAAA,EAAAA,QALN,WADN,MAAA,oBAAC,WAAD;EACE,IAAI;EACJ,KAAK;EACL,UAAU;EACV,MAAK;EACL,OAAOD;EACP,UAAUC;CACX,CAAA,GAJW,EAAA,MAAA,mBAEHD,EAAAA,MAAAA,KACGC,EAAAA,MAAAA,KALN,EAAA,MAAA;CAFRC,IAAAA;CACEH,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QADuC,WAAzC,MAAA,oBAACwC,mBAAD;EAAW,OAAM;EAAe,SAAS;EACvCxC,UAAAA;CAQS,CAAA,GARTA,EAAAA,MAAAA,KADuC,EAAA,MAAA;CAe9B,IAAA,MAAA,MAAM,aAAa,IAChB,MAAA,CAAC,CAAC,MAAM,SAAS,MAAM,kBALnCI;CAEY,AAAA,EAAA,QAAA,yBAAA,EAAA,QADN,eAAA,EAAA,QAGGC,OAAAA,EAAAA,QACGC,OALZ,MAAA,oBAAC,WAAD;EACE,IAAI;EACJ,UAAU;EACV,MAAK;EACL,OAAOD;EACP,UAAUC;CACX,CAAA,GAJW,EAAA,MAAA,uBADN,EAAA,MAAA,aAGGD,EAAAA,MAAAA,KACGC,EAAAA,MAAAA;CANdC,IAAAA;CAAuC,AAAA,EAAA,QAAA,eAAA,EAAA,QACrCH,OADF,MAAA,oBAACoC,mBAAD;EAAW,OAAM;EAAa,SAAS;EACrCpC,UAAAA;CAOS,CAAA,GAR4B,EAAA,MAAA,aACrCA,EAAAA,MAAAA;CAeWI,IAAAA;sDAAC,MAAA,EAAA,SAAS,QAAO;CAJ1BC,IAAAA;CACM,AAAA,EAAA,QAAA,sBAAA,EAAA,QACM,gCAAA,EAAA,QACKC,MAAAA,oBAHjB,MAAA,oBAAC,UAAD;EACE,IAAI;EACJ,UAAU;EACV,SAAS,MAAM;EACf,OAAOF;CACR,CAAA,GAJK,EAAA,MAAA,oBACM,EAAA,MAAA,8BACKE,EAAAA,MAAAA,MAAAA;CAGjBC,IAAAA;CAEoB,AAAA,EAAA,QAAA,oCAFpB,MAAA,oBAAC,KAAD;EAAK,MAAM;EAAG,aAAa;EACzB,UAAA,oBAAC,MAAD,EAAA,UACE,oBAAC,SAAD;GAAO,SAAS;GAAoB,UAAA;EAAyB,CAAA,EACzD,CAAA;CACH,CAAA,GAFe,EAAA,MAAA;CATtBC,IAAAA;CACEH,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAMAE,OAPF,MAAA,qBAAC,MAAD;EAAM,OAAM;EAAZ,UAAA,CACEF,KAMAE,GAKI;KAXJF,EAAAA,MAAAA,KAMAE,EAAAA,MAAAA;CAMDE,IAAAA;CAAQC,AAAAA,EAAAA,QAAAA,QAAAA,gBAAAA,EAAAA,QAAsBJ,MAAAA,oBAA9B,MAAA,QAAQ,gBAAgB,MAAM,mBAC7B,oBAAC,MAAD;EAAM,SAAS;GAAC;GAAG;GAAG;EAAC;EAAG,QAAQ;EAAG,QAAQ;EAAG,MAAK;EACnD,UAAA,qBAAC,OAAD;GAAO,KAAK;GAAZ,UAAA;IACE,oBAAC,MAAD;KAAM,MAAM;KAAG,UAAA;IAAiD,CAAA;IAChE,oBAAC,MAAD;KAAM,MAAM;KAAI,UAAA,QAAQ;IAAmB,CAAA;IAC3C,qBAAC,MAAD;KAAM,MAAM;KAAZ,UAAA;MACE;MACA,oBAAC,MAAD,CAAK,CAAA;MACL;KACI;;GACD;;CACH,CAAA,IACJ,MAZKI,EAAAA,MAAAA,QAAAA,cAAsBJ,EAAAA,MAAAA,MAAAA;CAdjCK,IAAAA;CACEH,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAaCC,OAdH,MAAA,qBAAC,OAAD;EAAO,KAAK;EAAZ,UAAA,CACED,KAaCC,GAaI;KA1BLD,EAAAA,MAAAA,KAaCC,EAAAA,MAAAA;CAoBQ,IAAA,MAAA,MAAM,eAAe,IAJ9BG;CACM,AAAA,EAAA,QAAA,iBAAA,EAAA,QACM,2BAAA,EAAA,QAEHC,OAJT,MAAA,oBAAC,WAAD;EACE,IAAI;EACJ,UAAU;EACV,MAAK;EACL,OAAOA;EACP,UAAU;CACX,CAAA,GALK,EAAA,MAAA,eACM,EAAA,MAAA,yBAEHA,EAAAA,MAAAA;CALXC,IAAAA;CAAiD,AAAA,EAAA,QAAA,iBAAA,EAAA,QAC/CF,OADF,MAAA,oBAACwB,mBAAD;EAAW,OAAM;EAAuB,SAAS;EAC/CxB,UAAAA;CAOS,CAAA,GARsC,EAAA,MAAA,eAC/CA,EAAAA,MAAAA;CAQaG,IAAAA;;EAAC;EAAG;EAAG;CAAC;CAEnBC,IAAAA;sDAAC,MAAA,qBAAA,MAAD;EAAM,MAAM;EAAZ,UAAA;GACE;GAC0E;GAC1E,oBAAC,KAAD;IACE,MAAK;IACL,QAAO;IACP,KAAI;IAEJ,UAAA;GACC,CAAA;GACH;EACI;;CAbVC,IAAAA;sDAAC,MAAA,oBAAA,MAAD;EAAM,SAASF;EAAW,QAAQ;EAAG,QAAQ;EAAG,MAAK;EACnD,UAAA,qBAAC,OAAD;GAAO,KAAK;GAAZ,UAAA,CACEC,KAYA,qBAAC,MAAD;IAAM,MAAM;IAAZ,UAAA;KACE,oBAAC,KAAD;MACE,MAAK;MACL,QAAO;MACP,KAAI;MAEJ,UAAA;KACC,CAAA;KAAE;KACL;IACI;GACD,CAAA,CAAA;;CACH,CAAA;CAKQ,IAAA,MAAA,CAAC,OAFbE;CAGiBC,AAAAA,EAAAA,QAAAA,MAAAA,cAAAA,EAAAA,QADLC,OAFZ,MAAA,oBAAC,QAAD;EACE,MAAK;EACL,UAAUA;EACV,SAAS,MAAM;EACf,MAAK;EACL,MAAK;EACL,MAAK;CACN,CAAA,GAJgBD,EAAAA,MAAAA,MAAAA,YADLC,EAAAA,MAAAA;CAMZC,IAAAA;CAIW,AAAA,EAAA,QAAA,eAAA,EAAA,QAHOF,MAAAA,cADlB,MAAA,oBAAC,QAAD;EACE,UAAU,MAAM;EAChB,MAAK;EACL,MAAK;EACL,SAAS;CACV,CAAA,GADU,EAAA,MAAA,aAHOA,EAAAA,MAAAA,MAAAA;CAVpBG,IAAAA;CACEJ,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAQAG,OATF,MAAA,qBAAC,QAAD;EAAQ,KAAK;EAAb,UAAA,CACEH,KAQAG,GAMM;KAdNH,EAAAA,MAAAA,KAQAG,EAAAA,MAAAA;CAODE,IAAAA;CAAMC,AAAAA,EAAAA,QAAAA,MAAAA,uBAAN,MAAA,MAAM,SACL,oBAAC,MAAD;EAAM,SAAS;GAAC;GAAG;GAAG;EAAC;EAAG,QAAQ;EAAG,QAAQ;EAAG,MAAK;EACnD,UAAA,oBAAC,MAAD,EAAA,UAAO,MAAM,MAAY,CAAA;CACrB,CAAA,GAHDA,EAAAA,MAAAA,MAAAA;CAhITC,IAAAA;CACG9B,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QA0BDI,OAAAA,EAAAA,QAUAI,OAAAA,EAAAA,QAUAQ,OAAAA,EAAAA,QA6BAG,OAAAA,EAAAA,QAoCAQ,OAAAA,EAAAA,QAgBCC,OAhIH,MAAA,qBAAC,OAAD;EAAO,KAAK;EAAZ,UAAA;GACG5B;GA0BDI;GAUAI;GAUAQ;GA6BAG;GASAG;GA2BAK;GAgBCC;EAKI;KApIJ5B,EAAAA,MAAAA,KA0BDI,EAAAA,MAAAA,KAUAI,EAAAA,MAAAA,KAUAQ,EAAAA,MAAAA,KA6BAG,EAAAA,MAAAA,KAoCAQ,EAAAA,MAAAA,KAgBCC,EAAAA,MAAAA;CAlIPG,IAAAA;CACkB,AAAA,EAAA,QAAA,gBAAA,EAAA,QACdD,OAFJ,MAAA,oBAAC,KAAD;EAAK,SAAS;EACZ,UAAA,oBAAC,QAAD;GAAM,UAAU;GAAc,YAAA;GAC5BA,UAAAA;EAsII,CAAA;CACH,CAAA,GAxIa,EAAA,MAAA,cACdA,EAAAA,MAAAA;CAZNE,IAAAA;CADF,OAIa,EAAA,QAAA,eAAA,EAAA,QADL,MAAA,EAAA,QAQJD,OAVF,MAAA,oBAAC,QAAD;EACE,SAAA;EACI;EACJ,SAAS;EACT,gBAAgB;EAChB,QAAQhC;EACR,SAAS;EACT,UAAS;EACT,OAAO;EAEPgC,UAAAA;CA0IM,CAAA,GAjJG,EAAA,MAAA,aADL,EAAA,MAAA,IAQJA,EAAAA,MAAAA,iCAVFC;AAsJJ;AAGA,SAAwB,eAAe;eAC/B,CAAC,YAAY,iBAAiB,eAAe,GAC7C,uBAAuB,yBAAyB,GAEvBC;CAAM,AAAA,EAAA,OAAA,6BAAN,WAAM,cAAc,SAAS,GAAvB,EAAA,KAAA;CAArC,IAAM,aAAaC;CAEnB,IAAI,eAAe,WAAW;EAE1BC,IAAAA;EADF,OAEwCC,EAAAA,OAAAA,qBAAN,MAAM,WAAA,EAAA,OACpB,iBAFlB,KAAA,oBAAC,oBAAD;GACE,SAAS,qBAAqB,MAAM;GACpC,gBAAgB;EACjB,CAAA,GAFqCA,EAAAA,KAAAA,qBAAN,MAAM,SACpB,EAAA,KAAA,uCAFlBD;CAKJ;CAEOE,IAAAA;CAAP,OAA6D,EAAA,OAAA,0BAAtD,KAAA,oBAAC,QAAD;EAAQ,MAAK;EAAQ,MAAK;EAAmB,SAAS;CAAa,CAAA,GAAb,EAAA,KAAA,wBAAtDA;AACT;;;;;;;;AC3RA,SAAgB,yBAAyB,SAAyB;CAChE,OAAO,UAAU,eAAe,SAAS,EAAE;AAC7C;;;;;;;;;AAUA,SAAgB,0BAA0B,UAA8B,SAA0B;CAQhG,OANI,CAAC,YAAY,SAAS,KAAK,MAAM,MAM9B,aADa,yBAAyB,OACzB;AACtB;AC5BA,SAAgB,aAAa,MAAoC;CAC/D,uBAAO,IAAI,KAAK,OAAO,IAAI,IAAI,GAAI;AACrC;ACEA,SAAgB,iBAAiB,QAAsB,SAAiB;CACtE,IAAM,EAAC,YAAW,OAAO,OAAO;CAChC,OAAO,kBAAkB,MAAM,CAAC,CAAC,QAAc;EAC7C,KAAK,sBAAsB,QAAQ,GAAG;EACtC,iBAAiB;EACjB,QAAQ;EACR,OAAO;CACT,CAAC;AACH;AAEA,eAAsB,YAAY,EAChC,QACA,OACA,eAKC;CACD,IAAI,CAAC,OAAO,KAAK,OAAO;CAExB,IAAI;EACF,MAAM,OAAO,OAAO,MAAM,GAAG;CAC/B,QAAQ;EACN,OAAO;CACT;CAEA,IAAI,eAAe,OAAO,SACxB,IAAI;EACF,MAAM,iBAAiB,QAAQ,MAAM,OAAO;CAC9C,QAAQ;EACN,OAAO;CACT;CAGF,OAAO;AACT;AAEA,SAAgB,SAAS,QAAsB,SAAiB;CAC9D,IAAM,EAAC,YAAW,OAAO,OAAO;CAChC,OAAO,kBAAkB,MAAM,CAAC,CAAC,QAA0B;EACzD,KAAK,sBAAsB,QAAQ,QAAQ;EAC3C,iBAAiB;EACjB,QAAQ;EACR,OAAO;CACT,CAAC;AACH;AAEA,SAAgB,WACd,QACA,SACA;CACA,IAAM,EAAC,YAAW,OAAO,OAAO,GAC1B,QAA2C,CAAC;CASlD,OAPI,QAAQ,UACV,MAAM,QAAQ,QAAQ,MAAM,SAAS,IAEnC,QAAQ,WACV,MAAM,SAAS,QAAQ,SAGlB,kBAAkB,MAAM,CAAC,CAAC,QAAyD;EACxF,KAAK,sBAAsB,QAAQ;EACnC,iBAAiB;EACjB,QAAQ;EACR,OAAO;GAAC,GAAG;GAAO,GAAG;EAAoB;CAC3C,CAAC;AACH;;;;AAKA,SAAgB,oBACd,QACA,SACA,QACA,SAKA;CACA,IAAM,EAAC,YAAW,OAAO,OAAO;CAEhC,OAAO,kBAAkB,MAAM,CAAC,CAAC,QAA0B;EACzD,KAAK,sBAAsB,QAAQ,GAAG,QAAQ;EAC9C,iBAAiB;EACjB,QAAQ;EACR,MAAM;GACJ,KAAK;GACL,MAAM;GACN,eAAe,QAAQ;GACvB,MAAM,QAAQ;GACd,WAAW,QAAQ,aAAa;EAClC;EACA,SAAS,EACP,gBAAgB,mBAClB;EACA,OAAO;CACT,CAAC;AACH;;;;AAKA,SAAgB,kBACd,QACA,SACA,cACA,SAIA;CACA,IAAM,EAAC,YAAW,OAAO,OAAO;CAChC,OAAO,kBAAkB,MAAM,CAAC,CAAC,QAA0B;EACzD,KAAK,sBAAsB,QAAQ,GAAG,QAAQ,UAAU,aAAa;EACrE,iBAAiB;EACjB,QAAQ;EACR,MAAM,EACJ,qBAAqB,CACnB;GACE,eAAe,QAAQ;GACvB,MAAM,QAAQ;EAChB,CACF,EACF;EACA,SAAS,EACP,gBAAgB,mBAClB;EACA,OAAO;CACT,CAAC;AACH;;;;AAKA,SAAgB,gBAAgB,QAAsB,SAAiB,SAAiB;CACtF,IAAM,EAAC,YAAW,OAAO,OAAO;CAChC,OAAO,kBAAkB,MAAM,CAAC,CAAC,QAA0B;EACzD,KAAK,sBAAsB,QAAQ,GAAG,QAAQ,UAAU;EACxD,iBAAiB;EACjB,QAAQ;EACR,OAAO;CACT,CAAC;AACH;;;;;AAMA,SAAgB,mBACd,QACA,SACA,cACA;CACA,IAAM,EAAC,YAAW,OAAO,OAAO;CAChC,OAAO,kBAAkB,MAAM,CAAC,CAAC,QAA0B;EACzD,KAAK,sBAAsB,QAAQ,GAAG,QAAQ;EAC9C,iBAAiB;EACjB,QAAQ;EACR,MAAM,EAAC,eAAe,aAAY;EAClC,SAAS,EACP,gBAAgB,mBAClB;EACA,OAAO;CACT,CAAC;AACH;;;;ACvIA,eAAe,mBACb,QACA,QACqB;CACrB,IAAI;EACF,IAAM,WAAW,MAAM,WAAW,QAAQ;GACxC,OAAO;GACP;EACF,CAAC;EAED,OAAO;GACL;GACA,MAAM,SAAS;GACf,aAAa,SAAS,eAAe;EACvC;CACF,QAAQ;EACN,OAAO;GACL;GACA,OAAO,EAAC,MAAM,aAAY;EAC5B;CACF;AACF;AAEA,SAAS,4BACP,cACA,YACgB;CAChB,IAAM,cAAe,UAAU,gBAAgB,aAAa,QAAS,CAAC,GAIhE,EAAC,aAAa,uBAHD,UAAU,cAAc,WAAW,QAAS,CAAC,EAAA,CAGb,QAIhD,KAAK,UAAU;EACd,IAAM,iBAAiB,MAAM,gBAAgB,MAAM,aAAa,SAAS,GACnE,cAAc,YAAY,MAAM,MAAM,EAAE,OAAO,MAAM,EAAE;EAU7D,OARK,mBACH,IAAI,oBAAoB,KAGtB,kBAAkB,CAAC,eACrB,IAAI,YAAY,KAAK,KAAK,GAGrB;CACT,GACA;EAAC,aAAa,CAAC;EAAG,mBAAmB;CAAK,CAC5C;CAEA,OAAO;EACL,GAAG;EACH,MAAM,CAAC,GAAG,aAAa,GAAG,WAAW;EACrC,OACE,WAAW,aACP,WAAW,QAEX,KAAA;EACN,QAAQ,iBAAiB,aAAa,WAAW,cAAc,WAAW;EAC1E,SAAS;EACT,iCACE,aAAa,mCAAmC;CACpD;AACF;AAEA,SAAS,aAAa,YAAwB;CAC5C,OACE,OAAO,cAAe,YAAY,iBAAiB,cAAc,WAAW,gBAAgB;AAEhG;;;;;;;;;AAUA,SAAwB,aAAA,IAA0E;eAA7D,EAAC,QAAQ,YAATK,IACgBC;;EAAC,SAAS;EAAM,QAAQ;CAAI;CAA/E,IAAM,CAAC,OAAO,YAAY,SAAyBA,EAA6B,GAEtEC;CAKJ,AAAA,EAAA,OAAA,UAAA,EAAA,OAJC,WAAA,EAAA,OAMS,SAPN,WAAM;EACd,IAAI,CAAC,SAAS;EAEd,IAAM,eAAe,YACnB,mBACE,QAEA,UAAU,SAAS,MAAM,QAAQ,MAAM,KAAK,SAAS,KAAK,CAAC,MAAM,QAC7D,MAAM,SACN,IACN,CACF,CAAC,CACE,KAEC,QAAQ,eAGF,aAAa,UAAU,IAClB,MAAM,GAAI,CAAC,CAAC,KACjB,gBACE,YACE,mBACE,QACA,iBAAiB,aAAa,WAAW,cAAc,IACzD,CACF,CACF,CACF,IAIK,GAAG,CACX,GAGD,KAAK,iBACH,UAAU,cAAc,4BAA4B,WAAWC,YAAU,CAAC,CAC5E,CACF,CAAC,CACA,UAAU,EAET,gBAAgB;GACd,SAASC,OAGP;EACJ,EACF,CAAC;EAGH,aAAa,aAAa,YAAY;CAGxC,GAhDM,EAAA,KAAA,QAJC,EAAA,KAAA,SAMS,EAAA,KAAA;CA8CbC,IAAAA;CAEH,OAFI,EAAA,OAAA,uBAAD,KAAA,CAAC,OAAO,GAAP,EAAA,KAAA,qBArDJ,UAAUH,IAqDPG,EAAS,GAEL;AACT;AAdmB,SAAAE,QAAC,MAAA;CAAU,OAAA;EAClB,GAAG;EACH,SAAS;CACX;;ACtJV,SAAwB,qBAAqB;gBACrC,gBAAgB,iBAAiB,GACjC,SAASc,YAAU,GAEnB,CAAC,gBAAgB,yBAAyB,kBAAkB,aAAa,GAGzE,aAAa,CAAC,CADS,yBACR,CAAA,CAAqB,MAAM,SAAS,WAEnD,CAAC,aAAa,kBAAkB,SAAkB,GAClD,CAAC,aAAa,kBAAkB,SAAsB,QAAQ,GAC9D,aAAa,gBAAgB,UAIxB,KAAA,cAAc,YAFMb;CAC7B,AAAA,EAAA,OAAA,UAAA,EAAA,OACSC,MAFoB,KAAA;EAC7B;EACA,SAASA;CACX,GAFE,EAAA,KAAA,QACSA,EAAAA,KAAAA;CAFX,IAAM,YAAY,aAAaD,EAG9B,GAGQE;CAA4BC,AAAAA,EAAAA,OAAAA,kBAAAA,EAAAA,OAAAA,UAAAA,QAA5B,KAAA,kBAAkB,UAAU,OAC/B,UAAU,KAAK,QAAQ,MAAM,CAAC,oBAAoB,GAAG,cAAc,CAAC,IACpE,KAAA,GAFG,EAAA,KAAA,gBAA4BA,EAAAA,KAAAA,UAAAA;CADrC,IAAM,gBAAgBC,IAM2CC;qDAAC,KAAA,CAAA;CAAlE,IAAM,CAAC,gBAAgB,qBAAqB,SAAqBA,EAAE,GAE/CC;CACd,AAAA,EAAA,OAAA,2BADc,WAAM;EACxB,AAAI,gBAAgB,eAAa,eAAe,QAAQ;CAC1D,GADM,EAAA,KAAA;CADN,IAAM,cAAcA,IAGDC;CACb,AAAA,EAAA,OAAA,4BADa,WAAM;EACvB,AAAI,gBAAgB,YAAU,eAAe,MAAM;CACrD,GADM,EAAA,KAAA;CADN,IAAM,aAAaA,IAInBC;CAIa,AAAA,EAAA,QAAA,UAAA,EAAA,QAFO,kBAFpB,KAAA,eAAe,eAAe;EAC5B,eAAe,WAAW;EAC1B,IAAM,YAAY,eAAe,QAAQC,OAAgD,GAEnF,KAAK,OAAO,YAAY;EAC9B,UAAU,SAAS,QAAQ,GAAG,OAAO,GAAG,CAAC;EAEzC,IAAI;GAGF,AAFA,MAAM,GAAG,OAAO,EAAC,iBAAiB,GAAK,CAAC,GACxC,kBAAkB,CAAC,CAAC,GACpB,eAAe,MAAM;EACvB,SAASC,IAAO;GAAP,IAAA,QAAA;GAEP,AADA,eAAe,OAAO,GACtB,eAAe,KAAK;EACtB;CACF,GAXa,EAAA,MAAA,QAFO,EAAA,MAAA;CAFpB,IAAe,eAAfF,IAiBOG;CAAP,OACE,EAAA,QAAA,yBAAA,EAAA,QACA,eAAA,EAAA,QACA,cAAA,EAAA,QAGA,cAAA,EAAA,QACA,gBAAA,EAAA,QAFA,eAAA,EAAA,QADA,eAAA,EAAA,QAIA,iBAAA,EAAA,QACA,aAAA,EAAA,QACA,cAAA,EAAA,QACA,kBAXK,KAAA;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,GAZE,EAAA,MAAA,uBACA,EAAA,MAAA,aACA,EAAA,MAAA,YAGA,EAAA,MAAA,YACA,EAAA,MAAA,cAFA,EAAA,MAAA,aADA,EAAA,MAAA,aAIA,EAAA,MAAA,eACA,EAAA,MAAA,WACA,EAAA,MAAA,YACA,EAAA,MAAA,0CAXKA;AAcT;AA7B6C,SAAAG,QAAC,OAAA;CAAU,OAAA,yBAAyB,KAAK,KAAK,CAAC;;AA+B5F,SAAS,yBAAyB,OAAiD;CACjF,IAAM,cAAc,MAAM,gBAAgB,CAAC,EAAA,CAAG,MAAM,MAAM,EAAE,EAAE,CAAC,EAAE;CAEjE,IAAK,YAEL,OAAO;EACL,KAAK,KAAK;EACV,OAAO;EACP,6BAAY,IAAI,KAAK,EAAA,CAAE,YAAY;EACnC,YAAY,aAAa,MAAM,UAAU,CAAC,CAAC,YAAY;EACvD,SAAS,MAAM;EACf;EACA,UAAU,MAAM,MAAM,SAAS,yBAAyB,MAAM,EAAE;EAChE,QAAQ,MAAM;EACd,MAAM;CACR;AACF;AAEA,MAAM,oBAAoB,iCACvB,kBACQ,cAAc,YACR,oJAIX,CAAC,GACD,EACE,YAAY,mBACd,CACF,CAEJ;AAEA,SAAS,oBAAoB,OAAiB,gBAAiC;CAI7E,OAFI,MAAM,WAAW,WAEd,eAAe,MACnB,aAAa,SAAS,YAAY,MAAM,MAAM,SAAS,aAAa,MAAM,SAC7E;AACF;ACnHA,SAAgB,UACd,KAAA,IAEA;eADAC;4BAA+B,KAAA,OAAA,KAAA,IAAA,CAAC,IAAhCA;mBAEM,CAAC,QAAQ,aAAa,SAAS,EAAK,GAEhCC,IAsBPC;CAEH,OAXIC,EAAAA,OAAAA,WAAAA,EAAAA,OAZGC,OADG,WAAM;EACd,IAAI,CAAC,IAAI,SAAS;EAElB,IAAM,WAAW,IAAI,sBAAA,IAA+B,QAAQ;GAAjB,IAAA,CAAC,SAADC,IAInC,YACJ,MAAO,kBACP,IAAI,WAAW,MAAM,cAAc,MAAO,qBAAqB,SAAS;GAI1E,AADA,UAAU,SAAS,GACnB,SAAS,WAAW,SAAS;EAC/B,GAAG,OAAO,GAEJ,YAAY,IAAI;EAGtB,OAFA,SAAS,QAAQ,SAAS,SAEb;GACX,AAAI,aAAW,SAAS,UAAU,SAAS;EAC7C;CACF,GAAG,KAAA,CAAC,SAAS,GAAG,GATZF,EAAAA,KAAAA,SAZGC,EAAAA,KAAAA,qDADP,UAAUH,IAsBPC,EAAc,GAEV;AACT;AC7BA,SAAgB,cACd,OACA,WAAqB;CAAC;CAAO;CAAU;AAAQ,GACvC;CACR,IAAI;EACF,IAAI,CAAC,OACH,MAAU,UAAU,wCAAwC;EAG9D,IAAM,cAAc,MAAM,MAAM;EAChC,IAAI,eAAe,YAAY,SAAS,GAAG;GACzC,KAAK,IAAM,UAAU,UAAU;IAC7B,IAAM,QAAQ,YAAY,MAAM,UAAU,MAAM,WAAW,MAAM;IACjE,IAAI,OACF,OAAO,MAAM;GAEjB;GAEA,OAAO,YAAY,EAAE,CAAE;EACzB;EAEA,MAAU,UAAU,oBAAoB;CAC1C,SAAS,GAAG;EAEV,MADA,QAAQ,MAAM,iCAAiC,EAAC,MAAK,GAAG,CAAC,GACnD;CACR;AACF;AAEA,SAAgB,kBACd,OAC2B;CAC3B,OACE,MAAM,MAAM,cAAc,MACvB,eAAe,cAAc,OAAO;EAAC;EAAO;EAAU;CAAQ,CAAC,MAAM,WAAW,EACnF,KAAK;EAAC,IAAI;EAAI,QAAQ;CAAQ;AAElC;AAEA,SAAgB,sBACd,OACA,YAC2B;CAC3B,OAAO,MAAM,MAAM,cAAc,MAAM,UAAU,eAAe,MAAM,EAAE;AAC1E;AAEA,SAAgB,kBACd,MAIA,QACA;CACA,OACG,KAAK,8BACJ,KAAK,2BAA2B,MAAM,MAAM,EAAE,WAAW,MAAM,KACjE,KAAK,iBAAiB,MAAM,MAAM,MAAM,MAAM;AAElD;;;;AC7CA,SAAgB,YACd,QACA,YACA,KACA,SACQ;CACR,IAAM,EAAC,cAAc,sBAAqB,YAAY,MAAM;CAC5D,IAAI,CAAC,cACH,MAAU,UAAU,6DAA6D;CAEnF,IAAI,CAAC,mBACH,MAAU,UAAU,kEAAkE;CAQxF,IAAM,EAAC,SAAS,SAAQ,cAAc,OAAO,0BAA0B,CAAC,uBAAuB,CAAC;CAEhG,OAAO,KACL,UAAU,KAAK,MAAM,KAAK,UAAU,UAAU,GAAG,MAAM,KAAK,KAAA,CAAS,CAAC,IAAI,CAAC,GAC3E,KAAK,iBAAiB,GACtB;EACE,WAAW;EACX,OAAO;EACP,UAAU;EACV,SAAS;EACT,aAAa;EACb,WAAW;CACb,CACF;AACF;;;;AC9CA,SAAgB,sBACd,QACA,OACA,QACA,UACA;CACA,IAAM,aAAa,cAAc,KAAK,GAElC,eAAe,IAAI,gBACrB,KAAK,MAAM,KAAK,UAAU,SAAS,GAAG,MAAM,KAAK,KAAA,CAAS,CAAC,CAC7D,GACM,iBAAiB,sBAAsB,OAAO,UAAU,CAAC,EAAE;CACjE,IAAI,mBAAmB,YAAY,mBAAmB,OAAO;EAC3D,IAAM,QAAQ,YAAY,QAAQ,YAAY,UAAU,MAAM;EAC9D,eAAe,IAAI,gBAAgB,EAAC,MAAK,CAAC;CAC5C;CAEA,OAAO;EAAC;EAAY;CAAY;AAClC;ACjBA,SAAgB,qBAAqB,EACnC,OACA,QACA,QACA,OACA,QAAQ,MAAM,YAAY,KAAK,IAAI,GAAG,MAAM,YAAY,GAAG,IAAI,GAC/D,MAAM,QAAQ,GACd,MAAM,MAC8C;CAGpD,IAAM,EAAC,YAAY,iBAAgB,sBAAsB,QAAQ,OAAO;EAFxD;EAAQ;EAAO;EAAO;EAAK;CAE6B,GAAQ,GAAG;CAEnF,OAAO,yBAAyB,WAAW,gBAAgB;AAC7D;ACdA,SAAgB,aAAa,EAC3B,OACA,QACA,UACA,QACA,OAAO,MAAM,aAAa,KAAA,GAC1B,SACoC;CACpC,IAAM,SAAS;EAAC;EAAU;EAAQ;CAAK;CACvC,AAAI,SAAS,KAAA,MACV,OAAgB,OAAO;CAG1B,IAAM,EAAC,YAAY,iBAAgB,sBAAsB,QAAQ,OAAO,QAAQ,GAAG;CAEnF,OAAO,yBAAyB,WAAW,iBAAiB;AAC9D;;;;;;;;;ACnBA,SAAgB,eACd,OACA,SACmB;CACnB,IAAI;EACF,OAAO,MAAM;CACf,SAAS,gBAAgB;EACvB,IAAI,0BAA0B,SAE5B,MAAM;EAER,OAAO,UAAU,QAAQ,cAAuB,IAAI,KAAA;CACtD;AACF;ACRA,MAAMK,UAAQ,OAAO,IAAA,WAAA;;;AAAG,CAAA,CAAA,gIAWlB,iBAAgD;CACpD,SAAS;CACT,OAAO;CACP,QAAQ;AACV;AAEA,SAAwB,eAAe,EACrC,OACA,OACA,cAAc,MAKb;CACD,IAAM,cAAc,SAAS,KACvB,SAASC,YAAU,GACnB,MAAM,OAA8B,IAAI,GACxC,SAAS,UAAU,GAAG,GAEtB,CAAC,QAAQ,aAAa,SAAsB,SAAS,GACrD,CAAC,OAAO,YAAY,SAAwB,IAAI,GAEhD,eAAe,cACZ,qBACC;EACJ,IAAI;EAIJ,OAFA,AACK,YADD,cAAyB,aAAa;GAAC;GAAO;GAAQ,OAAO;EAAW,CAAC,IAC5D,qBAAqB;GAAC;GAAO;GAAQ,OAAO;EAAW,CAAC,GAClE;CACT,IACC,QAAe;EAEd,YAAY,IAAI,OAAO;CAEzB,CACF,GACC;EAAC;EAAO;EAAQ;EAAa;CAAW,CAAC;CAE5C,SAAS,aAAa;EACpB,UAAU,QAAQ;CACpB;CAEA,SAAS,YAAY,KAAc;EAEjC,AADA,UAAU,OAAO,GAEf,SADE,OAGO,0BAA0B;CAEvC;CAEA,OACE,oBAAC,UAAD;EAAU,UAAU,oBAAC,QAAD,EAAA,UAAM,sBAAyB,CAAA;EACjD,UAAA,oBAAC,MAAD;GACE,OAAO;IACL,aAAa;IACb,UAAU;IACV,UAAU,QAAQ,GAAG,MAAM,MAAM,KAAA;IACjC,OAAO;IACP,MAAM;GACR;GACA,QAAA;GACA,QAAQ;GACH;GACL,MAAM,eAAe;GAEpB,UAAA,SACC,qBAAAC,UAAA,EAAA,UAAA;IACG,WAAW,aACV,oBAAC,KAAD;KACE,OAAO;MACL,UAAU;MACV,MAAM;MACN,KAAK;MACL,WAAW;KACb;KAEA,UAAA,oBAAC,SAAD,CAAU,CAAA;IACP,CAAA;IAEN,WAAW,WACV,qBAAC,OAAD;KACE,KAAK;KACL,OAAO;MACL,UAAU;MACV,OAAO;MACP,MAAM;MACN,KAAK;MACL,WAAW;MACX,cAAc;KAChB;KATF,UAAA,CAWE,oBAAC,MAAD;MAAM,MAAM;MAAG,OAAA;MACb,UAAA,oBAAC,kBAAD,EAAkB,OAAO,EAAC,UAAU,SAAQ,EAAI,CAAA;KAC5C,CAAA,GACN,oBAAC,MAAD;MAAM,OAAA;MAAM,OAAM;MACf,UAAA;KACG,CAAA,CACD;;IAET,oBAACF,SAAD;KACE,KAAK,gBAAgB,KAAA;KACrB,KAAK,eAAe,cAAc,UAAU,QAAQ,GAAG,MAAM,YAAY,MAAM;KAC/E,QAAQ;KACR,eAAe,YAAY;KAC3B,OAAO,EAAC,SAAS,aAAW,UAAgB;IAC7C,CAAA;GACD,EAAA,CAAA,IACA;EACA,CAAA;CACE,CAAA;AAEd;AC3HA,MAAM,uBAAuB,OAAO,QAAQ,CAAC,CAAA,WAAA;;;;AAa7C,SAAS,aAAA,IAQN;gBARmB,EACpB,OACA,aACA,aAHoBG,IASd,WAAW,qBAAqB,MAAM,WAAW,GAAI,GAIlD,KAAA,MAAM,IACL,KAAA,WAAW,aAAa,KAAA,GAIvBC;qDAAC,KAAA,EAAA,UAAU,WAAU;CAMdC,IAAAA;CACR,AAAA,EAAA,OAAA,2BADQ,MAAC,MAAM;EACf,YAAY,EAAE,cAAc,OAAO;CACrC,GADE,EAAA,KAAA;CAEU,IAAA,KAAA,WAAW,gBAAgB,MAAM,OAAO,wBAAwB,MAAM,MALpFC;CACW,AAAA,EAAA,OAAA,YAAA,EAAA,OACCD,MAAAA,EAAAA,OAGEE,MALd,KAAA,oBAAC,sBAAD;EACE,SAAS;EACT,UAAUF;EAGV,cAAYE;CACb,CAAA,GALU,EAAA,KAAA,UACCF,EAAAA,KAAAA,IAGEE,EAAAA,KAAAA;CAOEC,IAAAA;CAAMC,AAAAA,EAAAA,OAAAA,MAAAA,4BAAN,KAAA,MAAM,aAAa,KAAKC,OAAW,CAAC,EAAE,IAAhCD,EAAAA,KAAAA,MAAAA;CALtBE,IAAAA;CAEaC,AAAAA,EAAAA,OAAAA,SAAAA,EAAAA,QAGGJ,MALhB,KAAA,oBAAC,gBAAD;EACE,OAAO;GACL,SAAS,MAAM;GACf,MAAM;GACN,UAAU,MAAM;GAChB,YAAYA;EACd;EACA,OAAO;CACR,CAAA,GANYI,EAAAA,KAAAA,OAGGJ,EAAAA,MAAAA;CAMIK,IAAAA;CAAqBC,AAAAA,EAAAA,QAAAA,MAAAA,mBAArB,KAAA,eAAe,MAAM,IAAI,EAAE,GAANA,EAAAA,MAAAA,MAAAA;CAArCC,IAAAA;CAAgBF,AAAAA,EAAAA,QAAAA,oBAAhB,MAAA,oBAAC,MAAD;EAAM,MAAM;EAAIA,UAAAA;CAAmC,CAAA,GAAnCA,EAAAA,MAAAA;CAChBG,IAAAA;CACaC,AAAAA,EAAAA,QAAAA,SAAAA,2BADb,MAAA,qBAAC,MAAD;EAAM,OAAA;EAAM,MAAM;EAAlB,UAAA;GACE;GAAE,SAAS;GAAU;EACjB;KADOA,EAAAA,MAAAA,SAAAA;CAHfC,IAAAA;CACEH,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QACAC,OAFF,MAAA,qBAAC,MAAD;EAAM,OAAM;EAAS,KAAK;EAA1B,UAAA;GACED;GAAqD;GACrDC;EAGI;KAJJD,EAAAA,MAAAA,KACAC,EAAAA,MAAAA;CAMU,IAAA,MAAA,OAAO,MAAM,UAAU,IAAI,KAApCG;CAASC,AAAAA,EAAAA,QAAAA,qBAAT,MAAA,IAAI,KAAKA,GAA+B,CAAC,CAAC,mBAAmB,MAAM;EAClE,MAAM;EACN,KAAK;EACL,OAAO;CACT,CAAC,GAJSA,EAAAA,MAAAA;CAFZC,IAAAA;CAEGF,AAAAA,EAAAA,QAAAA,qBAFH,MAAA,qBAAC,MAAD;EAAM,MAAM;EAAZ,UAAA;GACE;GAAY;GACXA;EAKG;KALHA,EAAAA,MAAAA;CATLG,IAAAA;CACEJ,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAMAG,OAPF,MAAA,qBAAC,OAAD;EAAO,KAAK;EAAZ,UAAA,CACEH,KAMAG,GAQK;KAdLH,EAAAA,MAAAA,KAMAG,EAAAA,MAAAA;CAxBJE,IAAAA;CAiBED,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAhBAhB,MAAAA,EAAAA,QAOAK,MARF,MAAA,qBAAC,MAAD;EAAM,OAAM;EAAS,KAAK;EAA1B,UAAA;GACEL;GAOAK;GASAW;EAgBI;KAhBJA,EAAAA,MAAAA,KAhBAhB,EAAAA,MAAAA,IAOAK,EAAAA,MAAAA;CAjBJa,IAAAA;CADF,OAEeV,EAAAA,QAAAA,MAAAA,MAAAA,EAAAA,QAQXS,OAAAA,EAAAA,QAPME,MAFR,MAAA,oBAAC,MAAD;EAEE,MAAMA;EACN,QAAA;EACA,UAAU;EACV,UAAU;EACV,OAAOrB;EACP,QAAQ;EAERmB,UAAAA;CAkCI,GA1CCX,EA0CD,GA1COE,EAAAA,MAAAA,MAAAA,IAQXS,EAAAA,MAAAA,KAPME,EAAAA,MAAAA,gCAFRD;AA6CJ;AAvBgD,SAAA2B,QAAC,GAAA;CAAM,OAAA,EAAE;;AAyBzD,SAAS,mBAAmB,OAA8C;gBAClE,EAAC,gBAAe,OAEhB,oBACH,gBAAgB,UAAU,gBAAgB,YAAY,MAAM,eAAe,SAAS,GACjF,cAAc,gBAAgB,aAC9B,mBACJ,MAAM,eAAe,WAAW,KAAK,CAAC,MAAM,UAAU,WAAW,CAAC,MAAM,uBAapEzB;CA2BqB,AAAA,EAAA,OAAA,oBAAA,EAAA,OA3BrB,eAAA,EAAA,OAWkB,eAAA,EAAA,OAVjB,oBAAA,EAAA,OASsBC,MAAAA,eAAAA,EAAAA,OAeEC,MAAAA,gBAAAA,EAAAA,OAZZC,MAAAA,iBAAAA,EAAAA,OAOKC,MAAAA,kBApBlB,KAAA,gBAAgB,UAChB,CAAC,oBACC,oBAAC,MAAD;EAAM,SAAS;EACb,UAAA,qBAAC,MAAD;GAAM,SAAQ;GAAgB,OAAM;GAApC,UAAA,CACE,oBAAC,QAAD;IACE,UAAU;IACV,SAAS;IACT,MAAK;IACL,MAAK;IACL,MAAK;IACL,SAAS,MAAM;IACf,UAAU;GACX,CAAA,GACA,MAAM,iBACL,oBAAC,QAAD;IACE,MAAM;IACN,UAAU;IACV,SAAS;IACT,MAAK;IACL,MACE,MAAM,gBAAgB,SAAS,IAC3B,UAAU,MAAM,eAAe,OAAO,aACtC;IAEN,MAAK;IACL,SAAS,MAAM;IACf,WAAW,eAAe;IAC1B,UAAU,CAAC;GACZ,CAAA,CAEC;;CACF,CAAA,GAJa,EAAA,KAAA,kBA3BrB,EAAA,KAAA,aAWkB,EAAA,KAAA,aAVjB,EAAA,KAAA,kBASsBH,EAAAA,KAAAA,MAAAA,aAeEC,EAAAA,KAAAA,MAAAA,cAZZC,EAAAA,KAAAA,MAAAA,eAOKC,EAAAA,KAAAA,MAAAA;CAiBjBC,IAAAA;CAAgBC,AAAAA,EAAAA,OAAAA,MAAV,UAAU,gDAAhB,KAAA,MAAM,UAAU,mCACf,oBAAC,MAAD;EAAM,MAAK;EAAU,cAAc;EAAG,SAAS;EAAG,QAAA;EAChD,UAAA,qBAAC,MAAD;GAAM,OAAM;GAAS,KAAK;GAA1B,UAAA,CACE,oBAAC,iBAAD,EAAiB,UAAU,GAAK,CAAA,GAChC,qBAAC,OAAD;IAAO,KAAK;IAAZ,UAAA,CACE,oBAAC,MAAD;KAAM,MAAM;KAAG,QAAO;KACpB,UAAA;IACI,CAAA,GACN,oBAAC,MAAD;KAAM,MAAM;KACV,UAAA;IAEI,CAAA,CACD;GACH,CAAA,CAAA;;CACF,CAAA,GAdSA,EAAAA,KAAAA,MAAV,UAAU;CAkBhBC,IAAAA;CAAkCC,AAAAA,EAAAA,QAAAA,MAAAA,yBAAAA,EAAAA,QAUlBL,MAAAA,iBAAAA,EAAAA,QAVCM,MAAV,UAAU,WAAjB,MAAC,MAAM,UAAU,WAAW,MAAM,0BACjC,oBAAC,MAAD;EAAM,MAAK;EAAU,cAAc;EAAG,SAAS;EAAG,QAAA;EAChD,UAAA,qBAAC,MAAD;GAAM,OAAM;GAAS,KAAK;GAA1B,UAAA,CACE,oBAAC,SAAD;IAAS,OAAA;IAAM,MAAM;GAAI,CAAA,GACzB,qBAAC,OAAD;IAAO,KAAK;IAAZ,UAAA,CACE,oBAAC,MAAD;KAAM,MAAM;KAAG,QAAO;KACpB,UAAA;IACI,CAAA,GACN,qBAAC,MAAD;KAAM,MAAM;KAAZ,UAAA,CACE,0BACC,MAAM,iBACL,MAAM,cAAc,SAAS,KAC7B,uBAAuB,MAAM,cAAc,OAAO,QAAQ,MAAM,cAAc,SAAS,IAAI,MAAM,GAAG,4BAClG;IACD,CAAA,CAAA;GACH,CAAA,CAAA;;CACF,CAAA,GAhB2BD,EAAAA,MAAAA,MAAAA,uBAUlBL,EAAAA,MAAAA,MAAAA,eAVCM,EAAAA,MAAAA,MAAV,UAAU;CAoBjBC,IAAAA;CASgBP,AAAAA,EAAAA,QAAAA,MAAAA,iBAAAA,EAAAA,QATAQ,MAAV,UAAU,SAAhB,KAAA,MAAM,UAAU,SACf,oBAAC,MAAD;EAAM,MAAK;EAAW,cAAc;EAAG,SAAS;EAAG,QAAA;EACjD,UAAA,qBAAC,MAAD;GAAM,OAAM;GAAS,KAAK;GAA1B,UAAA,CACE,oBAAC,kBAAD,EAAkB,UAAU,GAAK,CAAA,GACjC,qBAAC,OAAD;IAAO,KAAK;IAAZ,UAAA,CACE,oBAAC,MAAD;KAAM,MAAM;KAAG,QAAO;KACpB,UAAA;IACI,CAAA,GACN,oBAAC,MAAD;KAAM,MAAM;KACT,UAAA,MAAM,gBACH,mBAAmB,MAAM,cAAc,OAAO,QAAQ,MAAM,cAAc,SAAS,IAAI,MAAM,GAAG,sDAChG;IACA,CAAA,CACD;GACH,CAAA,CAAA;;CACF,CAAA,GANSR,EAAAA,MAAAA,MAAAA,eATAQ,EAAAA,MAAAA,MAAV,UAAU;CAmBhBC,IAAAA;CAOgBR,AAAAA,EAAAA,QAAAA,eAAAA,EAAAA,QAAAA,MAAAA,kBAPhB,KAAA,gBAAgB,eACf,oBAAC,MAAD;EAAM,MAAK;EAAU,cAAc;EAAG,SAAS;EAAG,QAAA;EAChD,UAAA,qBAAC,MAAD;GAAM,OAAM;GAAS,KAAK;GAA1B,UAAA,CACE,oBAAC,SAAD;IAAS,OAAA;IAAM,MAAM;GAAI,CAAA,GACzB,oBAAC,OAAD;IAAO,KAAK;IACV,UAAA,qBAAC,MAAD;KAAM,MAAM;KAAG,QAAO;KAAtB,UAAA;MACE;MAAW,MAAM,eAAe;MAAO;MACtC,MAAM,eAAe,SAAS,KAAK;MAAI;KACpC;;GACD,CAAA,CACH;;CACF,CAAA,GAXP,EAAA,MAAA,aAOgBA,EAAAA,MAAAA,MAAAA;CAQhBS,IAAAA;CAkB0BX,AAAAA,EAAAA,QAAAA,eAAAA,EAAAA,QAAAA,MAAAA,gBAAAA,EAAAA,QATVY,MAAAA,eAThB,KAAA,gBAAgB,WACf,oBAAC,MAAD;EAAM,MAAK;EAAW,cAAc;EAAG,SAAS;EAAG,QAAA;EACjD,UAAA,qBAAC,MAAD;GAAM,OAAM;GAAS,KAAK;GAA1B,UAAA,CACE,oBAAC,kBAAD,EAAkB,UAAU,GAAK,CAAA,GACjC,qBAAC,OAAD;IAAO,KAAK;IAAZ,UAAA;KACE,oBAAC,MAAD;MAAM,MAAM;MAAG,QAAO;MACpB,UAAA;KACI,CAAA;KACN,oBAAC,MAAD;MAAM,MAAM;MACT,UAAA,MAAM,cACH,UAAU,MAAM,gBAChB;KACA,CAAA;KACN,oBAAC,KAAD;MAAK,WAAW;MACd,UAAA,oBAAC,QAAD;OACE,MAAM;OACN,MAAK;OACL,MAAK;OACL,SAAS,MAAM;MAChB,CAAA;KACE,CAAA;IACA;GACH,CAAA,CAAA;;CACF,CAAA,GAvBP,EAAA,MAAA,aAkB0BZ,EAAAA,MAAAA,MAAAA,cATVY,EAAAA,MAAAA,MAAAA;CAkBhBC,IAAAA;CAAqB,AAAA,EAAA,QAAA,eAAA,EAAA,QAApB,oBAAD,MAAC,oBAAoB,gBAAgB,WACpC,qBAAC,OAAD;EAAO,UAAU;EAAG,cAAc;EAAG,KAAK;EAAG,OAAO,EAAC,WAAW,SAAQ;EAAxE,UAAA;GACE,oBAAC,KAAD,EAAA,UACE,oBAAC,qBAAD,EAAqB,UAAU,GAAK,CAAA,EACjC,CAAA;GACL,oBAAC,SAAD;IAAS,MAAM;IACZ,UAAA,gBAAgB,SACb,iCACA;GACG,CAAA;GACT,oBAAC,MAAD;IAAM,MAAM;IACT,UAAA,gBAAgB,SACb,iDACA;GACA,CAAA;EACD;KAfa,EAAA,MAAA,aAApB,EAAA,MAAA;CAmBDC,IAAAA;CAEE,AAAA,EAAA,QAAA,eAAA,EAAA,QAFFC,SAAM,KAAA,MAAA,iBACL,MAAM,cAAc,SAAS,MAC5B,gBAAgB,UAAU,gBAAgB,YACzC,qBAAC,OAAD;EAAO,KAAK;EAAZ,UAAA;GACE,qBAAC,SAAD;IAAS,MAAM;IAAf,UAAA;KACE;KAAW,MAAM,cAAc;KAC9B,MAAM,UAAU,WAAW;KAAI;KAAW,MAAM,cAAc,SAAS,KAAK;KAAK;KAClF;IACO;;GACR,CAAC,MAAM,UAAU,WAChB,qBAAC,MAAD;IAAM,OAAM;IAAS,UAAU;IAA/B,UAAA,CACE,oBAAC,UAAD;KACE,IAAG;KACH,OAAO,EAAC,SAAS,QAAO;KACxB,UAAU,MAAM;MAEd,AADkB,EAAE,cAAc,UAGhC,MAAM,iBAAiB,MAAM,kBAAkB,MAAM,aAAa,IAElE,MAAM,kBAAkB,CAAC,CAAC;KAE9B;KACA,SAAS,MAAM,eAAe,WAAW,MAAM,cAAc;IAC9D,CAAA,GACD,oBAAC,KAAD;KAAK,MAAM;KAAG,aAAa;KAAG,IAAG;KAAQ,SAAQ;KAC/C,UAAA,oBAAC,MAAD,EAAA,UAAM,aAAgB,CAAA;IACnB,CAAA,CACD;;GAEP,MAAM,cAAc,KAAK,UACxB,oBAAC,cAAD;IAES;IACP,cAAc,aAAa;KACzB,AAAI,WACF,MAAM,kBAAkB,CAAC,GAAG,MAAM,gBAAgB,KAAK,CAAC,IAExD,MAAM,kBAAkB,MAAM,eAAe,QAAQ,MAAM,EAAE,OAAO,MAAM,EAAE,CAAC;IAEjF;IACA,UAAU,MAAM,eAAe,MAAM,QAAMC,IAAE,OAAO,MAAM,EAAE;GAC7D,GAVM,MAAM,EAUZ,CACF;EACI;KA1CR,EAAA,MAAA,aAFFD,EAAAA,MAAAA;CAxHHE,IAAAA;CAEGd,AAAAA,EAAAA,QAAAA,MAAAA,EAAAA,QAkBAE,MAAAA,EAAAA,QAoBAG,MAAAA,EAAAA,QAmBAE,MAAAA,EAAAA,QAeAC,MAAAA,EAAAA,QA2BAE,MAAAA,EAAAA,QAmBAC,MAxHH,KAAA,qBAAC,KAAD;EAAK,SAAS;EAAd,UAAA;GAEGX;GAkBAE;GAoBAG;GAmBAE;GAeAC;GA2BAE;GAmBAC;EA8CE;KApKFX,EAAAA,MAAAA,IAkBAE,EAAAA,MAAAA,IAoBAG,EAAAA,MAAAA,IAmBAE,EAAAA,MAAAA,IAeAC,EAAAA,MAAAA,IA2BAE,EAAAA,MAAAA,IAmBAC,EAAAA,MAAAA;CArKLI,IAAAA;CADF,OAMmBnB,EAAAA,QAAAA,MAAAA,eAAAA,EAAAA,QAKbD,MAAAA,EAAAA,QAmCFmB,MA7CF,KAAA,oBAAC,QAAD;EACE,SAAA;EACA,QAAQ;EACR,SAAS;EACT,IAAG;EACH,SAAS,MAAM;EACf,gBAAgB,MAAM;EACtB,OAAO;EACP,UAAS;EACT,QACEnB;EAmCFmB,UAAAA;CAuKM,CAAA,GA/MSlB,EAAAA,MAAAA,MAAAA,aAKbD,EAAAA,MAAAA,IAmCFmB,EAAAA,MAAAA,8BA7CFC;AAsNJ;AAEA,SAAwB,sBAAsB;eACtC,eAAe,mBAAmB;CAExC,IAAI,CAAC,aAAa,YAChB;CAGF,IAAI,aAAa,YAAY;EACpBC,IAAAA;EAAP,OAA+B,EAAA,OAAA,4BAAxB,KAAA,oBAAC,oBAAD,EAAoB,GAAI,aAAe,CAAA,GAAf,EAAA,KAAA,0BAAxBA;CACT;CAEOC,IAAAA;CAAP,OAAyEC,EAAAA,OAAAA,aAAAA,0BAAlE,KAAA,oBAAC,QAAD;EAAQ,MAAK;EAAQ,MAAK;EAAkB,SAAS,aAAa;CAAa,CAAA,GAAbA,EAAAA,KAAAA,aAAAA,wBAAlED;AACT;AChUA,MAAM,gBAAgB,UAIhB;gBACE,OAAO,MAAM,MACb,UAAU,MAAM,SAEZI,IAMPC;CANH,AAEwD,EAAA,OAAA,QAAA,EAAA,OAAvBC,MAAAA,SAAAA,EAAAA,OAE7B,WAJM,WAAM;EAEd,IAAM,UAAU,KAAK,IAAI,MAAM,QAAQ,GAAG,KAAK,IAAI,GAAG,IAAI,CAAC;EAC3D,AAAI,SAAS,WACX,QAAQ,OAAO;CAEnB,GAAG,KAAA;EAAC;EAAM,MAAM;EAAO;CAAO,GAJ0B,EAAA,KAAA,MAAvBA,EAAAA,KAAAA,MAAAA,OAE7B,EAAA,KAAA,yDAJJ,UAAUF,IAMPC,EAA4B;CAQlBE,IAAAA;qDAAC,KAAA,EAAA,QAAQ,UAAS;CACf,IAAA,KAAA,QAAQ,GACTC;CAEiBF,AAAAA,EAAAA,OAAAA,MAAAA,SAAAA,EAAAA,OADxB,WADO,WAAM;EACb,SAAS,MACA,KAAK,IAAI,MAAM,QAAQ,GAAG,KAAK,IAAI,GAAG,IAAI,CAAC,CAAC,CACpD;CACH,GAF0BA,EAAAA,KAAAA,MAAAA,OADxB,EAAA,KAAA;CAPJG,IAAAA;CAKYC,AAAAA,EAAAA,OAAAA,MAAAA,EAAAA,QACDF,MANX,KAAA,oBAAC,QAAD;EACE,MAAM;EACN,MAAK;EACL,SAAS;EACT,OAAOD;EACP,UAAUG;EACV,SAASF;CAKV,CAAA,GANWE,EAAAA,KAAAA,IACDF,EAAAA,MAAAA;CAOH,IAAA,KAAA,OAAO,GADfG;CACyBL,AAAAA,EAAAA,QAAAA,MAAAA,SAAAA,EAAAA,QAAjBM,MADR,KAAA,qBAAC,OAAD;EAAO,OAAA;EAAP,UAAA;GACE;GAAMA;GAAS;GAAE,MAAM;EAClB;KADkBN,EAAAA,MAAAA,MAAAA,OAAjBM,EAAAA,MAAAA;CAMCL,IAAAA;sDAAC,KAAA,EAAA,QAAQ,UAAS;CACf,IAAA,KAAA,QAAQ,MAAM,QAAQ,GACvBM;CAEiBP,AAAAA,EAAAA,QAAAA,MAAAA,SAAAA,EAAAA,QADxB,WADO,YAAM;EACb,SAAS,QACA,KAAK,IAAI,MAAM,QAAQ,GAAG,KAAK,IAAI,GAAGQ,MAAI,CAAC,CAAC,CACpD;CACH,GAF0BR,EAAAA,MAAAA,MAAAA,OADxB,EAAA,MAAA;CAPJS,IAAAA;CAMWF,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QADCG,MALZ,MAAA,oBAAC,QAAD;EACE,MAAM;EACN,MAAK;EACL,SAAS;EACT,OAAOT;EACP,UAAUS;EACV,SAASH;CAKV,CAAA,GALUA,EAAAA,MAAAA,KADCG,EAAAA,MAAAA;CArBdC,IAAAA;CADF,OAiBIF,EAAAA,QAAAA,OAAAA,EAAAA,QAfAN,MAAAA,EAAAA,QAYAE,MAbF,MAAA,qBAAAQ,UAAA,EAAA,UAAA;EACEV;EAYAE;EAGAI;CAYA,EAAA,CAAA,GAZAA,EAAAA,MAAAA,KAfAN,EAAAA,MAAAA,IAYAE,EAAAA,MAAAA,gCAbFM;AA8BJ;;;;;;;AC5CA,SAAgB,iBAAiB,MAA0B;CACzD,OAAO;EACL,GAAG;EACH,QAAQ,KAAK,QAAQ,KAAK,OAAO,WAAW;GAC1C,GAAG;GACH,MAAM,MAAM,MAAM,SAAS;EAC7B,EAAE;EACF,cAAc,KAAK,cAAc,KAAK,YAAY,WAAW;GAC3D,GAAG;GACH,MAAM,WAAW,MAAM,YAAY;EACrC,EAAE;EACF,mBAAmB,KAAK,oBACpB;GACE,GAAG,KAAK;GACR,OAAO,KAAK,kBAAkB,OAAO,KAAK,MAAM,WAAW;IACzD,GAAG;IACH,MAAM,KAAK,MAAM,aAAa;GAChC,EAAE;EACJ,IACA,KAAA;CACN;AACF;ACjBA,SAAwB,uBAAuB;gBACvC,gBAAgB,iBAAiB,GACjC,SAASkB,YAAU,GAEnB,CAAC,cAAc,uBAAuB,gBAAgB,aAAa,GAGnE,aAAa,CAAC,CADS,yBACR,CAAA,CAAqB,MAAM,SAAS,WAEnD,CAAC,aAAa,kBAAkB,SAAkB,GAClD,CAAC,aAAa,kBAAkB,SAAsB,QAAQ,GAC9D,aAAa,gBAAgB,UAIxB,KAAA,cAAc,YAFMf;CAC7B,AAAA,EAAA,OAAA,UAAA,EAAA,OACSC,MAFoB,KAAA;EAC7B;EACA,SAASA;CACX,GAFE,EAAA,KAAA,QACSA,EAAAA,KAAAA;CAFX,IAAM,YAAY,aAAaD,EAG9B,GAGQE;CAA0BC,AAAAA,EAAAA,OAAAA,UAAAA,QAAAA,EAAAA,OAA1B,gBAAgB,KAAA,gBAAA,UAAU,OAC7B,aAAa,KAAK,cAAc;EAC9B,IAAM,WAAW,UAAU,MAAM,MAC9B,MAAM,EAAE,OAAO,UAAU,WAAW,EAAE,OAAO,UAAU,MAAM,EAChE;EACA,OAAO;GACL;GACA;GACA,UAAU,UAAU,MAAM;GAC1B,cAAc,UAAU;EAC1B;CACF,CAAC,IACD,KAAA,GAZ6BA,EAAAA,KAAAA,UAAAA,MAA1B,EAAA,KAAA;CADT,IAAM,gBAAgBC,IAgBFC;CACd,AAAA,EAAA,OAAA,2BADc,WAAM;EACxB,AAAI,gBAAgB,aAAW,eAAe,QAAQ;CACxD,GADM,EAAA,KAAA;CADN,IAAM,cAAcA,IAIDC;CACb,AAAA,EAAA,OAAA,2BADa,WAAM;EACvB,AAAI,gBAAgB,YAAU,eAAe,MAAM;CACrD,GADM,EAAA,KAAA;CADN,IAAM,aAAaA,IAInBC;CAMe,AAAA,EAAA,QAAA,UAAA,EAAA,QALR,iBADP,KAAA,eAAe,gBAAgB;EAC7B,IAAK,eAEL;kBAAe,SAAS;GAExB,IAAI;IACF,IAAM,KAAK,OAAO,YAAY;IAS9B,AAPA,cAAc,SAAS,YAAY;KAEjC,IAAM,WAAW,QAAQ,YAAY;KACrC,GAAG,MAAM,QAAQ,UAAU,KAAK,EAAC,KAAK,EAAC,UAAU,SAAQ,EAAC,CAAC;IAC7D,CAAC,GAED,MAAM,GAAG,OAAO,EAAC,iBAAiB,GAAK,CAAC,GACxC,eAAe,MAAM;GACvB,SAASC,IAAO;IAAP,IAAA,QAAA;IAEP,AADA,eAAe,OAAO,GACtB,eAAe,KAAK;GACtB;EAhBwB;CAiB1B,GAde,EAAA,MAAA,QALR,EAAA,MAAA;CADP,IAAe,gBAAfD,IAsBAE;CAMe,AAAA,EAAA,QAAA,UAAA,EAAA,QALR,iBADP,KAAA,eAAe,gBAAgB;EAC7B,IAAK,eAEL;kBAAe,SAAS;GAExB,IAAI;IACF,IAAMC,OAAK,OAAO,YAAY;IAe9B,AAbA,cAAc,SAAS,cAAY;KAGjC,AACEC,UAAQ,YACRA,UAAQ,YACR,0BAA0BA,UAAQ,cAAcA,UAAQ,SAAS,EAAE,KAEnE,KAAG,MAAMA,UAAQ,UAAU,KAAK,EAAC,KAAK,EAAC,UAAUA,UAAQ,SAAQ,EAAC,CAAC;IAEvE,CAAC,GAED,MAAMD,KAAG,OAAO,EAAC,iBAAiB,GAAK,CAAC,GACxC,eAAe,MAAM;GACvB,SAASF,IAAO;IAAP,IAAA,UAAA;IAEP,AADA,eAAe,OAAO,GACtB,eAAeA,OAAK;GACtB;EAtBwB;CAuB1B,GApBe,EAAA,MAAA,QALR,EAAA,MAAA;CADP,IAAe,gBAAfC,IA4BAG;CAMe,AAAA,EAAA,QAAA,UAAA,EAAA,QALR,iBADP,KAAA,eAAe,eAAe;EAC5B,IAAK,eAEL;kBAAe,SAAS;GAExB,IAAI;IACF,IAAMF,OAAK,OAAO,YAAY;IAkB9B,AAhBA,cAAc,SAAS,cAAY;KACjC,IAAI,CAACC,UAAQ,UAAU;KAEvB,IAAM,eAAe,iBAAiBA,UAAQ,QAAQ;KAGtD,KAAG,MAAMA,UAAQ,UAAU,KAAK,EAC9B,KAAK;MACH,UAAUA,UAAQ,YAAYA,UAAQ,gBAAgB;MACtD,QAAQA,UAAQ,SAAS;MACzB,MAAM;KACR,EACF,CAAC;IACH,CAAC,GAED,MAAMD,KAAG,OAAO,EAAC,iBAAiB,GAAK,CAAC,GACxC,eAAe,MAAM;GACvB,SAASF,IAAO;IAAP,IAAA,UAAA;IAEP,AADA,eAAe,OAAO,GACtB,eAAeA,OAAK;GACtB;EAzBwB;CA0B1B,GAvBe,EAAA,MAAA,QALR,EAAA,MAAA;CADP,IAAe,eAAfI,IA+BOC;CAAP,OAEE,EAAA,QAAA,eAAA,EAAA,QACA,cAAA,EAAA,QAGA,cAAA,EAAA,QAIA,iBAAA,EAAA,QACA,aAAA,EAAA,QACA,cAAA,EAAA,QAPA,eAAA,EAAA,QADA,eAAA,EAAA,QAHA,uBAAA,EAAA,QAMA,iBAAA,EAAA,QAEA,gBAAA,EAAA,QADA,iBARK,KAAA;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,GAXE,EAAA,MAAA,aACA,EAAA,MAAA,YAGA,EAAA,MAAA,YAIA,EAAA,MAAA,eACA,EAAA,MAAA,WACA,EAAA,MAAA,YAPA,EAAA,MAAA,aADA,EAAA,MAAA,aAHA,EAAA,MAAA,qBAMA,EAAA,MAAA,eAEA,EAAA,MAAA,cADA,EAAA,MAAA,yCARKA;AAcT;AAEA,MAAM,kBAAkB,iCACrB,kBACQ,cAAc,YACR,kCACX,CAAC,GACD,EACE,YAAY,mBACd,CACF,CAEJ;AC3IA,SAAS,WAAA,IAQW;gBARA,EAClB,IACA,UACA,UACA,OACA,OACA,aACA,aAPkBG,IAeR,KAAA,WAAW,YAAY,WAEnB,KAAA,WAAW,gBAAgB,WAC1B,KAAA,WAAW,KAAM,GAFrBC;CACGC,AAAAA,EAAAA,OAAAA,MAAAA,EAAAA,OACCC,MAFJ,KAAA;EACL,QAAQD;EACR,SAASC;CACX,GAFUD,EAAAA,KAAAA,IACCC,EAAAA,KAAAA;CAOKC,IAAAA;CAAe,AAAA,EAAA,OAAA,MAAA,EAAA,OAAT,YAAN,WAAM,SAAS,EAAE,GAAF,EAAA,KAAA,IAAT,EAAA,KAAA;CAHpBC,IAAAA;CAIc,AAAA,EAAA,OAAA,YAAA,EAAA,OAFD,YAAA,EAAA,OACCD,MAHd,KAAA,oBAAC,KAAD;EAAK,YAAY;EACf,UAAA,oBAAC,OAAD;GACE,SAAS;GACT,UAAUA;GACA;GACV,MAAK;EACN,CAAA;CACE,CAAA,GAHS,EAAA,KAAA,UAFD,EAAA,KAAA,UACCA,EAAAA,KAAAA;CAMZE,IAAAA;CAEc,AAAA,EAAA,QAAA,SAAA,EAAA,QAAT,SAFL,KAAA,oBAAC,MAAD;EAAM,OAAM;EAAS,KAAK;EACxB,UAAA,qBAAC,MAAD;GAAM,MAAM;GAAG,QAAO;GAAtB,UAAA;IACG;IAAM;IAAG;IAAM;GACZ;;CACF,CAAA,GAFQ,EAAA,MAAA,OAAT,EAAA,MAAA;CAGLC,IAAAA;CACG,AAAA,EAAA,QAAA,4BADH,KAAA,oBAAC,MAAD;EAAM,MAAM;EAAG,OAAA;EACZ,UAAA;CACG,CAAA,GADH,EAAA,MAAA;CAPLC,IAAAA;CACEF,AAAAA,EAAAA,QAAAA,MAAAA,EAAAA,QAKAC,MANF,KAAA,qBAAC,OAAD;EAAO,KAAK;EAAG,MAAM;EAArB,UAAA,CACED,IAKAC,EAGK;KARLD,EAAAA,MAAAA,IAKAC,EAAAA,MAAAA;CAfJE,IAAAA;CACEJ,AAAAA,EAAAA,QAAAA,MAAAA,EAAAA,QAQAG,MATF,MAAA,qBAAC,MAAD;EAAM,KAAK;EAAG,OAAM;EAApB,UAAA,CACEH,IAQAG,EAUI;KAlBJH,EAAAA,MAAAA,IAQAG,EAAAA,MAAAA;CApBJE,IAAAA;CADF,OAMUC,EAAAA,QAAAA,MAAAA,EAAAA,QAMNF,OAAAA,EAAAA,QALOR,MANT,MAAA,oBAAC,MAAD;EACE,IAAG;EACH,SAAS;EACT,QAAQ;EACR,QAAA;EACA,MAAMU;EACN,OAAOV;EAKPQ,UAAAA;CAoBI,CAAA,GA1BEE,EAAAA,MAAAA,IAMNF,EAAAA,MAAAA,KALOR,EAAAA,MAAAA,gCANTS;AAiCJ;AAEA,SAAS,qBAAqB,OAAgD;gBACtE,EAAC,gBAAe,OAECE;CAAMC,AAAAA,EAAAA,OAAAA,MAAAA,6BAAN,KAAA,MAAM,eAAe,OAAOC,OAAiB,CAAC,CAAC,UAAU,GAAnDD,EAAAA,KAAAA,MAAAA;CAA7B,IAAM,iBAAiBD,IAErBG;CAAMF,AAAAA,EAAAA,OAAAA,MAAAA,6BAAN,KAAA,MAAM,eAAe,OACnBG,QACF,CAAC,CAAC,UAAU,GAFNH,EAAAA,KAAAA,MAAAA;CADR,IAAM,+BACJE,IAII,iBAAiB,+BAA+B,GAEhD,CAAC,gBAAgB,qBAAqB,SADV,iBAAiB,cAAc,YACa,GAExE,mBAAmB,gBAAgB,UAAU,gBAAgB,SAC7D,cAAc,gBAAgB,WAC9B,SAAS,gBAAgB,QACzB,YAAY,MAAM,UAAU,WAAW,MAAM,qBAEhCE;CAGR,AAAA,EAAA,OAAA,SAAA,EAAA,OAFD,kBADS,WAAM;EACvB,MAAA,QAAQ,gBAAR;GACE,KAAK;IACE,MAAM,cAAc;IACzB,MAAA;GACF,KAAK;IACE,MAAM,cAAc;IACzB,MAAA;GACF,KAAK;IACE,MAAM,aAAa;IACxB,MAAA;EAGJ;CACF,GAXW,EAAA,KAAA,OAFD,EAAA,KAAA;CADV,IAAM,aAAaA,IA2BbC;CAmBmB,AAAA,EAAA,OAAA,oBAAA,EAAA,OAFF,cAAA,EAAA,OAjBhB,UAAA,EAAA,QAmBsC,aAAA,EAAA,QAVrB,eAAA,EAAA,QADKC,MAAAA,eARvB,KAAA,CAAC,UACC,oBAAC,MAAD;EAAM,SAAS;EACb,UAAA,qBAAC,MAAD;GAAM,SAAQ;GAAW,KAAK;GAA9B,UAAA,CACE,oBAAC,QAAD;IACE,UAAU;IACV,SAAS;IACT,MAAK;IACL,MAAK;IACL,SAAS,MAAM;IACf,UAAU;GACX,CAAA,GACD,oBAAC,QAAD;IACE,MAAM;IACN,UAAU;IACV,SAAS;IACT,MAAK;IACL,MAAK;IACL,SAAS;IACT,WAAW,eAAe;IAC1B,UAAU,CAAC,oBAAoB;GAChC,CAAA,CACG;;CACF,CAAA,GAHW,EAAA,KAAA,kBAFF,EAAA,KAAA,YAjBhB,EAAA,KAAA,QAmBsC,EAAA,MAAA,WAVrB,EAAA,MAAA,aADKA,EAAAA,MAAAA,MAAAA;CAoBtBC,IAAAA;qCACC,KAAA,aAAA,oBAAC,MAAD;EAAM,MAAK;EAAU,cAAc;EAAG,SAAS;EAAG,QAAA;EAAO,QAAQ;EAC/D,UAAA,qBAAC,MAAD;GAAM,OAAM;GAAS,KAAK;GAA1B,UAAA,CACE,oBAAC,SAAD;IAAS,OAAA;IAAM,MAAM;GAAI,CAAA,GACzB,qBAAC,OAAD;IAAO,KAAK;IAAZ,UAAA,CACE,oBAAC,MAAD;KAAM,MAAM;KAAG,QAAO;KACpB,UAAA;IACI,CAAA,GACN,oBAAC,MAAD;KAAM,MAAM;KAAG,OAAA;KACb,UAAA;IACI,CAAA,CACD;GACH,CAAA,CAAA;;CACF,CAAA,GAbP,EAAA,MAAA;CAiBAC,IAAAA;CAAgBC,AAAAA,EAAAA,QAAAA,MAAV,UAAU,sBAAhB,KAAA,MAAM,UAAU,SACf,oBAAC,MAAD;EAAM,MAAK;EAAW,cAAc;EAAG,SAAS;EAAG,QAAA;EAAO,QAAQ;EAChE,UAAA,qBAAC,MAAD;GAAM,OAAM;GAAS,KAAK;GAA1B,UAAA,CACE,oBAAC,kBAAD,EAAkB,UAAU,GAAK,CAAA,GACjC,qBAAC,OAAD;IAAO,KAAK;IAAZ,UAAA,CACE,oBAAC,MAAD;KAAM,MAAM;KAAG,QAAO;KACpB,UAAA;IACI,CAAA,GACN,oBAAC,MAAD;KAAM,MAAM;KAAG,UAAA;IAAuD,CAAA,CACjE;GACH,CAAA,CAAA;;CACF,CAAA,GAXSA,EAAAA,MAAAA,MAAV,UAAU;CAehBC,IAAAA;uCAAgB,KAAA,gBAAA,aACf,oBAAC,MAAD;EAAM,MAAK;EAAU,cAAc;EAAG,SAAS;EAAG,QAAA;EAAO,QAAQ;EAC/D,UAAA,qBAAC,MAAD;GAAM,OAAM;GAAS,KAAK;GAA1B,UAAA,CACE,oBAAC,SAAD;IAAS,OAAA;IAAM,MAAM;GAAI,CAAA,GACzB,qBAAC,OAAD;IAAO,KAAK;IAAZ,UAAA,CACE,oBAAC,MAAD;KAAM,MAAM;KAAG,QAAO;KACpB,UAAA;IACI,CAAA,GACN,oBAAC,MAAD;KAAM,MAAM;KAAG,OAAA;KACb,UAAA;IACI,CAAA,CACD;GACH,CAAA,CAAA;;CACF,CAAA,GAbP,EAAA,MAAA;CAiBAC,IAAAA;CASgBC,AAAAA,EAAAA,QAAAA,MAAAA,eAAAA,EAAAA,QAThB,eAAgB,KAAA,gBAAA,WACf,oBAAC,MAAD;EAAM,MAAK;EAAW,cAAc;EAAG,SAAS;EAAG,QAAA;EAAO,QAAQ;EAChE,UAAA,qBAAC,MAAD;GAAM,OAAM;GAAS,KAAK;GAA1B,UAAA,CACE,oBAAC,kBAAD,EAAkB,UAAU,GAAK,CAAA,GACjC,qBAAC,OAAD;IAAO,KAAK;IAAZ,UAAA,CACE,oBAAC,MAAD;KAAM,MAAM;KAAG,QAAO;KACpB,UAAA;IACI,CAAA,GACN,oBAAC,MAAD;KAAM,MAAM;KACT,UAAA,MAAM,cACH,UAAU,MAAM,gBAChB;IACA,CAAA,CACD;GACH,CAAA,CAAA;;CACF,CAAA,GANSA,EAAAA,MAAAA,MAAAA,aAThB,EAAA,MAAA;CAmBAC,IAAAA;uCAAgB,KAAA,gBAAA,UACf,qBAAC,OAAD;EAAO,UAAU;EAAG,KAAK;EAAG,OAAO,EAAC,WAAW,SAAQ;EAAvD,UAAA;GACE,oBAAC,KAAD,EAAA,UACE,oBAAC,qBAAD,EAAqB,UAAU,GAAK,CAAA,EACjC,CAAA;GACL,oBAAC,SAAD;IAAS,MAAM;IAAG,UAAA;GAAuB,CAAA;GACzC,oBAAC,MAAD;IAAM,MAAM;IAAG,OAAA;IACb,UAAA;GACI,CAAA;EACD;KATR,EAAA,MAAA;CAaAC,IAAAA;CAOM,AAAA,EAAA,QAAA,kBAAA,EAAA,QAPL,UAAA,EAAA,QAAW,aAAA,EAAA,QAeO,eAAA,EAAA,QAfuBL,MAAV,UAAU,SAAA,EAAA,QAUvB,kBAAA,EAAA,QAPe,kBAAA,EAAA,QAUlB,gCAbhB,KAAA,CAAC,UAAU,CAAC,aAAa,CAAC,MAAM,UAAU,SACzC,qBAAC,OAAD;EAAO,KAAK;EAAZ,UAAA,CACE,qBAAC,MAAD;GAAM,MAAM;GAAG,OAAA;GAAf,UAAA;IACE;IAAO;IAAe;IAAO,mBAAmB,IAAI,KAAK;IAAI;GACzD;EAEN,CAAA,GAAA,qBAAC,OAAD;GAAO,KAAK;GAAZ,UAAA;IACG,kBACC,oBAAC,YAAD;KACE,IAAG;KACH,UAAU,mBAAmB;KAC7B,UAAU;KACV,OAAM;KACN,OAAO;KACP,aAAY;KACZ,UAAU;IACX,CAAA;IAGH,oBAAC,YAAD;KACE,IAAG;KACH,UAAU,mBAAmB;KAC7B,UAAU;KACV,OAAM;KACN,OAAO;KACP,aAAY;KACZ,UAAU;IACX,CAAA;IAED,oBAAC,YAAD;KACE,IAAG;KACH,UAAU,mBAAmB;KAC7B,UAAU;KACV,OAAM;KACN,OAAO;KACP,aAAY;KACZ,UAAU;IACX,CAAA;GACI;EACF,CAAA,CAAA;KAhCF,EAAA,MAAA,gBAPL,EAAA,MAAA,QAAW,EAAA,MAAA,WAeO,EAAA,MAAA,aAfuBA,EAAAA,MAAAA,MAAV,UAAU,OAUvB,EAAA,MAAA,gBAPe,EAAA,MAAA,gBAUlB,EAAA,MAAA;CAhGnBM,IAAAA;CAEGR,AAAAA,EAAAA,QAAAA,MAAAA,EAAAA,QAiBAC,MAAAA,EAAAA,QAeAE,MAAAA,EAAAA,QAiBAC,MAAAA,EAAAA,QAmBAE,MAAAA,EAAAA,QAaAC,MAnFH,MAAA,qBAAC,KAAD;EAAK,SAAS;EAAd,UAAA;GAEGP;GAiBAC;GAeAE;GAiBAC;GAmBAE;GAaAC;EAyCE;KA1HFP,EAAAA,MAAAA,IAiBAC,EAAAA,MAAAA,IAeAE,EAAAA,MAAAA,IAiBAC,EAAAA,MAAAA,IAmBAE,EAAAA,MAAAA,IAaAC,EAAAA,MAAAA;CAvHLE,IAAAA;CADF,OAMmBV,EAAAA,QAAAA,MAAAA,eAAAA,EAAAA,QA+BfS,OAAAA,EAAAA,QA1BEV,MAVJ,MAAA,oBAAC,QAAD;EACE,SAAA;EACA,QAAO;EACP,SAAS;EACT,IAAG;EACH,SAAS,MAAM;EACf,gBAAgB,MAAM;EACtB,OAAO;EACP,UAAS;EACT,QACEA;EA0BFU,UAAAA;CA6HM,CAAA,GA5JST,EAAAA,MAAAA,MAAAA,aA+BfS,EAAAA,MAAAA,KA1BEV,EAAAA,MAAAA,gCAVJW;AAmKJ;AAhMM,SAAAO,SAAC,KAAA;CAAMN,OAAAA,IAAE,YAAYA,IAAE,YAAY,0BAA0BA,IAAE,cAAcA,IAAE,SAAS,EAAE;;AAH3C,SAAAK,QAAC,GAAA;CAAM,OAAA,EAAE;;AAqM9D,SAAwB,iBAAiB;eACjC,iBAAiB,qBAAqB;CAE5C,IAAI,CAAC,eAAe,YAClB;CAGF,IAAI,eAAe,YAAY;EACtBJ,IAAAA;EAAP,OAAiC,EAAA,OAAA,8BAA1B,KAAA,oBAAC,sBAAD,EAAsB,GAAI,eAAiB,CAAA,GAAjB,EAAA,KAAA,4BAA1BA;CACT;CAEOC,IAAAA;CAAP,OAAyEC,EAAAA,OAAAA,eAAAA,0BAAlE,KAAA,oBAAC,QAAD;EAAQ,MAAK;EAAQ,MAAK;EAAgB,SAAS,eAAe;CAAa,CAAA,GAAbA,EAAAA,KAAAA,eAAAA,wBAAlED;AACT;AC/QA,MAAM,6BAA2C;CAC/C,eAAe;CACf,WAAW;CACX,QAAQ;CACR,OAAO;AACT;;;;;AAMA,SAAgB,kBAAkB,OAA6D;eACvF,KAAK,MAAM,GAKXK;qDAAC,KAAA,oBAAA,QAAD;EAAQ,MAAK;EAAO,MAAM;EAAU,MAAK;EAAQ,SAAS;EAAG,OAAO,EAAC,QAAQ,UAAS;CAAI,CAAA;CAKvFC,IAAAA;qDAAO,KAAA,OAAA,QAAQ,kBAAkB;CADpCC,IAAAA;CAKqB,AAAA,EAAA,OAAA,qBALrB,KAAA,oBAAC,MAAD,EAAA,UACGD,GAAmC,KAAA,OAAK;EAAC,IAAA,CAAA,MAAME,MAAPC,IAAO,EAAC,UAADD;EAC9C,OAAA,oBAAC,UAAD;GAEE,WAAQ;GACR,eAAe,MAAM,QAAQ,IAAkB;GAC/C,SAAS;GACT,MAAK;GACL,MAAM;GACN,SAAS,SAAS,MAAM;EACzB,GAPM,IAON;CAToD,CAUtD,EACG,CAAA,GAPe,EAAA,KAAA;CAXzBE,IAAAA;CADF,OAKQ,EAAA,OAAA,MAAA,EAAA,OAEFH,MANJ,KAAA,oBAAC,YAAD;EACE,QACEF;EAEE;EACJ,MACEE;EAcF,SAAS;CACV,CAAA,GAjBK,EAAA,KAAA,IAEFA,EAAAA,KAAAA,4BANJG;AAuBJ;AC5CA,MAAM,mBAAA;eACJE;CAAAA,2DAAC,KAAA,oBAAA,KAAD;EACE,OAAO;GACL,SAAS;GACT,YAAY;GACZ,gBAAgB;GAChB,WAAW;EACb;EAEA,UAAA,oBAAC,SAAD,CAAU,CAAA;CACP,CAAA,2BATLA;GCDI,YAKA,UAAU;gBACR,OAAO,MAAM,MAGH,MAAC,MAAM,QAAQ,KAAK,GAC9BE;CAAC,AAAA,EAAA,OAAA,oBAAD,KAAA,oBAAC,MAAD,CAAO,CAAA,GAAN,EAAA,KAAA;CADHC,IAAAA;CAAYC,AAAAA,EAAAA,OAAAA,MAAAA,EAAAA,OACVF,MADF,KAAA,oBAAC,MAAD;EAAM,MAAME;EAAuB,OAAA;EACjCF,UAAAA;CACI,CAAA,GAFME,EAAAA,KAAAA,IACVF,EAAAA,KAAAA;CAEU,IAAA,KAAA,MAAM,QAAQ,GAA1BG;CAA0CC,AAAAA,EAAAA,OAAAA,MAAAA,SAAAA,EAAAA,OACjCC,MAAAA,QAAAA,EAAAA,OADGC,MAAZ,KAAA,oBAAC,MAAD;EAAM,MAAMA;EAAiB,OAAO,MAAM;EACvC,UAAA,MAAM;CACH,CAAA,GAFoCF,EAAAA,KAAAA,MAAAA,OACjCC,EAAAA,KAAAA,MAAAA,MADGC,EAAAA,KAAAA;CAJdC,IAAAA;CADF,OAEIN,EAAAA,OAAAA,MAAAA,EAAAA,QAGAE,MAJF,KAAA,qBAAC,MAAD;EAAM,KAAK;EAAG,OAAM;EAAS,SAAS;EAAtC,UAAA,CACEF,IAGAE,EAGI;KANJF,EAAAA,KAAAA,IAGAE,EAAAA,MAAAA,8BAJFI;AASJ;ACjBA,SAAgB,eAAe,OAAgC;eAGzDE;qDAAC,KAAA,oBAAA,QAAD;EACE,MAAK;EACL,GAAE;CACH,CAAA;CAJHC,IAAAA;CADF,OAC2F,EAAA,OAAA,qBAAzF,KAAA,oBAAC,OAAD;EAAK,OAAM;EAA6B,OAAM;EAAM,QAAO;EAAM,SAAQ;EAAY,GAAI;EACvFD,UAAAA;CAIG,CAAA,GALoF,EAAA,KAAA,mBAAzFC;AAOJ;ACTA,SAAgB,cAAc,OAAgC;eASxDE,IACAC,IAIAC;qDALA,KAAA,oBAAC,QAAD;EAAM,GAAE;EAAmC,MAAK;CAAgB,CAAA,GAChE,KAAA,oBAAC,QAAD;EACE,GAAE;EACF,MAAK;CACN,CAAA,GACD,KAAA,oBAAC,QAAD;EAAM,GAAE;EAAsB,MAAK;CAAgB,CAAA;CAZrDC,IAAAA;CADF,OAMQ,EAAA,OAAA,qBALN,KAAA,qBAAC,OAAD;EACE,OAAM;EACN,OAAM;EACN,QAAO;EACP,SAAQ;EACR,GAAI;EALN,UAAA;GAOEH;GACAC;GAIAC;EACG;KARC,EAAA,KAAA,mBALNC;AAeJ;;ACqBA,SAAgB,mBACd,OACgD;CAChD,IAAM,SAAS,MAAM,MAAM;CAI3B,OAHI,QAAQ,WAAW,cAAoB,cACvC,QAAQ,WAAW,WAAW,OAAO,MAAY,UACjD,QAAQ,WAAW,YAAkB,YAClC;AACT;;;;;;;;;;;AAYA,SAAgB,aAAa,OAA+C;CAC1E,IAAM,SAASE,YAAU,GACnB,QAAQ,SAAS,GAEjB,SAAS,MAAM,MAAM,QACrB,CAAC,MAAM,WAAW,SAAS,EAAK,GAChC,CAAC,SAAS,cAAc,SAAS,EAAK,GAGtC,CAAC,aAAa,kBAAkB,SAAS,MAAM,OAAO;CAC5D,AAAI,gBAAgB,MAAM,YACxB,eAAe,MAAM,OAAO,GAC5B,WAAW,EAAK;CAGlB,IAAM,aAAa,cACX,MAAM,MAAM,uBAAuB,MAAM,MAAM,yBAAyB,KAAA,GAC9E,CAAC,MAAM,MAAM,qBAAqB,MAAM,MAAM,qBAAqB,CACrE,GAEM,SAA0B,mBAAmB,KAAK,GAGlD,UAAU,YACd,OAAO,SAAmB;EACxB,AAAK,MAAM,OACX,MAAM,OACH,MAAM,MAAM,GAAG,CAAC,CAChB,IAAI;GAAC,QAAQ,KAAK;GAAQ,MAAM,iBAAiB,IAAI;EAAC,CAAC,CAAC,CACxD,OAAO,EAAC,iBAAiB,GAAK,CAAC;CACpC,GACA,CAAC,MAAM,KAAK,MAAM,CACpB,GAGM,UAAU,YAAY,YAA2C;EACrE,IAAI,CAAC,MAAM,WAAW,CAAC,MAAM,KAAK;EAClC,IAAM,EAAC,SAAQ,MAAM,SAAS,QAAQ,MAAM,OAAO;EAEnD,OADA,MAAM,QAAQ,IAAI,GACX;CACT,GAAG;EAAC,MAAM;EAAS,MAAM;EAAK;EAAQ;CAAO,CAAC;CAqF9C,OAlFA,gBAAgB;EACd,IAAI,QAAQ,WAAW,eAAe,CAAC,MAAM,WAAW,CAAC,MAAM,KAAK;EAEpE,IAAI,YAAY,IACZ,UAAU,IACR,WAAW,YAAY,YAAY;GAGvC,IAAI,UACJ;cAAU;IACV,IAAI;KACF,IAAM,OAAO,MAAM,QAAQ;KAC3B,IAAI,WAAW;KACf,CAAI,CAAC,QAAQ,KAAK,QAAQ,WAAW,gBACnC,cAAc,QAAQ;IAE1B,SAAS,OAAO;KACd,QAAQ,MAAM,oCAAoC,KAAK;IAEzD,UAAU;KACR,UAAU;IACZ;GAZU;EAaZ,GAAG,GAAgB;EAEnB,aAAa;GAEX,AADA,YAAY,IACZ,cAAc,QAAQ;EACxB;CACF,GAAG;EAAC,QAAQ;EAAQ,MAAM;EAAS,MAAM;EAAK;CAAO,CAAC,GAsD/C;EAAC;EAAQ;EAAM;EAAS;EAAY,QApD5B,YAAY,YAAY;GACrC,IAAK,MAAM,WAAY,MAAM,KAE7B;IACA,AADA,QAAQ,EAAI,GACZ,WAAW,EAAK;IAChB,IAAI;KACF,IAAM,EAAC,SAAQ,MAAM,mBAAmB,QAAQ,MAAM,SAAS,WAAW;KAI1E,MAAM,QAAQ,IAAI;IACpB,SAAS,OAAO;KACd,MAAM,KAAK;MACT,QAAQ;MACR,OAAO;MACP,aAAa,iBAAiB,QAAQ,MAAM,UAAU;KACxD,CAAC;IAEH,UAAU;KACR,QAAQ,EAAK;IACf;GAjBY;EAkBd,GAAG;GAAC,MAAM;GAAS,MAAM;GAAK;GAAQ;GAAS;EAAK,CA+BT;EAAQ,UA7BlC,YAAY,YAAY;GACvC,IAAK,MAAM,SAEX;YAAQ,EAAI;IACZ,IAAI;KAGF,IAAM,OAAO,MAAM,QAAQ,GACrB,MAAM,MAAM,QAAQ,WAAW,UAAU,KAAK,OAAO,MAAM,KAAA;KAEjE,AAAI,OACF,WAAW,EAAK,GAChB,yBAAyB,GAAG,KAG5B,WAAW,EAAI;IAEnB,SAAS,OAAO;KACd,MAAM,KAAK;MACT,QAAQ;MACR,OAAO;MACP,aAAa,iBAAiB,QAAQ,MAAM,UAAU;KACxD,CAAC;IAEH,UAAU;KACR,QAAQ,EAAK;IACf;GAvBY;EAwBd,GAAG;GAAC,MAAM;GAAS;GAAS;EAAK,CAEkB;CAAQ;AAC7D;;;;;;AAOA,SAAS,yBAAyB,WAAyB;CACzD,IAAI,OAAO,SAAW,KAAa;CAEnC,IAAM,SAAS,SAAS,cAAc,GAAG;CAMzC,AALA,OAAO,OAAO,WACd,OAAO,SAAS,UAChB,OAAO,MAAM,uBACb,SAAS,KAAK,YAAY,MAAM,GAChC,OAAO,MAAM,GACb,SAAS,KAAK,YAAY,MAAM;AAClC;;ACxMA,SAAwB,uBAAuB;eAE3CC;CADF,2DACG,KAAA,qBAAA,OAAD;EAAO,KAAK;EAAZ,UAAA,CACE,oBAAC,MAAD;GAAM,MAAM;GAAG,OAAA;GACb,UAAA;EAGI,CAAA,GACN,oBAAC,MAAD;GAAM,MAAM;GAAG,OAAA;GACb,UAAA;EAGI,CAAA,CACD;6BAXPA;AAaJ;;;;;ACGA,SAAwB,UAAA,IAAkD;gBAAxC,EAAC,OAAO,iBAAA,OAARE,IAAQ,kBAAA,OAAA,KAAA,KAAAC,IAClC,EAAC,QAAQ,MAAM,SAAS,YAAY,QAAQ,aAAY,aAAa,KAAK,GAE1E,aAAa,MAAM,WAAW,WAAW,MAAM,MAAM,WAAW,SAIhE,UAAU,WAAW,WAAW,CAAC,SACjC,cAAc,WAAW,aACzB,kBAAkB,CAAC,WAAW,CAAC,aAM7BC;qDAAC,KAAA,oBAAA,OAAD;EAAO,OAAA;EAAM,MAAM;EACjB,UAAA;CACK,CAAA;CAHTC,IAAAA;qDAAC,KAAA,qBAAA,MAAD;EAAM,OAAM;EAAS,SAAQ;EAAgB,KAAK;EAAlD,UAAA,CACED,IAGA,oBAAC,MAAD;GAAM,MAAM;GACV,UAAA,oBAAC,KAAD;IAAG,MAAM;IAA0B,QAAO;IAAS,KAAI;IACrD,UAAA;GACC,CAAA;EACC,CAAA,CACF;;CAGkB,IAAA,KAAA,CAAC,SAAvBE;CAAsBC,AAAAA,EAAAA,OAAAA,kBAAtB,KAAA,oBAAC,MAAD;EAAM,MAAM;EAAG,OAAOA;EACpB,UAAA;CACI,CAAA,GAFgBA,EAAAA,KAAAA;CAGrBC,IAAAA;oCACC,KAAA,cAAA,oBAAC,MAAD;EAAM,MAAM;EAAG,OAAA;EACZ,UAAA;CACG,CAAA,GAHP,EAAA,KAAA;CAJHC,IAAAA;CACEH,AAAAA,EAAAA,OAAAA,MAAAA,EAAAA,OAGCE,MAJH,KAAA,qBAAC,OAAD;EAAO,KAAK;EAAZ,UAAA,CACEF,IAGCE,EAKI;KARLF,EAAAA,KAAAA,IAGCE,EAAAA,KAAAA;CAOFE,IAAAA;CAAmB,AAAA,EAAA,OAAA,mBAAA,EAAA,QAAnB,mBAAmB,KAAA,mBAAA,mBAAmB,oBAAC,sBAAD,CAAuB,CAAA,GAA1C,EAAA,KAAA,iBAAnB,EAAA,MAAA;CAEAC,IAAAA;CAAoB,AAAA,EAAA,QAAA,WAAA,EAAA,QAApB,mBAAA,EAAA,QAA+B,UAA/B,KAAA,oBAAoB,WAAW,WAAW,cACzC,qBAAC,OAAD;EAAO,KAAK;EAAZ,UAAA,CACG,WACC,oBAAC,MAAD;GAAM,MAAM;GAAG,OAAA;GACb,UAAA;EACI,CAAA,GAEP,WAAW,aACV,oBAAC,MAAD;GAAM,MAAM;GAAG,OAAO,EAAC,OAAO,6BAA4B;GACxD,UAAA;EACI,CAAA,CAEH;KAZY,EAAA,MAAA,SAApB,EAAA,MAAA,iBAA+B,EAAA,MAAA;CAe/BC,IAAAA;wCACC,MAAA,eAAA,oBAAC,MAAD;EAAM,MAAM;EAAG,OAAA;EACb,UAAA;CAEI,CAAA,GAJP,EAAA,MAAA;CAOAC,IAAAA;oCACC,MAAA,WAAA,oBAAC,MAAD;EAAM,MAAM;EAAG,OAAA;EACb,UAAA;CACI,CAAA,GAHP,EAAA,MAAA;CAMDC,IAAAA;CA0ByB,AAAA,EAAA,QAAA,cAAA,EAAA,QAXV,QAAA,EAAA,QAEW,YAAA,EAAA,QAUA,UAAA,EAAA,QA1BvB,eAAA,EAAA,QAOG,WAAA,EAAA,QAaM,UArBZ,MAAA,oBAAC,MAAD;EAAM,SAAQ;EAAW,KAAK;EAC3B,UAAA,cACC,qBAAC,MAAD;GAAM,OAAM;GAAS,KAAK;GAA1B,UAAA,CACE,oBAAC,SAAD;IAAS,OAAA;IAAM,MAAM;GAAI,CAAA,GACzB,oBAAC,MAAD;IAAM,MAAM;IAAG,OAAA;IACb,UAAA;GACI,CAAA,CACF;EACJ,CAAA,IAAA,UACF,oBAAC,QAAD;GACE,MAAM;GACN,MAAK;GACL,MAAK;GACL,UAAU;GACV,SAAS;GACT,SAAS;GACT,UAAU;GACV,eAAe,KAAK,SAAS;EAC9B,CAAA,IAED,oBAAC,QAAD;GACE,MAAM,WAAW,YAAY,cAAc;GAC3C,MAAK;GACL,UAAU;GACV,SAAS;GACT,SAAS;GACT,UAAU,QAAQ,CAAC;GACnB,eAAe,KAAK,OAAO;EAC5B,CAAA;CAEC,CAAA,GAJmB,EAAA,MAAA,YAXV,EAAA,MAAA,MAEW,EAAA,MAAA,UAUA,EAAA,MAAA,QA1BvB,EAAA,MAAA,aAOG,EAAA,MAAA,SAaM,EAAA,MAAA;CA3EhBC,IAAAA;CADF,OA0COH,EAAAA,QAAAA,OAAAA,EAAAA,QAOAC,OAAAA,EAAAA,QAMDC,OAAAA,EAAAA,QAzCAL,MAAAA,EAAAA,QAWCC,MAAAA,EAAAA,QAEAC,MA1BL,MAAA,oBAAC,MAAD;EAAM,SAAS;EAAG,QAAQ;EAAG,MAAK;EAAc,QAAA;EAC9C,UAAA,qBAAC,OAAD;GAAO,KAAK;GAAZ,UAAA;IACEN;IAWAI;IAWCC;IAEAC;IAeAC;IAOAC;IAMDC;GA+BK;;CACH,CAAA,GA7CDF,EAAAA,MAAAA,KAOAC,EAAAA,MAAAA,KAMDC,EAAAA,MAAAA,KAzCAL,EAAAA,MAAAA,IAWCC,EAAAA,MAAAA,IAEAC,EAAAA,MAAAA,gCA1BLI;AAwFJ;AClGA,SAAgB,eAAe,SAAuD;gBAC9E,SAASS,YAAU,GACnB,QAAQ,SAAS,GACjB,CAAC,aAAa,kBAAkB,SAA2B,MAAM,GACjE,CAAC,aAAa,kBAAkB,SAAkB,IAAI,GAEtD,YAAY,SAAS,aAAa,IAGtCP;CA6BoC,AAAA,EAAA,OAAA,UAAA,EAAA,OApBhCC,WAAAA,EAAAA,OAPI,aAAA,EAAA,OACF,SAHN,KAAA,OAAO,UAA8B;EACnC,IAAI,CAAC,MAAM,SAQT,AAPI,aACF,MAAM,KAAK;GACT,OAAO;GACP,aAAa;GACb,QAAQ;EACV,CAAC,GAEH,SAAS,UAAU,gBAAI,MAAM,qBAAqB,CAAC;OAIrD,IAAI,CAAC,MAAM,KAQT,AAPI,aACF,MAAM,KAAK;GACT,OAAO;GACP,aAAa;GACb,QAAQ;EACV,CAAC,GAEH,SAAS,UAAU,gBAAI,MAAM,0BAA0B,CAAC;OAI1D;GACA,AADA,eAAe,SAAS,GACxB,eAAe,IAAI;GAEnB,IAAI;IAEF,IAAM,WAAU,MADO,SAAS,QAAQ,MAAM,OAAO,EAAA,CAC5B,MACnB,eAAe,iBAAiB,OAAO;IAqB7C,OAnBA,MAAM,OACH,MAAM,MAAM,GAAG,CAAC,CAChB,IAAI;KACH,QAAQ,QAAQ;KAChB,MAAM;KACN,GAAI,QAAQ,MAAM,SAAS,EAAC,UAAU,QAAQ,KAAK,MAAK;IAC1D,CAAC,CAAC,CACD,OAAO,EAAC,iBAAiB,GAAK,CAAC,GAElC,eAAe,SAAS,GACpB,aACF,MAAM,KAAK;KACT,OAAO;KACP,aAAa;KACb,QAAQ;IACV,CAAC,GAGH,SAAS,YAAY,OAAO,GACrB;GACT,SAASC,IAAO;IAAP,IAAA,QAAA;IAWP,AAVA,eAAe,OAAO,GACtB,eAAe,KAAK,GACpB,QAAQ,MAAM,iCAAiC,KAAK,GAChD,aACF,MAAM,KAAK;KACT,OAAO;KACP,aAAa;KACb,QAAQ;IACV,CAAC,GAEH,SAAS,UAAU,KAAK;IACxB;GACF;EAzCwB;CA0C1B,GAtCoC,EAAA,KAAA,QApBhCD,EAAAA,KAAAA,SAPI,EAAA,KAAA,WACF,EAAA,KAAA;CAJR,IAAM,cAAcE,IA4EL,KAAA,gBAAgB,WAJxBC;CAAP,OAGE,EAAA,OAAA,eAAA,EAAA,OADA,eAAA,EAAA,OADA,eAAA,EAAA,OAGaC,MAJR,KAAA;EACL;EACA;EACA;EACA,aAAaA;CACf,GAFE,EAAA,KAAA,aADA,EAAA,KAAA,aADA,EAAA,KAAA,aAGaA,EAAAA,KAAAA,4BAJRD;AAMT;ACrGA,SAAgB,oBACd,OACA,iBAAiB,6BACT;CACR,IAAI,UAAU;CAEd,IAAI,SAAS,OAAO,SAAU,UAAU;EACtC,IAAM,MAAM;EACZ,UAAU,IAAI,UAAU,MAAM,WAAW,IAAI,WAAW;CAC1D,OAAO,AAAI,OAAO,SAAU,aAC1B,UAAU;CAGZ,IAAI,CAAC,SACH,OAAO;CAGT,IAAM,QAAQ,QAAQ,MAAM,aAAa;CACzC,IAAI,SAAS,MAAM,IACjB,OAAO,MAAM;CAGf,IAAI,QAAQ,SAAS,gBAAgB,GAAG;EACtC,IAAM,QAAQ,QAAQ,MAAM,GAAG;EAC/B,IAAI,MAAM,SAAS,GACjB,OAAO,MAAM,MAAM,SAAS,EAAE,CAAE,QAAQ,KAAK,EAAE,CAAC,CAAC,KAAK;CAE1D;CAEA,OAAO;AACT;;;;;;;;AA0BA,eAAsB,gBACpB,SACgC;CAChC,IAAM,EACJ,QACA,SACA,WACA,mBACA,cAAc,IACd,cACA,gBACA,iBACE,SAEE,cAAc,UAAU,KAAK,GAC7B,sBAAsB,kBAAkB,KAAK,GAC/C,UACA,WAAW,GACX,aAAa,IAEX,aAAa,eAAyD;EAC1E,IAAI,aAAa,WAAW,MACzB,UAAU,MAAM,SAAS,eAAe,MAAM,kBAAkB,mBACnE;EAUA,OARA,AACE,eAAa,WAAW,MAAM,UAAU,MAAM,kBAAkB,mBAAmB,GAGjF,CAAC,cAAc,WAAW,SAAS,MACrC,aAAa,WAAW,WAAW,SAAS,KAGvC;CACT;CAEA,OAAO,WAAW,cAAa;EAC7B,IAAI;GACF,AAAI,WAAW,KACb,MAAM,IAAI,SAAS,YAAY,WAAW,SAAS,GAAI,CAAC;GAO1D,IAAM,aAAa,WAFjB,MAFsB,SAAS,QAAQ,OAAO,EAAA,CAEpC,KAAK,QAAQ,QAAQ,UAAiC,MAAM,SAAS,MAAM,KAAK,CAAC,CAEtD;GAEvC,IAAI,CAAC,YAAY;IACf;IACA;GACF;GASA,IAPA,aAAa,IACb,WAAW,YAEP,gBACF,aAAa,UAAU,GAGrB,WAAW,WAAW,SAAS;IACjC,AAAI,gBACF,aAAa,UAAU;IAEzB;GACF;GAEA,IAAI,WAAW,WAAW,WAIxB,OAHI,kBACF,eAAe,UAAU,GAEpB;IACL,OAAO;IACP,OAAO;IACP,QAAQ;GACV;EAEJ,SAAS,OAAO;GACd,QAAQ,MAAM,kCAAkC,KAAK;EACvD;EAEA;CACF;CAkBA,OAhBI,CAAC,YAAY,CAAC,aACT;EACL,OAAO,KAAA;EACP,OAAO;EACP,QAAQ;CACV,IAGE,SAAS,WAAW,cACf;EACL,OAAO;EACP,OAAO;EACP,QAAQ;CACV,IAGK;EACL,OAAO;EACP,OAAO;EACP,QAAQ;CACV;AACF;;;;AAKA,eAAsB,gBACpB,QACA,OACA,OACe;CACf,IAAI,CAAC,MAAM,IACT,MAAU,MAAM,qBAAqB;CAGvC,IAAI,MAAM,WAAW,SACnB,MAAU,MAAM,mCAAmC,MAAM,QAAQ;CAGnE,IAAI,CAAC,MAAM,SACT,MAAU,MAAM,sBAAsB;CAGxC,IAAM,aAAa,cAAc,KAAK;CACtC,IAAI,CAAC,YACH,MAAU,MAAM,yBAAyB;CAG3C,IAAM,iBAAiB,kBAAkB,KAAK,CAAC,EAAE,QAE7C,cAAc,0BAA0B,WAAW,QAAQ,MAAM,GAAG;CAExE,IAAI,mBAAmB,YAAY,mBAAmB,OAAO;EAC3D,IAAM,QAAQ,YAAY,QAAQ,YAAY,GAAG;EACjD,eAAe,UAAU;CAC3B;CAEA,IAAM,WAAW,MAAM,MAAM,WAAW;CACxC,IAAI,CAAC,SAAS,IACZ,MAAU,MAAM,4BAA4B,SAAS,YAAY;CAGnE,IAAM,OAAO,MAAM,SAAS,KAAK,GAC3B,UAAU,IAAI,gBAAgB,IAAI,GAElC,OAAO,SAAS,cAAc,GAAG;CAOvC,AANA,KAAK,OAAO,SACZ,KAAK,WAAW,GAAG,MAAM,YAAY,WAAW,GAAG,MAAM,iBAAiB,KAAK,OAC/E,SAAS,KAAK,YAAY,IAAI,GAC9B,KAAK,MAAM,GACX,SAAS,KAAK,YAAY,IAAI,GAE9B,IAAI,gBAAgB,OAAO;AAC7B;ACFA,MAAa,0BAA0B;CACrC;EAAC,OAAO;EAAW,MAAM;EAAM,OAAO;CAAQ;CAC9C;EAAC,OAAO;EAAW,MAAM;EAAM,OAAO;CAAQ;CAC9C;EAAC,OAAO;EAAW,MAAM;EAAM,OAAO;CAAQ;CAC9C;EAAC,OAAO;EAAc,MAAM;EAAM,OAAO;CAAQ;CACjD;EAAC,OAAO;EAAU,MAAM;EAAM,OAAO;CAAQ;CAC7C;EAAC,OAAO;EAAU,MAAM;EAAM,OAAO;CAAQ;CAC7C;EAAC,OAAO;EAAU,MAAM;EAAM,OAAO;CAAM;CAC3C;EAAC,OAAO;EAAW,MAAM;EAAM,OAAO;CAAM;CAC5C;EAAC,OAAO;EAAS,MAAM;EAAM,OAAO;CAAM;CAC1C;EAAC,OAAO;EAAW,MAAM;EAAM,OAAO;CAAM;CAC5C;EAAC,OAAO;EAAW,MAAM;EAAM,OAAO;CAAM;CAC5C;EAAC,OAAO;EAAW,MAAM;EAAM,OAAO;CAAM;CAC5C;EAAC,OAAO;EAAa,MAAM;EAAM,OAAO;CAAM;CAC9C;EAAC,OAAO;EAAa,MAAM;EAAM,OAAO;CAAM;CAC9C;EAAC,OAAO;EAAW,MAAM;EAAM,OAAO;CAAM;CAC5C;EAAC,OAAO;EAAU,MAAM;EAAM,OAAO;CAAM;CAC3C;EAAC,OAAO;EAAS,MAAM;EAAM,OAAO;CAAM;CAC1C;EAAC,OAAO;EAAS,MAAM;EAAM,OAAO;CAAM;CAC1C;EAAC,OAAO;EAAY,MAAM;EAAM,OAAO;CAAM;CAC7C;EAAC,OAAO;EAAU,MAAM;EAAM,OAAO;CAAM;CAC3C;EAAC,OAAO;EAAY,MAAM;EAAM,OAAO;CAAM;CAC7C;EAAC,OAAO;EAAa,MAAM;EAAM,OAAO;CAAM;AAChD;AAE8C,wBAAwB,KAAK,MAAM,EAAE,IAAI;AAyBvF,SAAgB,kBAAkB,OAA2D;CAC3F,OAAO,MAAM,SAAS;AACxB;AAEA,SAAgB,qBACd,OACiC;CACjC,OAAO,MAAM,SAAS;AACxB;AC5PA,MAAMI,qBAAmB,cAAc,YAAY,CAAC,CAAC,KAAK,UAAU;CAClE,OAAO;CACP,OAAO,cAAc,cAAc,IAAI;AACzC,EAAE,GAEI,uBAAuB,wBAAwB,KAAK,UAAU;CAClE,OAAO,KAAK;CACZ,OAAO,KAAK;AACd,EAAE;AAQF,SAAwB,iBAAiB,EAAC,OAAO,OAAO,WAAiB;CACvE,IAAM,SAASC,YAAU,GACnB,QAAQ,SAAS,GACjB,WAAW,mBAAmB,MAAM,KAEpC,CAAC,iBAAiB,sBAAsB,SAAS,EAAK,GACtD,CAAC,QAAQ,aAAa,SAAS,EAAE,GACjC,CAAC,cAAc,mBAAmB,SAAS,EAAE,GAC7C,CAAC,kBAAkB,uBAAuB,SAC9C,IACF,GACM,CAAC,MAAM,WAAW,SAAS,EAAE,GAC7B,CAAC,cAAc,mBAAmB,SAAS,EAAK,GAChD,CAAC,cAAc,mBAAmB,SAAsB,IAAI,GAC5D,eAAe,OAAyB,IAAI,GAE5C,gBAAgB,OAAO,UAIpB,MAHqB,OAAO,OAAO,OAAO,QAAQ,MAAM,EAC7D,UAAU,KAAK,KACjB,CAAC,EAAA,CACoB,KAGjB,mBAAmB,YAAY;EACnC,IAAK,MAAM,OAAQ,MAAM,SACzB,IAAI;GACF,IAAM,kBAAkB,MAAM,SAAS,QAAQ,MAAM,OAAO,GACtD,eAAe,iBAAiB,gBAAgB,IAAI;GAC1D,MAAM,OACH,MAAM,MAAM,GAAG,CAAC,CAChB,IAAI;IAAC,MAAM;IAAc,QAAQ,gBAAgB,KAAK;GAAM,CAAC,CAAC,CAC9D,OAAO,EAAC,iBAAiB,GAAK,CAAC;EACpC,SAAS,cAAc;GACrB,QAAQ,MAAM,iCAAiC,YAAY;EAC7D;CACF,GAEM,wBAAwB,YAAY;EACxC,IAAI,CAAC,MAAM,SACT,MAAU,MAAM,sBAAsB;EAGxC,IAAM,cAAc,KAAK,KAAK,GACxB,sBAAsB,aAAa,KAAK,GAE1C,cAAc,OAAO,KAAK;EAE9B,IAAI,cACF,IAAI;GACF,cAAc,MAAM,cAAc,YAAY;EAChD,SAAS,aAAa;GAOpB,MANA,MAAM,KAAK;IACT,OAAO;IACP,QAAQ;IACR,aAAa;GACf,CAAC,GACD,gBAAgB,EAAK,GACf;EACR;EAGF,MAAM,oBAAoB,QAAQ,MAAM,SAAS,aAAa;GAC5D,eAAe;GACf,MAAM;GACN,WAAW;EACb,CAAC;EAED,IAAM,SAAS,MAAM,gBAAgB;GACnC;GACA,SAAS,MAAM;GACf,WAAW;GACX,mBAAmB;GACnB,gBAAgB,OAAO,UAAU;IAC/B,IAAM,eACJ,MAAM,OAAO,WAAW,MACxB,MAAM,OAAO,QACb;IAQF,AAPA,MAAM,KAAK;KACT,OAAO;KACP,QAAQ;KACR,aAAa;IACf,CAAC,GACD,MAAM,iBAAiB,GACvB,MAAM,KAAK,GACX,QAAQ;GACV;EACF,CAAC;EAED,AAAI,CAAC,OAAO,SAAS,CAAC,OAAO,SAC3B,MAAM,KAAK;GACT,OAAO;GACP,QAAQ;GACR,aACE;EACJ,CAAC,GACD,QAAQ,KAIN,OAAO,WAAW,cAIlB,OAAO,WAAW,eACpB,MAAM,KAAK;GACT,OAAO;GACP,QAAQ;GACR,aACE;EACJ,CAAC,GACD,MAAM,iBAAiB,GACvB,MAAM,OAAO,KAAK,GAClB,QAAQ,MAIV,MAAM,iBAAiB,GACvB,MAAM,KAAK;GACT,OAAO;GACP,QAAQ;GACR,aAAa;EACf,CAAC,GAED,MAAM,OAAO,KAAK,GAClB,QAAQ;CACV,GAEM,0BAA0B,YAAY;EAC1C,IAAI,CAAC,MAAM,SACT,MAAU,MAAM,sBAAsB;EAIxC,IAAM,cAAa,MADK,SAAS,QAAQ,MAAM,OAAO,EAAA,CACzB,KAAK,QAAQ,MAAM,UAAU,MAAM,SAAS,OAAO;EAEhF,IAAI,CAAC,cAAc,CAAC,WAAW,IAO7B,MANA,MAAM,KAAK;GACT,OAAO;GACP,QAAQ;GACR,aACE;EACJ,CAAC,GACS,MAAM,sBAAsB;EAGxC,MAAM,kBAAkB,QAAQ,MAAM,SAAS,WAAW,IAAI;GAC5D,eAAe,aAAa,KAAK;GACjC,MAAM,KAAK,KAAK;EAClB,CAAC;EAGD,IAAM,YAA0B;GAC9B,MAAM;GACN,IAAI,cAH4B,KAAK,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,GAAG,EAAE;GAIpF,WAAW;GACX,aAAa;GACb,eAAe,aAAa,KAAK;GACjC,MAAM,KAAK,KAAK;GAChB,QAAQ;EACV;EASA,AAPA,MAAM,KAAK;GACT,OAAO;GACP,QAAQ;GACR,aAAa;EACf,CAAC,GAED,MAAM,SAAS,GACf,QAAQ;CACV,GAEM,eAAe,YAAY;EAC/B,IAAI,CAAC,iBAAiB;GACpB,IAAI,CAAC,gBAAgB,CAAC,OAAO,KAAK,GAAG;IACnC,MAAM,KAAK;KACT,OAAO;KACP,QAAQ;KACR,aAAa;IACf,CAAC;IACD;GACF;GAEA,IAAI,OAAO,KAAK,KAAK,CAAC,cACpB,IAAI;IACF,IAAS,IAAI,OAAO,KAAK,CAAC;GAC5B,QAAQ;IACN,MAAM,KAAK;KACT,OAAO;KACP,QAAQ;KACR,aACE;IACJ,CAAC;IACD;GACF;EAEJ;EAEA,IAAI,CAAC,KAAK,KAAK,GACb,MAAM,KAAK;GACT,OAAO;GACP,QAAQ;GACR,aAAa;EACf,CAAC;OAIH,IAAI,CAAC,aAAa,KAAK,GACrB,MAAM,KAAK;GACT,OAAO;GACP,QAAQ;GACR,aAAa;EACf,CAAC;OAIH;mBAAgB,EAAI;GAEpB,IAAI;IACF,AAAI,kBACF,MAAM,wBAAwB,IAE9B,MAAM,sBAAsB;GAEhC,SAAS,OAAO;IACd,MAAM,KAAK;KACT,OAAO;KACP,QAAQ;KACR,aAAa,oBAAoB,OAAO,6BAA6B;IACvE,CAAC;GAEH,UAAU;IACR,gBAAgB,EAAK;GACvB;EAjBoB;CAkBtB;CAEA,OACE,oBAAC,QAAD;EACE,IAAI;EACJ,QAAO;EACE;EACT,OAAO;EACP,gBAAgB;EAEhB,UAAA,qBAAC,OAAD;GAAO,SAAS;GAAG,KAAK;GAAxB,UAAA;IACE,qBAAC,OAAD;KAAO,KAAK;KAAZ,UAAA,CACE,qBAAC,MAAD;MAAM,OAAM;MAAS,cAAc;MAAnC,UAAA,CACE,oBAAC,UAAD;OACE,IAAG;OACH,OAAO,EAAC,SAAS,QAAO;OACxB,SAAS;OACT,WAAW,MAAM;QAEf,AADA,mBAAmB,EAAE,cAAc,OAAO,GACtC,EAAE,cAAc,WAClB,UAAU,EAAE;OAEhB;OACA,UAAU;MACX,CAAA,GACD,oBAAC,MAAD;OAAM,MAAM;OAAG,aAAa;OAC1B,UAAA,oBAAC,MAAD,EAAA,UACE,oBAAC,SAAD;QAAO,SAAQ;QAAyB,UAAA;OAAwB,CAAA,EAC5D,CAAA;MACF,CAAA,CACF;KACL,CAAA,GAAA,CAAC,mBACA,qBAAC,OAAD;MAAO,KAAK;MAAZ,UAAA;OACE,qBAAC,MAAD;QAAM,SAAS;QAAG,cAAc;QAAG,MAAK;QAAc,QAAA;QAAO,QAAQ;QAArE,UAAA,CACE,qBAAC,MAAD;SAAM,OAAM;SAAS,SAAQ;SAA7B,UAAA,CACE,oBAAC,MAAD;UAAM,MAAM;UAAG,OAAA;UACZ,UAAA,eAAe,aAAa,aAAa,SAAS;SAC/C,CAAA,GACN,oBAAC,QAAD;UACE,MAAM;UACN,MAAK;UACL,MAAK;UACL,MAAK;UACL,UAAU;UACV,SAAS;UACT,eAAe,aAAa,SAAS,MAAM;UAC3C,UAAU;SACX,CAAA,CACG;QACN,CAAA,GAAA,oBAAC,SAAD;SACE,KAAK;SACL,MAAK;SACL,QAAO;SACP,OAAO,EAAC,SAAS,OAAM;SACvB,WAAW,MAAM;UACf,AAAI,EAAE,OAAO,SAAS,EAAE,OAAO,MAAM,SAAS,KAAK,CAAC,iBAClD,gBAAgB,EAAE,OAAO,MAAM,EAAG,GAClC,UAAU,EAAE;SAEhB;QACD,CAAA,CACG;;OACN,oBAAC,MAAD;QAAM,MAAM;QAAG,OAAA;QAAM,OAAO,EAAC,WAAW,SAAQ;QAAG,UAAA;OAE7C,CAAA;OACN,qBAAC,OAAD;QAAO,KAAK;QAAZ,UAAA,CACE,oBAAC,OAAD;SAAO,IAAG;SAAQ,SAAQ;SAAU,UAAA;QAE7B,CAAA,GACP,oBAAC,WAAD;SACE,IAAG;SACH,aAAY;SACZ,OAAO;SACP,WAAW,MAAM;UAEf,AADA,UAAU,EAAE,cAAc,KAAK,GAC/B,gBAAgB,IAAI;SACtB;SACA,UAAU;QACX,CAAA,CACI;;MACF;KAEJ,CAAA,CAAA;;IAEP,qBAAC,OAAD;KAAO,KAAK;KAAZ,UAAA,CACE,oBAAC,OAAD;MAAO,IAAG;MAAQ,SAAQ;MAAe,UAAA;KAElC,CAAA,GACP,oBAAC,cAAD;MACE,IAAG;MACH,OAAO,kBAAkB,SAAS;MAClC,WAAW,aAAa;OAEtB,IAAM,YADU,kBAAkB,uBAAuBD,mBAAAA,CAChC,MAAM,QAAQ,IAAI,UAAU,QAAQ;OAC7D,AAAI,aACF,oBAAoB,QAAQ,GAC5B,gBAAgB,SAAS,KAAK,GAC9B,QAAQ,SAAS,KAAK;MAE1B;MACA,SAAS,kBAAkB,uBAAuBA;MAClD,MAAM;MACN,aAAY;MACZ,eAAe,OAAO,WACpB,OAAO,MAAM,YAAY,CAAC,CAAC,QAAQ,MAAM,YAAY,CAAC,IAAI,MAC1D,OAAO,MAAM,YAAY,CAAC,CAAC,QAAQ,MAAM,YAAY,CAAC,IAAI;MAE5D,YAAA;MACA,cAAc,WACX,kBAAkB,uBAAuBA,mBAAAA,CAAkB,MACzD,MAAM,EAAE,UAAU,KACrB,CAAC,EAAE,SAAS;MAEd,eAAe,WACb,oBAAC,MAAD;OAAM,WAAQ;OAAS,SAAS;OAAG,QAAQ;OAAG,MAAK;OACjD,UAAA,qBAAC,MAAD;QAAM,MAAM;QAAG,cAAa;QAA5B,UAAA;SACG,OAAO;SAAM;SAAG,OAAO;SAAM;QAC1B;;MACF,CAAA;MAER,UAAU;KACX,CAAA,CACI;;IAEP,qBAAC,OAAD;KAAO,KAAK;KAAZ,UAAA,CACE,oBAAC,OAAD;MAAO,IAAG;MAAQ,SAAQ;MAAmB,UAAA;KAEtC,CAAA,GACP,oBAAC,WAAD;MACE,IAAG;MACH,aAAY;MACZ,OAAO;MACP,WAAW,MAAM;OAEf,AADA,gBAAgB,EAAE,cAAc,KAAK,GACjC,oBAAoB,iBAAiB,UAAU,EAAE,cAAc,UACjE,oBAAoB,IAAI,IACpB,CAAC,QAAQ,SAAS,iBAAiB,UACrC,QAAQ,EAAE;MAGhB;MACA,UAAU;KACX,CAAA,CACI;;IAEP,qBAAC,MAAD;KAAM,KAAK;KAAG,SAAQ;KAAW,WAAW;KAA5C,UAAA,CACE,oBAAC,QAAD;MAAQ,MAAK;MAAS,MAAK;MAAQ,SAAS;MAAS,UAAU;KAAe,CAAA,GAC9E,oBAAC,QAAD;MACE,MAAK;MACL,MAAK;MACL,MACE,eACE,oBAAC,SAAD,EACE,OAAO;OACL,eAAe;OACf,SAAS;OACT,cAAc;OACd,OAAO;OACP,QAAQ;OACR,aAAa;MACf,EACD,CAAA,IAED,oBAAC,YAAD,CAAa,CAAA;MAGjB,SAAS;MACT,UAAU;KACX,CAAA,CACG;;GACD;;CACD,CAAA;AAEZ;AC7aA,MAAM,mBAAmB,cAAc,YAAY,CAAC,CAAC,KAAK,UAAU;CAClE,OAAO;CACP,OAAO,cAAc,cAAc,IAAI;AACzC,EAAE;AASF,SAAwB,kBAAkB,EAAC,OAAO,OAAO,UAAU,WAAiB;CAClF,IAAM,SAASE,YAAU,GACnB,QAAQ,SAAS,GACjB,WAAW,oBAAoB,MAAM,KAErC,kBACJ,MAAM,gBAAgB,oBACtB,MAAM,gBAAgB,0BACtB,MAAM,gBAAgB,iBAElB,CAAC,QAAQ,aAAa,SAAS,EAAE,GACjC,CAAC,cAAc,mBAAmB,SAAS,MAAM,iBAAiB,EAAE,GACpE,CAAC,kBAAkB,uBAAuB,eACxC;EACJ,IAAM,WAAW,MAAM,eAAe,MAAM,GAAG,CAAC,CAAC,IAC3C,QAAQ,iBAAiB,MAC5B,QAAQ,IAAI,UAAU,MAAM,iBAAiB,IAAI,UAAU,QAC9D;EACA,IAAI,OAAO,OAAO;EAClB,IAAI,MAAM,MAAM;GACd,IAAM,cAAc,iBAAiB,MAAM,QAAQ,IAAI,UAAU,MAAM,IAAI;GAC3E,IAAI,aAAa,OAAO;EAC1B;EACA,OAAO;CACT,CACF,GACM,CAAC,MAAM,WAAW,SAAS,MAAM,QAAQ,EAAE,GAC3C,CAAC,cAAc,mBAAmB,SAAS,EAAK,GAChD,CAAC,aAAa,kBAAkB,SAAS,EAAK,GAC9C,CAAC,cAAc,mBAAmB,SAAsB,IAAI,GAC5D,eAAe,OAAyB,IAAI;CAElD,gBAAgB;EAId,AAFA,gBAAgB,MAAM,iBAAiB,EAAE,GACzC,QAAQ,MAAM,QAAQ,EAAE,GACxB,UAAU,EAAE;EACZ,IAAM,WAAW,MAAM,eAAe,MAAM,GAAG,CAAC,CAAC,IAC3C,cAAc,iBAAiB,MAClC,QAAQ,IAAI,UAAU,MAAM,iBAAiB,IAAI,UAAU,QAC9D,GACM,cAAc,MAAM,OAAO,iBAAiB,MAAM,QAAQ,IAAI,UAAU,MAAM,IAAI,IAAI;EAC5F,oBAAoB,eAAe,eAAe,IAAI;CAExD,GAAG;EAAC;EAAO;EAAO;CAAM,CAAC;CAEzB,IAAM,4BAA4B,YAAY;EAC5C,eAAe,EAAI;EACnB,IAAI;GACF,MAAM,gBAAgB,QAAQ,OAAO,KAAK;EAC5C,SAAS,OAAO;GACd,IAAI,eAAe,oBACf,QAAQ;GAYZ,AAVI,iBAAiB,SACnB,eAAe,MAAM,SACjB,MAAM,QAAQ,SAAS,OAAO,MAChC,QAAQ,uBAED,UAAU,yBAAyB,UAAU,8BACtD,eAAe,OACf,QAAQ,oBAGV,MAAM,KAAK;IACT;IACA,QAAQ;IACR,aAAa;GACf,CAAC;EAEH,UAAU;GACR,eAAe,EAAK;EACtB;CACF,GAEM,2BACA,MAAM,MAAM,MAAM,WACb,GAAG,MAAM,SAAS,GAAG,MAAM,iBAAiB,KAAK,QAEnD,YAAY,MAAM,iBAAiB,KAAK,OAG3C,gBAAgB,OAAO,UAIpB,MAHqB,OAAO,OAAO,OAAO,QAAQ,MAAM,EAC7D,UAAU,KAAK,KACjB,CAAC,EAAA,CACoB,KAGjB,mBAAmB,YAAY;EACnC,IAAK,MAAM,OAAQ,MAAM,SACzB,IAAI;GACF,IAAM,kBAAkB,MAAM,SAAS,QAAQ,MAAM,OAAO,GACtD,eAAe,iBAAiB,gBAAgB,IAAI;GAC1D,MAAM,OACH,MAAM,MAAM,GAAG,CAAC,CAChB,IAAI;IAAC,MAAM;IAAc,QAAQ,gBAAgB,KAAK;GAAM,CAAC,CAAC,CAC9D,OAAO,EAAC,iBAAiB,GAAK,CAAC;EACpC,SAAS,cAAc;GACrB,QAAQ,MAAM,iCAAiC,YAAY;EAC7D;CACF,GAEM,8BAA8B,YAAY;EAC9C,IAAI,CAAC,MAAM,SACT,MAAU,MAAM,sBAAsB;EAGxC,IAAM,cAAc,KAAK,KAAK,GACxB,sBAAsB,aAAa,KAAK,GAExC,aAAa,MAAM;EAEzB,IAAI;GACF,MAAM,gBAAgB,QAAQ,MAAM,SAAS,UAAU;EACzD,SAAS,aAAa;GAOpB,MANA,MAAM,KAAK;IACT,OAAO;IACP,QAAQ;IACR,aAAa;GACf,CAAC,GACD,gBAAgB,EAAK,GACf;EACR;EAEA,IAAI,cAAc,OAAO,KAAK;EAE9B,IAAI,cACF,IAAI;GACF,cAAc,MAAM,cAAc,YAAY;EAChD,SAAS,aAAa;GAOpB,MANA,MAAM,KAAK;IACT,OAAO;IACP,QAAQ;IACR,aAAa;GACf,CAAC,GACD,gBAAgB,EAAK,GACf;EACR;EAGF,IAAI;GACF,MAAM,oBAAoB,QAAQ,MAAM,SAAS,aAAa;IAC5D,eAAe;IACf,MAAM;IACN,WAAW;GACb,CAAC;EACH,SAAS,OAAgB;GAOvB,MANA,MAAM,KAAK;IACT,OAAO;IACP,QAAQ;IACR,aAAa,oBAAoB,OAAO,gCAAgC;GAC1E,CAAC,GACD,gBAAgB,EAAK,GACf;EACR;EAEA,IAAM,SAAS,MAAM,gBAAgB;GACnC;GACA,SAAS,MAAM;GACf,WAAW;GACX,mBAAmB;GACnB,gBAAgB,OAAO,iBAAiB;IACtC,IAAM,eACJ,aAAa,OAAO,WAAW,MAC/B,aAAa,OAAO,QACpB;IAQF,AAPA,MAAM,KAAK;KACT,OAAO;KACP,QAAQ;KACR,aAAa;IACf,CAAC,GACD,MAAM,iBAAiB,GACvB,SAAS,cAAc,UAAU,GACjC,gBAAgB,EAAK;GACvB;EACF,CAAC;EAED,AAAI,CAAC,OAAO,SAAS,CAAC,OAAO,SAC3B,MAAM,KAAK;GACT,OAAO;GACP,QAAQ;GACR,aACE;EACJ,CAAC,GACD,gBAAgB,EAAK,KAInB,OAAO,WAAW,cAItB,MAAM,iBAAiB,GAEnB,OAAO,WAAW,cACpB,MAAM,KAAK;GACT,OAAO;GACP,QAAQ;GACR,aACE;EACJ,CAAC,IAED,MAAM,KAAK;GACT,OAAO;GACP,QAAQ;GACR,aAAa;EACf,CAAC,GAGH,SAAS,OAAO,OAAO,UAAU,GACjC,gBAAgB,EAAK;CACvB,GAEM,eAAe,YAAY;EAC/B,IAAI,CAAC,KAAK,KAAK,GACb,MAAM,KAAK;GACT,OAAO;GACP,QAAQ;GACR,aAAa;EACf,CAAC;OAIH,IAAI,CAAC,aAAa,KAAK,GACrB,MAAM,KAAK;GACT,OAAO;GACP,QAAQ;GACR,aAAa;EACf,CAAC;OAIH;mBAAgB,EAAI;GAEpB,IAAI;IACF,IAAI,CAAC,MAAM,SAET,MAAU,MAAM,sBAAsB;IAGxC,IAAM,wBAAwB;KAC5B,IAAI,mBAAmB,CAAC,MAAM,IAAI,OAAO;KACzC,IAAM,aAAa,cAAc,KAAK;KACtC,IAAI,CAAC,YAAY,OAAO;KACxB,IAAI,MAAM,0BAA0B,WAAW,QAAQ,MAAM,GAAG;KAChE,IAAI,kBAAkB,KAAK,CAAC,EAAE,WAAW,UAAU;MACjD,IAAM,QAAQ,YAAY,QAAQ,YAAY,GAAG;MACjD,OAAO,UAAU;KACnB;KACA,OAAO;IACT,EAAA,CAAG,GAEG,aACJ,iBAAiB,QAAS,OAAO,KAAK,KAAK,OAAO,KAAK,MAAM;IAE/D,IAAI,CAAC,YAAY;KAOf,AANA,MAAM,KAAK;MACT,OAAO;MACP,QAAQ;MACR,aACE;KACJ,CAAC,GACD,gBAAgB,EAAK;KACrB;IACF;IAEA,IAAI,YAAY;KACd,IAAI,CAAC,gBAAgB,OAAO,KAAK,GAC/B,IAAI;MACF,IAAS,IAAI,OAAO,KAAK,CAAC;KAC5B,QAAQ;MAMN,AALA,MAAM,KAAK;OACT,OAAO;OACP,QAAQ;OACR,aAAa;MACf,CAAC,GACD,gBAAgB,EAAK;MACrB;KACF;KAGF,IAAI,CAAC,gBAAgB,CAAC,OAAO,KAAK,GAAG;MAMnC,AALA,MAAM,KAAK;OACT,OAAO;OACP,QAAQ;OACR,aAAa;MACf,CAAC,GACD,gBAAgB,EAAK;MACrB;KACF;KAEA,MAAM,4BAA4B;IACpC;IAEA,QAAQ;GACV,SAAS,OAAO;IACd,MAAM,KAAK;KACT,OAAO;KACP,QAAQ;KACR,aAAa,iBAAiB,QAAQ,MAAM,UAAU;IACxD,CAAC;GAEH,UAAU;IACR,gBAAgB,EAAK;GACvB;EAxEoB;CAyEtB;CAEA,OACE,oBAAC,QAAD;EACE,IAAI;EACJ,QAAO;EACE;EACT,OAAO;EACP,gBAAgB;EAEhB,UAAA,qBAAC,OAAD;GAAO,SAAS;GAAG,KAAK;GAAxB,UAAA;IACE,qBAAC,OAAD;KAAO,KAAK;KAAZ,UAAA,CACE,qBAAC,MAAD;MAAM,SAAS;MAAG,cAAc;MAAG,MAAK;MAAc,QAAA;MAAO,QAAQ;MAArE,UAAA;OACE,qBAAC,MAAD;QAAM,OAAM;QAAS,SAAQ;QAA7B,UAAA,CACE,oBAAC,MAAD,EAAA,UAAO,mBAAmB,EAAQ,CAAA,GAClC,qBAAC,MAAD;SAAM,KAAK;SAAX,UAAA,CACG,MAAM,WAAW,aAChB,oBAAC,QAAD;UACE,MACE,cACE,oBAAC,SAAD,EACE,OAAO;WACL,eAAe;WACf,SAAS;WACT,WAAW;WACX,OAAO;WACP,QAAQ;UACV,EACD,CAAA,IAED,oBAAC,cAAD,CAAe,CAAA;UAGnB,MAAK;UACL,MAAK;UACL,MAAK;UACL,UAAU;UACV,SAAS;UACT,SAAS;UACT,UAAU,eAAe;SAC1B,CAAA,GAEH,oBAAC,QAAD;UACE,MAAM;UACN,MAAK;UACL,MAAK;UACL,MAAK;UACL,UAAU;UACV,SAAS;UACT,eAAe,aAAa,SAAS,MAAM;UAC3C,UAAU;SACX,CAAA,CACG;QACF,CAAA,CAAA;;OACN,oBAAC,SAAD;QACE,KAAK;QACL,MAAK;QACL,QAAO;QACP,OAAO,EAAC,SAAS,OAAM;QACvB,WAAW,MAAM;SACf,AAAI,EAAE,OAAO,SAAS,EAAE,OAAO,MAAM,SAAS,KAAK,CAAC,iBAClD,gBAAgB,EAAE,OAAO,MAAM,EAAG,GAClC,UAAU,EAAE;QAEhB;OACD,CAAA;OACA,gBACC,qBAAC,MAAD;QAAM,MAAM;QAAG,OAAA;QAAM,OAAO,EAAC,WAAW,EAAC;QAAzC,UAAA,CAA4C,cAC/B,aAAa,IACpB;;MAEJ;KACN,CAAA,GAAA,qBAAC,OAAD;MAAO,KAAK;MAAZ,UAAA;OACE,oBAAC,OAAD;QAAO,IAAG;QAAQ,SAAQ;QAAU,UAAA;OAE7B,CAAA;OACP,oBAAC,WAAD;QACE,IAAG;QACH,aAAY;QACZ,OAAO;QACP,WAAW,MAAM;SAEf,AADA,UAAU,EAAE,cAAc,KAAK,GAC/B,gBAAgB,IAAI;QACtB;QACA,UAAU;OACX,CAAA;OACD,oBAAC,MAAD;QAAM,MAAM;QAAG,OAAA;QAAM,UAAA;OAEf,CAAA;MACD;KACF,CAAA,CAAA;;IAEP,qBAAC,OAAD;KAAO,KAAK;KAAZ,UAAA,CACE,oBAAC,OAAD;MAAO,IAAG;MAAQ,SAAQ;MAAe,UAAA;KAElC,CAAA,GACP,oBAAC,cAAD;MACE,IAAG;MACH,OAAO,kBAAkB,SAAS;MAClC,WAAW,aAAa;OACtB,IAAM,WAAW,iBAAiB,MAAM,QAAQ,IAAI,UAAU,QAAQ;OACtE,AAAI,aACF,oBAAoB,QAAQ,GAC5B,gBAAgB,SAAS,KAAK,GAC9B,QAAQ,SAAS,KAAK;MAE1B;MACA,SAAS;MACT,MAAM;MACN,aAAY;MACZ,eAAe,OAAO,WACpB,OAAO,MAAM,YAAY,CAAC,CAAC,QAAQ,MAAM,YAAY,CAAC,IAAI,MAC1D,OAAO,MAAM,YAAY,CAAC,CAAC,QAAQ,MAAM,YAAY,CAAC,IAAI;MAE5D,YAAA;MACA,cAAc,UAAU,iBAAiB,MAAM,MAAM,EAAE,UAAU,KAAK,CAAC,EAAE,SAAS;MAClF,eAAe,WACb,oBAAC,MAAD;OAAM,WAAQ;OAAS,SAAS;OAAG,QAAQ;OAAG,MAAK;OACjD,UAAA,qBAAC,MAAD;QAAM,MAAM;QAAG,cAAa;QAA5B,UAAA;SACG,OAAO;SAAM;SAAG,OAAO;SAAM;QAC1B;;MACF,CAAA;MAER,UAAU;KACX,CAAA,CACI;;IAEP,qBAAC,OAAD;KAAO,KAAK;KAAZ,UAAA,CACE,oBAAC,OAAD;MAAO,IAAG;MAAQ,SAAQ;MAAmB,UAAA;KAEtC,CAAA,GACP,oBAAC,WAAD;MACE,IAAG;MACH,aAAY;MACZ,OAAO;MACP,WAAW,MAAM;OAEf,AADA,gBAAgB,EAAE,cAAc,KAAK,GACjC,oBAAoB,iBAAiB,UAAU,EAAE,cAAc,UACjE,oBAAoB,IAAI,IACpB,CAAC,QAAQ,SAAS,iBAAiB,UACrC,QAAQ,EAAE;MAGhB;MACA,UAAU;KACX,CAAA,CACI;;IAEP,qBAAC,MAAD;KAAM,KAAK;KAAG,SAAQ;KAAW,WAAW;KAA5C,UAAA,CACE,oBAAC,QAAD;MAAQ,MAAK;MAAS,MAAK;MAAQ,SAAS;MAAS,UAAU;KAAe,CAAA,GAC9E,oBAAC,QAAD;MACE,MAAK;MACL,MAAK;MACL,MACE,eACE,oBAAC,SAAD,EACE,OAAO;OACL,eAAe;OACf,SAAS;OACT,cAAc;OACd,OAAO;OACP,QAAQ;OACR,aAAa;MACf,EACD,CAAA,IAED;MAGJ,SAAS;MACT,UAAU;KACX,CAAA,CACG;;GACD;;CACD,CAAA;AAEZ;ACjeA,SAAS,UAAA,IAUU;gBAVA,EACjB,OACA,UACA,oBACA,iBACA,aACA,qBACA,gBACA,gBACA,qBATiBC,IAWEC;CAGkB,AAAA,EAAA,OAAA,mBAAA,EAAA,OAA/B,sBAAA,EAAA,OAAyDC,MAAAA,MAAAA,EAAAA,OAAmBA,aAAAA,MAH/D,MAAC,WACd,WAAW,aAEX,uBAAuB,QAAQ,oBAAoB,MAAM,MAAM,aAAa,OAAO,MAAM,KAGzF,WAAW,SAEX,uBAAuB,MAAM,MAC7B,oBAAoB,MAAM,MAC1B,aAAa,OAAO,MAAM,KAI5B,uBAAuB,MAAM,MAAM,oBAAoB,QAAQ,aAAa,OAAO,MAAM,IAXxD,EAAA,KAAA,iBAA/B,EAAA,KAAA,oBAAyDA,EAAAA,KAAAA,MAAAA,IAAmBA,EAAAA,KAAAA,aAAAA;CAHlF,IAAM,aAAaD,IAkBSE;CA+DlB,AAAA,EAAA,OAAA,mBAAA,EAAA,OArCE,sBAAA,EAAA,OAmBa,kBAAA,EAAA,OALT,YAAA,EAAA,OAMI,cAAA,EAAA,QAqCG,oBAAA,EAAA,QAzBA,kBAAA,EAAA,QAzDjBC,SADsB,WACtB,MAAM,WAAW,cAEjB,qBAAC,MAAD;EAAM,OAAM;EAAS,KAAK;EAA1B,UAAA,CACE,oBAAC,SAAD;GACE,OAAA;GACA,OAAO;IACL,OAAO;IACP,QAAQ;IACR,eAAe;IACf,SAAS;IACT,cAAc;GAChB;EACD,CAAA,GACD,oBAAC,MAAD;GAAM,MAAM;GAAG,OAAA;GACb,UAAA;EACI,CAAA,CACF;MAKR,qBAAC,MAAD;EAAM,KAAK;EAAX,UAAA;GACG,MAAM,WAAW,aAChB,oBAAC,QAAD;IACE,MACE,uBAAuB,MAAM,KAC3B,oBAAC,SAAD,EACE,OAAO;KACL,eAAe;KACf,SAAS;KACT,WAAW;KACX,OAAO;KACP,QAAQ;IACV,EACD,CAAA,IAED,oBAAC,cAAD,CAAe,CAAA;IAGnB,MAAM,WAAW,KAAA,IAAY;IAC7B,MAAK;IACL,MAAK;IACL,UAAU;IACV,SAAS;IACT,eAAe,eAAe,KAAK;IACnC,UAAU,WAAW,UAAU;IAC/B,OAAM;GACP,CAAA;GAEH,oBAAC,QAAD;IACE,MAAM,oBAAC,UAAD,CAAW,CAAA;IACjB,MAAM,WAAW,KAAA,IAAY;IAC7B,MAAK;IACL,MAAK;IACL,UAAU;IACV,SAAS;IACT,UAAU,WAAW,MAAM;IAC3B,eAAe,eAAe,KAAK;IACnC,OAAM;GACP,CAAA;GACD,oBAAC,QAAD;IACE,MACE,oBAAoB,MAAM,KACxB,oBAAC,SAAD,EACE,OAAO;KACL,eAAe;KACf,SAAS;KACT,WAAW;KACX,OAAO;KACP,QAAQ;IACV,EACD,CAAA,IAED,oBAAC,WAAD,CAAY,CAAA;IAGhB,MAAM,WAAW,KAAA,IAAY;IAC7B,MAAK;IACL,MAAK;IACL,UAAU;IACV,SAAS;IACT,UAAU,WAAW,QAAQ;IAC7B,eAAe,iBAAiB,KAAK;IACrC,OAAM;GACP,CAAA;EACG;KAvBA,EAAA,KAAA,iBArCE,EAAA,KAAA,oBAmBa,EAAA,KAAA,gBALT,EAAA,KAAA,UAMI,EAAA,KAAA,YAqCG,EAAA,MAAA,kBAzBA,EAAA,MAAA,gBAzDjBA,EAAAA,MAAAA;CADN,IAAM,sBAAsBD,IA8FlB,KAAA,MAAM,WAAW,YAAY,YAAY,eAMhB,KAAA,MAAM,QAAQ,YAAvCE;CAAyBC,AAAAA,EAAAA,QAAAA,mBAAzB,KAAA,oBAAC,MAAD;EAAM,QAAO;EAAYA,UAAAA;CAA+B,CAAA,GAA/BA,EAAAA,MAAAA;CAErBC,IAAAA;CAAoB,AAAA,EAAA,QAAA,uBAAA,EAAA,QAAA,SAApB,KAAA,oBAAoB,KAAK,GAAzB,EAAA,MAAA,qBAAoB,EAAA,MAAA;CADxBC,IAAAA;CACID,AAAAA,EAAAA,QAAAA,mBADJ,KAAA,qBAAC,MAAD;EAAM,MAAM;EAAG,OAAA;EAAf,UAAA;GACE;GAAEA;GAA2B;EACzB;KADFA,EAAAA,MAAAA;CAEHE,IAAAA;CAAMC,AAAAA,EAAAA,QAAAA,MAAAA,uBAAN,KAAA,MAAM,WAAW,aAChB,oBAAC,kBAAD;EACE,OAAO,EAAC,OAAO,6BAA4B;EAC3C,cAAW;EACX,UAAU;CACX,CAAA,GALIA,EAAAA,MAAAA,MAAAA;CALTC,IAAAA;CACEN,AAAAA,EAAAA,QAAAA,MAAAA,EAAAA,QACAG,MAAAA,EAAAA,QAGCC,MALH,KAAA,qBAAC,MAAD;EAAM,OAAM;EAAS,KAAK;EAA1B,UAAA;GACEJ;GACAG;GAGCC;EAOG;KAXJJ,EAAAA,MAAAA,IACAG,EAAAA,MAAAA,IAGCC,EAAAA,MAAAA;CAQFG,IAAAA;CAAMC,AAAAA,EAAAA,QAAAA,MAAAA,+BAAN,MAAA,MAAM,iBACL,qBAAC,MAAD;EAAM,MAAM;EAAG,OAAA;EAAf,UAAA,CACE,cAAW,MAAM,aACb;KAHDA,EAAAA,MAAAA,MAAAA;CAKNC,IAAAA;CAAoCC,AAAAA,EAAAA,QAAAA,MAAAA,SAAAA,EAAAA,QAA9BL,MAAAA,UAAN,MAAA,MAAM,WAAW,aAAa,MAAM,SACnC,oBAAC,MAAD;EAAM,MAAM;EAAG,OAAO,EAAC,OAAO,6BAA4B;EACvD,UAAA,MAAM,MAAM,WAAW,MAAM,MAAM,MAAM,QAAQ;CAC9C,CAAA,GAH6BK,EAAAA,MAAAA,MAAAA,OAA9BL,EAAAA,MAAAA,MAAAA;CAnBTM,IAAAA;CAcGJ,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAKAE,OAAAA,EAAAA,QAlBDH,MADF,MAAA,qBAAC,OAAD;EAAO,KAAK;EAAG,MAAM;EAArB,UAAA;GACEA;GAaCC;GAKAE;EAKI;KAVJF,EAAAA,MAAAA,KAKAE,EAAAA,MAAAA,KAlBDH,EAAAA,MAAAA;CAwBDM,IAAAA;gDAAoB,MAAA,oBAAA,GAApB,EAAA,MAAA;CA1BHC,IAAAA;CACEF,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAyBCC,OA1BH,MAAA,qBAAC,MAAD;EAAM,OAAM;EAAS,SAAQ;EAAgB,KAAK;EAAlD,UAAA,CACED,KAyBCC,GACG;KA1BJD,EAAAA,MAAAA,KAyBCC,EAAAA,MAAAA;CAhCLE,IAAAA;CADF,OAOID,EAAAA,QAAAA,OAAAA,EAAAA,QAHME,MAHR,MAAA,oBAAC,MAAD;EACE,SAAS;EACT,QAAQ;EACR,MAAMA;EACN,QAAA;EAEAF,UAAAA;CA4BI,CAAA,GA5BJA,EAAAA,MAAAA,KAHME,EAAAA,MAAAA,gCAHRD;AAoCJ;AASA,SAAwB,kBAAkB,EACxC,OACA,WAAW,IACX,QAAQ,YACR,iBAAiB,MACQ;CACzB,IAAM,SAASG,YAAU,GACnB,QAAQ,SAAS,GACjB,WAAW,sBAAsB,MAAM,KACvC,EAAC,gBAAe,eAAe,GAC/B,CAAC,oBAAoB,yBAAyB,SAAwB,IAAI,GAC1E,CAAC,iBAAiB,sBAAsB,SAAwB,IAAI,GACpE,CAAC,aAAa,kBAAkB,SAAyB,CAAC,CAAC,GAC3D,CAAC,eAAe,oBAAoB,yBAAoC,IAAI,IAAI,CAAC,GACjF,CAAC,oBAAoB,yBAAyB,yBAA8B,IAAI,IAAI,CAAC,GACrF,CAAC,uBAAuB,4BAA4B,yBAAsB,IAAI,IAAI,CAAC,GACnF,CAAC,eAAe,oBAAoB,SAA8B,IAAI,GACtE,CAAC,aAAa,kBAAkB,SAA8B,IAAI,GAClE,CAAC,eAAe,oBAAoB,SAAS,EAAK,GAClD,CAAC,YAAY,iBAAiB,SAAS,EAAK,GAQ5C,gBAJ6B,cAE/B,MAAM,MAAM,QAAQ,QAAQ,UAAiC,MAAM,SAAS,MAAM,KAAK,CAAC,EAAA,CAE5D,QAC7B,UACC,MAAM,OACL,MAAM,WAAW,WAAW,MAAM,WAAW,eAAe,MAAM,WAAW,UAClF,GAEM,YAAY,cAAc;EAC9B,IAAM,oBAAoB,aAAa,KAAK,UAC1B,cAAc,IAAI,MAAM,EACjC,KAAW,KACnB,GAEK,uBAAuB,WAAyB,mBAChD,CAAC,UAAU,MAAM,CAAC,UAAU,GAAG,WAAW,aAAa,IAClD,KAEF,eAAe,MAAM,cAAc;GACxC,IAAM,cAAc,UAAU,SAAS,UAAU,MAC3C,kBAAkB,UAAU,kBAAkB,UAAU;GAc9D,OAbI,CAAC,eAAe,CAAC,kBACZ,KAEL,UAAU,WAAW,UAErB,UAAU,gBAAgB,oBAC1B,UAAU,gBAAgB,0BAC1B,UAAU,gBAAgB,kBAG1B,UAAU,WAAW;EAI3B,CAAC,GAGG,8BACJ,YACA,mBAEK,WAAW,KACZ,WAAW,GAAG,WAAW,aAAa,IACjC,oBAAoB,YAAY,cAAc,IAEhD,eAAe,MAAM,cAAc,UAAU,OAAO,WAAW,EAAE,IAJ7C,IAOvB,eAAe,YAAY,QAAQ,eACnC,WAAW,MAAM,WAAW,GAAG,WAAW,aAAa,IAClD,CAAC,oBAAoB,YAAY,iBAAiB,IAEpD,CAAC,2BAA2B,YAAY,iBAAiB,CACjE;EAED,OAAO,CAAC,GAAG,mBAAmB,GAAG,YAAY;CAC/C,GAAG;EAAC;EAAc;EAAa;CAAa,CAAC;CA2C7C,AAzCA,gBAAgB;EACd,IAAM,sCAAsB,IAAI,IAAY;EA2B5C,AAzBA,aAAa,SAAS,UAAU;GAC9B,AACE,MAAM,OACL,MAAM,gBAAgB,oBACrB,MAAM,gBAAgB,0BACtB,MAAM,gBAAgB,oBAExB,oBAAoB,IAAI,MAAM,EAAE;EAEpC,CAAC,GAED,YAAY,SAAS,cAAc;GACjC,IAAI,UAAU,MAAM,UAAU,GAAG,WAAW,aAAa,GAAG;IAC1D,IAAM,YAAY,aAAa,MAAM,OAAO;KAC1C,IAAM,cAAc,GAAG,SAAS,UAAU,MACpC,kBAAkB,GAAG,kBAAkB,UAAU;KACvD,OAAO,eAAe;IACxB,CAAC;IACD,AAAI,WAAW,MACb,oBAAoB,IAAI,UAAU,EAAE;GAExC;EACF,CAAC,GAGD,0BAA0B,SAAS;GACjC,IAAI,SAAS,IACP,UAAU,IAAI,IAAI,IAAI;GAO5B,OANA,oBAAoB,SAAS,OAAO;IAClC,AAAK,KAAK,IAAI,EAAE,MACd,QAAQ,IAAI,EAAE,GACd,SAAS;GAEb,CAAC,GACM,SAAS,UAAU;EAC5B,CAAC;CACH,GAAG,CAAC,cAAc,WAAW,CAAC,GAE9B,gBAAgB;EAEd,IADwB,UAAU,QAAQ,UAAU,MAAM,WAAW,WACjE,CAAA,CAAgB,WAAW,KAAK,CAAC,MAAM,WAAW,CAAC,MAAM,KAC3D;EAGF,IAAM,WAAW,YAAY,YAAY;GACvC,IAAI;IACF,IAAM,UAAU,MAAM,YAAY,KAAK;IACvC,IAAI,CAAC,SAAS;IAEd,IAAM,gBACJ,QAAQ,QAAQ,QAAQ,UAAiC,MAAM,SAAS,MAAM,KAAK,CAAC,GAEhF,uBACJ,WACA,sBAEI,CAAC,UAAU,MAAM,CAAC,UAAU,GAAG,WAAW,aAAa,IAClD,KAEF,kBAAkB,MAAM,cAAc;KAC3C,IAAM,cAAc,UAAU,SAAS,UAAU,MAC3C,kBAAkB,UAAU,kBAAkB,UAAU;KAc9D,OAbI,CAAC,eAAe,CAAC,kBACZ,KAEL,UAAU,WAAW,UAErB,UAAU,gBAAgB,oBAC1B,UAAU,gBAAgB,0BAC1B,UAAU,gBAAgB,kBAG1B,UAAU,WAAW;IAI3B,CAAC,GAGG,sCAAsB,IAAI,IAAY;IAC5C,cAAc,SAAS,UAAU;KAC/B,AACE,MAAM,OACL,MAAM,gBAAgB,oBACrB,MAAM,gBAAgB,0BACtB,MAAM,gBAAgB,oBAExB,oBAAoB,IAAI,MAAM,EAAE;IAEpC,CAAC;IAED,IAAM,yBAAyB,WAAyB,eAC/C,WAAW,MAAM,OAAO;KAC7B,IAAM,cAAc,GAAG,SAAS,UAAU,MACpC,kBAAkB,GAAG,kBAAkB,UAAU;KACvD,OAAO,eAAe;IACxB,CAAC;IA4BH,AAzBA,gBAAgB,SACP,KAAK,QAAQ,cAAc;KAChC,IAAI,UAAU,MAAM,UAAU,GAAG,WAAW,aAAa,GAAG;MAC1D,IAAM,WAAW,oBAAoB,WAAW,aAAa;MAC7D,IAAI,UAAU;OACZ,IAAM,YAAY,sBAAsB,WAAW,aAAa;OAChE,AAAI,WAAW,OACb,oBAAoB,IAAI,UAAU,EAAE,GACpC,uBAAuB,cAAc;QACnC,IAAM,YAAY,UAAU,IAAI,UAAU,EAAE;QAC5C,IAAI,WAAW;SACb,IAAM,SAAS,IAAI,IAAI,SAAS;SAEhC,OADA,OAAO,IAAI,UAAU,IAAI,SAAS,GAC3B;QACT;QACA,OAAO;OACT,CAAC;MAEL;MACA,OAAO,CAAC;KACV;KACA,OAAO;IACT,CAAC,CACF,GAEG,oBAAoB,OAAO,KAC7B,0BAA0B,YAAY;KACpC,IAAM,UAAU,IAAI,IAAI,OAAO;KAE/B,OADA,oBAAoB,SAAS,OAAO,QAAQ,IAAI,EAAE,CAAC,GAC5C;IACT,CAAC;GAEL,SAAS,OAAO;IACd,QAAQ,MAAM,iCAAiC,KAAK;GACtD;EACF,GAAG,GAAI;EAEP,aAAa,cAAc,QAAQ;CACrC,GAAG;EAAC;EAAW;EAAO;CAAW,CAAC;CAElC,IAAM,gBAAgB,UACnB,QACE,UACC,MAAM,WAAW,WAAW,MAAM,WAAW,eAAe,MAAM,WAAW,SACjF,CAAC,CACA,MAAM,GAAG,MAAM;EACd,IAAM,SAAS,mBAAmB,IAAI,EAAE,EAAE,KAAK,GACzC,SAAS,mBAAmB,IAAI,EAAE,EAAE,KAAK;EAE/C,IAAI,SAAS,KAAK,SAAS,GACzB,OAAO,SAAS;EAGlB,IAAI,SAAS,GAAG,OAAO;EACvB,IAAI,SAAS,GAAG,OAAO;EAEvB,IAAM,eAAe,EAAE,WAAW,aAC5B,eAAe,EAAE,WAAW;EAClC,IAAI,gBAAgB,CAAC,cAAc,OAAO;EAC1C,IAAI,CAAC,gBAAgB,cAAc,OAAO;EAE1C,IAAM,mBACH,EAAE,MAAM,EAAE,GAAG,WAAW,aAAa,KAAO,EAAE,MAAM,sBAAsB,IAAI,EAAE,EAAE,GAC/E,mBACH,EAAE,MAAM,EAAE,GAAG,WAAW,aAAa,KAAO,EAAE,MAAM,sBAAsB,IAAI,EAAE,EAAE;EAIrF,OAHI,oBAAoB,CAAC,mBAAyB,KAC9C,CAAC,oBAAoB,mBAAyB,IAE3C;CACT,CAAC,GAEG,iBAAiB,OAAO,UAAwB;EACpD,IAAK,MAAM,IAEX;yBAAsB,MAAM,EAAE;GAC9B,IAAI;IACF,MAAM,gBAAgB,QAAQ,OAAO,KAAK;GAC5C,SAAS,OAAO;IACd,MAAM,KAAK;KACT,OAAO;KACP,QAAQ;KACR,aAAa,iBAAiB,QAAQ,MAAM,UAAU;IACxD,CAAC;GAEH,UAAU;IACR,sBAAsB,IAAI;GAC5B;EAZ8B;CAahC,GAEM,gBAAgB,YAAY;EAChC,IAAI,CAAC,iBAAiB,CAAC,cAAc,IAAI;EAEzC,IAAM,QAAQ;EAEd,AADA,iBAAiB,IAAI,GACrB,mBAAmB,MAAM,EAAE;EAC3B,IAAI;GACF,IAAI,CAAC,MAAM,SAET,MAAU,MAAM,sBAAsB;GAuBxC,AArBA,MAAM,gBAAgB,QAAQ,MAAM,SAAS,MAAM,EAAE,GAGrD,MAAM,YAAY,KAAK,GAEvB,MAAM,KAAK;IACT,OAAO;IACP,QAAQ;GACV,CAAC,GAED,gBAAgB,SAAS,KAAK,QAAQ,MAAM,EAAE,OAAO,MAAM,EAAE,CAAC,GAC9D,kBAAkB,SAAS;IACzB,IAAM,SAAS,IAAI,IAAI,IAAI;IAE3B,OADA,OAAO,OAAO,MAAM,EAAE,GACf;GACT,CAAC,GACD,uBAAuB,SAAS;IAC9B,IAAM,SAAS,IAAI,IAAI,IAAI;IAE3B,OADA,OAAO,OAAO,MAAM,EAAE,GACf;GACT,CAAC,GACD,0BAA0B,SAAS;IACjC,IAAM,UAAU,IAAI,IAAI,IAAI;IAE5B,OADA,QAAQ,OAAO,MAAM,EAAE,GAChB;GACT,CAAC;EACH,SAAS,OAAO;GACd,MAAM,KAAK;IACT,OAAO;IACP,QAAQ;IACR,aAAa,iBAAiB,QAAQ,MAAM,UAAU;GACxD,CAAC;EAEH,UAAU;GACR,mBAAmB,IAAI;EACzB;CACF,GAEM,kBAAkB,UAAwB;EAO9C,AANA,gBAAgB,SAAS,CAAC,GAAG,MAAM,KAAK,CAAC,GACzC,uBAAuB,SAAS;GAC9B,IAAM,SAAS,IAAI,IAAI,IAAI;GAE3B,OADA,OAAO,IAAI,MAAM,IAAI,KAAK,OAAO,CAAC,GAC3B;EACT,CAAC,GACD,iBAAiB,EAAK;CACxB,GAEM,oBAAoB,OAAO,cAA4B,eAAwB;EAyCnF,AAxCI,eACF,gBAAgB,SAAS,KAAK,QAAQ,MAAM,EAAE,OAAO,UAAU,CAAC,GAChE,kBAAkB,SAAS;GACzB,IAAM,SAAS,IAAI,IAAI,IAAI;GAE3B,OADA,OAAO,OAAO,UAAU,GACjB;EACT,CAAC,GACD,uBAAuB,SAAS;GAC9B,IAAM,SAAS,IAAI,IAAI,IAAI;GAE3B,OADA,OAAO,OAAO,UAAU,GACjB;EACT,CAAC,GACD,0BAA0B,SAAS;GACjC,IAAM,UAAU,IAAI,IAAI,IAAI;GAE5B,OADA,QAAQ,OAAO,UAAU,GAClB;EACT,CAAC,IAGkB,YAAY,MAAM,MAAM,EAAE,OAAO,aAAa,EAE/D,IACF,gBAAgB,SAAS,KAAK,KAAK,MAAO,EAAE,OAAO,aAAa,KAAK,eAAe,CAAE,CAAC,IAEvF,kBAAkB,SAAS;GACzB,IAAM,SAAS,IAAI,IAAI,IAAI;GAE3B,OADA,OAAO,IAAI,aAAa,IAAI,YAAY,GACjC;EACT,CAAC,GAGH,uBAAuB,SAAS;GAC9B,IAAM,SAAS,IAAI,IAAI,IAAI;GAE3B,OADA,OAAO,IAAI,aAAa,IAAI,KAAK,OAAO,CAAC,GAClC;EACT,CAAC,GAED,eAAe,IAAI,GAGnB,MAAM,YAAY,KAAK;CACzB,GAEM,uBAAuB,UACvB,MAAM,MAAM,MAAM,GAAG,WAAW,aAAa,KAG7C,MAAM,MAAM,sBAAsB,IAAI,MAAM,EAAE,KAIhD,MAAM,gBAAgB,0BACtB,MAAM,gBAAgB,oBACtB,MAAM,gBAAgB,kBAEf,mBAEL,MAAM,gBAAgB,aACjB,aAEF;CAGT,IAAI,cAAc,WAAW,KAAK,CAAC,eACjC,OACE,qBAAC,OAAD;EAAO,KAAK;EAAZ,UAAA;GACE,oBAAC,MAAD;IAAM,SAAQ;IACZ,UAAA,oBAAC,QAAD;KACE,MAAM;KACN,MAAK;KACL,MAAK;KACL,eAAe,iBAAiB,EAAI;IACrC,CAAA;GACG,CAAA;GACN,oBAAC,MAAD;IAAM,SAAS;IAAG,QAAQ;IAAG,MAAK;IAAc,QAAA;IAC9C,UAAA,oBAAC,MAAD;KAAM,MAAM;KAAG,OAAA;KAAM,UAAA;IAEf,CAAA;GACF,CAAA;GACL,iBACC,oBAAC,kBAAD;IACS;IACP,OAAO;IACP,eAAe,iBAAiB,EAAK;GACtC,CAAA;EAEE;;CAIX,IAAM,kBACJ,kBAAkB,CAAC,aAAa,cAAc,MAAM,GAAG,CAAkB,IAAI,eACzE,gBAAgB,kBAAkB,cAAc,SAAS;CAE/D,OACE,qBAAC,OAAD;EAAO,KAAK;EAAZ,UAAA;GACE,oBAAC,MAAD;IAAM,SAAQ;IACZ,UAAA,oBAAC,QAAD;KACE,MAAM;KACN,MAAK;KACL,MAAK;KACL,eAAe,iBAAiB,EAAI;IACrC,CAAA;GACG,CAAA;GAEL,gBAAgB,KAAK,UACpB,oBAAC,WAAD;IAES;IACG;IACU;IACH;IACJ;IACQ;IACL;IACA;IACE;GACnB,GAVM,MAAM,EAUZ,CACF;GAEA,iBACC,oBAAC,MAAD;IAAM,SAAQ;IACZ,UAAA,oBAAC,QAAD;KACE,MAAM,aAAa,gBAAgB;KACnC,MACE,aAAa,cAAc,QAAQ,cAAc,SAAS,EAAmB;KAE/E,MAAK;KACL,MAAK;KACL,eAAe,cAAc,CAAC,UAAU;IACzC,CAAA;GACG,CAAA;GAGP,iBACC,oBAAC,QAAD;IACE,SAAA;IACA,IAAI;IACJ,QAAO;IACP,eAAe,iBAAiB,IAAI;IACpC,sBAAsB,iBAAiB,IAAI;IAC3C,OAAO;IAEP,UAAA,oBAAC,MAAD;KACE,SAAS;KACT,OAAO;MACL,WAAW;MACX,SAAS;MACT,YAAY;MACZ,gBAAgB;KAClB;KAEA,UAAA,qBAAC,OAAD;MAAO,KAAK;MAAZ,UAAA;OACE,qBAAC,SAAD;QAAS,MAAM;QAAf,UAAA;SAAkB;SAEf,cAAc,QAAQ,cAAc,iBAAiB;SAAW;QAC1D;;OACT,oBAAC,MAAD;QAAM,MAAM;QAAG,UAAA;OAAiC,CAAA;OAChD,oBAAC,OAAD;QAAO,KAAK;QAAG,SAAS;QACtB,UAAA,oBAAC,KAAD,EAAA,UACE,oBAAC,QAAD;SACE,MACE,oBAAoB,cAAc,KAChC,oBAAC,SAAD,EACE,OAAO;UACL,eAAe;UACf,SAAS;UACT,WAAW;UACX,OAAO;UACP,QAAQ;SACV,EACD,CAAA,IAED,oBAAC,WAAD,CAAY,CAAA;SAGhB,UAAU;SACV,SAAS;SACT,MAAK;SACL,MAAK;SACL,SAAS;SACT,UAAU,oBAAoB;QAC/B,CAAA,EACE,CAAA;OACA,CAAA;MACF;;IACH,CAAA;GACA,CAAA;GAGT,iBACC,oBAAC,kBAAD;IACS;IACP,OAAO;IACP,eAAe,iBAAiB,EAAK;GACtC,CAAA;GAGF,eACC,oBAAC,mBAAD;IACS;IACP,OAAO;IACP,UAAU;IACV,eAAe,eAAe,IAAI;GACnC,CAAA;EAEE;;AAEX;AC1tBA,MAAM,qBAAqB,cAAuC;CAChE,aAAa;CACb,sBACS;AAEX,CAAC,GAMY,uBAAA,OAImB;eAJI,EAClC,aACA,gBACA,aAHkCC,IAKLC;CAAC,AAAA,EAAA,OAAA,eAAA,EAAA,OAAa,kBAAd,KAAA;EAAC;EAAa;CAAc,GAA3B,EAAA,KAAA,aAAa,EAAA,KAAA;CAA3C,IAAM,QAAQC,IACPC;CAAP,OAAmD,EAAA,OAAA,YAAA,EAAA,OAAR,SAApC,KAAA,oBAACC,mBAAAA,UAAD;EAAoC;EAAQ;CAAsC,CAAA,GAAtC,EAAA,KAAA,UAAR,EAAA,KAAA,+BAApCD;AACT,GAEa,8BACK,WAAW,kBACpB;;;;AClBT,SAAgB,YAAY,EAAC,QAAQ,iBAA8C;CACjF,IAAM,eAAe,IAAI,gBAAgB;CAEzC,IAAI,cAAc,WAAW,YAAY,cAAc,WAAW,OAAO;EACvE,IAAM,QAAQ,YAAY,QAAQ,cAAc,IAAI,GAAG;EACvD,aAAa,IAAI,SAAS,KAAK;CACjC;CAEA,OAAO,0BAA0B,cAAc,GAAG,QAAQ;AAC5D;ACXA,SAAwB,eAAA,IAA+B;eAAhB,EAAC,UAADG,IAC/B,EAAC,mBAAkB,sBAAsB,GACzC,WAAW,iBAAiB,MAAM,KAGgBC;CAAM,AAAA,EAAA,OAAA,8BAAN,WAAM,eAAe,EAAK,GAApB,EAAA,KAAA;CAC1DC,IAAAA;CAC4B,AAAA,EAAA,OAAA,qBAD5B,KAAA,oBAAC,OAAD;EAAO,SAAS;EACd,UAAA,oBAAC,mBAAD,EAA0B,MAAQ,CAAA;CAC7B,CAAA,GADqB,EAAA,KAAA;CAF9BC,IAAAA;CADF,OACc,EAAA,OAAA,YAAA,EAAA,OAA0CF,MAAAA,EAAAA,OACpDC,MADF,KAAA,oBAAC,QAAD;EAAQ,IAAI;EAAU,QAAO;EAAgB,SAASD;EAA6B,OAAO;EACxFC,UAAAA;CAGM,CAAA,GAJI,EAAA,KAAA,UAA0CD,EAAAA,KAAAA,IACpDC,EAAAA,KAAAA,4BADFC;AAMJ;ACrBA,SAAgB,cAAc,SAAyB;CACrD,IAAI,OAAO,WAAY,YAAY,OAAO,MAAM,OAAO,GACrD,OAAO;CAGT,IAAM,MAAM,CAAC,EAAE,UAAU,OACnB,OAAO,CAAC,EAAG,UAAU,OAAQ,KAC7B,OAAO,CAAC,CAAC,UAAU,IAGrB,MAAM;CAQV,OANI,MAAM,MACR,OAAO,KAAK,MAAM,OAAO,OAAO,KAAK,MAAM,MAG7C,OAAO,KAAK,OAAO,OAAO,OAAO,KAAK,MAAM,KAC5C,OAAO,KAAK,MACL;AACT;AAGA,SAAgB,sBAAsB,SAAyB;CAW7D,OAAO,GAVK,KAAK,MAAM,UAAU,IAAI,CAAC,CACnC,SAAS,CAAC,CACV,SAAS,GAAG,GAQL,EAAI,GAPD,KAAK,MAAO,UAAU,OAAQ,EAAE,CAAC,CAC3C,SAAS,CAAC,CACV,SAAS,GAAG,GAKE,EAAK,GAJT,KAAK,MAAM,UAAU,EAAE,CAAC,CAClC,SAAS,CAAC,CACV,SAAS,GAAG,GAEU;AAC3B;AAGA,SAAgB,kBAAkB,MAAc;CAE9C,OAAO,qDAAM,KAAK,IAAI,KAAK,SAAS;AACtC;AAGA,SAAgB,yBAAyB,MAAsB;CAC7D,IAAM,CAAC,KAAK,GAAG,KAAK,GAAG,KAAK,KAAK,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM;CAC3D,OAAO,KAAK,OAAO,KAAK,KAAK;AAC/B;AC5BA,SAAwB,oBAAA,IAAqD;gBAAjC,EAAC,OAAO,aAAA,OAARE,IAAQ,cAAA,OAAA,KAAA,IAAc,IAAdC,IAC5C,SAASqB,YAAU,GAEnB,EAAC,mBAAkB,sBAAsB,GACzC,WAAW,sBAAsB,MAAM,KAEcpB;CACnC,AAAA,EAAA,OAAA,2BADmC,WACzD,sBAAsB,WAAW,GAAX,EAAA,KAAA;CADxB,IAAM,CAAC,eAAe,oBAAoB,SAAiBA,EAE3D,GACM,CAAC,UAAU,eAAe,SAAiB,WAAW,GACtD,CAAC,YAAY,iBAAiB,SAAiB,EAAE,GAEVC;CAAI,AAAA,EAAA,OAAA,SAAA,EAAA,OAAkB,YAAtB,KAAA;EAAC,GAAG;EAAO,WAAW;CAAQ,GAA1B,EAAA,KAAA,OAAkB,EAAA,KAAA;CAAnE,IAAM,wBAAwBC,IACxB,CAAC,QAAQ,aAAa,SAAS,EAAK,GACpC,CAAC,oBAAoB,yBAAyB,SAAuB,IAAI,GAC5DC;CAGFC,AAAAA,EAAAA,OAAAA,MAAAA,OAAAA,EAAAA,OADf,UAAA,EAAA,OAEmB,YAAA,EAAA,OAEL,kBANG,WAAM;EAEvB,AADA,UAAU,EAAI,GACd,OACG,MAAM,MAAM,GAAG,CAAC,CAChB,IAAI,EAAC,WAAW,SAAQ,CAAC,CAAC,CAC1B,OAAO,EAAC,iBAAiB,GAAK,CAAC,CAAC,CAChC,WAAW,eAAe,EAAK,CAAC,CAAC,CACjC,MAAM,qBAAqB,CAAC,CAC5B,cAAc,UAAU,EAAK,CAAC;CACnC,GANiBA,EAAAA,KAAAA,MAAAA,KADf,EAAA,KAAA,QAEmB,EAAA,KAAA,UAEL,EAAA,KAAA;CANhB,IAAM,aAAaD,IAUCE;sDAAoB,KAAA,oBAAA,EAAC,QAAQ,EAAC,CAAC;CAAnD,IAAM,QAAQ,MAAMA;CAEpB,IAAI,oBAEF,MAAM;CAGkBC,IAAAA;sDAAC,MAAA,UAAyC;EAClE,IAAM,QAAQ,MAAM,cAAc;EAGlC,IAFA,iBAAiB,KAAK,GAElB,kBAAkB,KAAK,GAAG;GAC5B,cAAc,EAAE;GAChB,IAAM,eAAe,yBAAyB,KAAK;GACnD,YAAY,YAAY;EAC1B,OACE,cAAc,qBAAqB;CAEvC;CAXA,IAAM,oBAAoBA,IAiBbC;CAAM,AAAA,EAAA,QAAA,+BAAN,WAAM,eAAe,EAAK,GAApB,EAAA,MAAA;CAKC,IAAA,KAAA,eAAe,IAH7BC;CAOa,AAAA,EAAA,QAAA,cAAA,EAAA,QADA,UAAA,EAAA,QAHCC,MAHd,KAAA,oBAAC,OAAD;EAAO,SAAS;EACd,UAAA,oBAAC,QAAD;GAEE,UAAUA;GACV,MAAK;GACL,MAAK;GACL,SAAS;GACT,SAAS;GACT,MAAK;EACN,GAPK,WAOL;CACI,CAAA,GAHM,EAAA,MAAA,YADA,EAAA,MAAA,QAHCA,EAAAA,MAAAA;CAYZC,IAAAA;sDAAC,MAAA,oBAAA,MAAD;EAAM,MAAM;EAAG,QAAO;EACpB,UAAA;CACI,CAAA;CAHRC,IAAAA;CAIyB,AAAA,EAAA,QAAA,uBAJzB,MAAA,qBAAC,OAAD;EAAO,KAAK;EAAZ,UAAA,CACED,KAGA,oBAAC,gBAAD;GAAuB;GAAc;GAAO,aAAA;EAAa,CAAA,CACpD;KADkB,EAAA,MAAA;CAGvBE,IAAAA;sDAAC,MAAA,oBAAA,MAAD;EAAM,MAAM;EAAG,QAAO;EACpB,UAAA;CACI,CAAA;CAHRC,IAAAA;CAIyB,AAAA,EAAA,QAAA,uCAJzB,MAAA,qBAAC,OAAD;EAAO,KAAK;EAAZ,UAAA,CACED,KAGA,oBAAC,gBAAD;GAAgB,OAAO;GAA8B;GAAO,aAAA;EAAa,CAAA,CACpE;KADkB,EAAA,MAAA;CAGzBE,IAAAA;sDAAC,MAAA,oBAAA,OAAD;EAAO,KAAK;EACV,UAAA,oBAAC,MAAD;GAAM,OAAO;GAAU,SAAS;GAC9B,UAAA,oBAAC,MAAD;IAAM,MAAM;IAAG,QAAO;IACpB,UAAA;GACI,CAAA;EACF,CAAA;CACD,CAAA;CAGLC,IAAAA;sDAAC,MAAA,oBAAA,MAAD;EAAM,MAAM;EAAG,QAAO;EACpB,UAAA;CACI,CAAA;CAHRC,IAAAA;CASoB,AAAA,EAAA,QAAA,cAAA,EAAA,QAHT,iBANX,MAAA,qBAAC,OAAD;EAAO,KAAK;EAAZ,UAAA,CACED,KAGA,oBAAC,WAAD;GACE,MAAM;GACN,OAAO;GACP,aAAY;GACZ,UAAU;GACV,gBAAgB;EACjB,CAAA,CACI;KAFa,EAAA,MAAA,YAHT,EAAA,MAAA;CA5BbE,IAAAA;CACEN,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAMAE,OAAAA,EAAAA,QAeAG,OAtBF,MAAA,qBAAC,OAAD;EAAO,KAAK;EAAG,SAAS;EAAxB,UAAA;GACEL;GAMAE;GAOAC;GAQAE;EAYK;KAjCLL,EAAAA,MAAAA,KAMAE,EAAAA,MAAAA,KAeAG,EAAAA,MAAAA;CAxCJE,IAAAA;CADF,OAEQ,EAAA,QAAA,YAAA,EAAA,QAiBJD,OAAAA,EAAAA,QAfSV,MAAAA,EAAAA,QAEPC,MALJ,MAAA,oBAAC,QAAD;EACE,IAAI;EACJ,QAAO;EACP,SAASD;EACT,QACEC;EAaFS,UAAAA;CAmCM,CAAA,GApDF,EAAA,MAAA,UAiBJA,EAAAA,MAAAA,KAfSV,EAAAA,MAAAA,IAEPC,EAAAA,MAAAA,gCALJU;AAuDJ;ACtHA,SAAgB,UAAU,OAAgC;eAGpDG;qDAAC,KAAA,oBAAA,QAAD;EACE,MAAK;EACL,OAAO,EAAC,SAAS,OAAM;EACvB,GAAE;CACH,CAAA;CALHC,IAAAA;CADF,OAC2F,EAAA,OAAA,qBAAzF,KAAA,oBAAC,OAAD;EAAK,OAAM;EAA6B,OAAM;EAAM,QAAO;EAAM,SAAQ;EAAY,GAAI;EACvFD,UAAAA;CAKG,CAAA,GANoF,EAAA,KAAA,mBAAzFC;AAQJ;;;;;ACOA,SAAwB,gBAAA,IAAyC;gBAAzB,EAAC,OAAO,YAARE,IAChC,EAAC,mBAAkB,sBAAsB,GACzC,WAAW,kBAAkB,MAAM,KAEzBC;CACd,AAAA,EAAA,OAAA,WAAA,EAAA,OACA,kBAFc,WAAM;EAEpB,AADA,UAAU,GACV,eAAe,EAAK;CACtB,GAFE,EAAA,KAAA,SACA,EAAA,KAAA;CAFF,IAAM,UAAUA,IAKDC;CAAmB,AAAA,EAAA,OAAA,qBAAnB,KAAA,mBAAmB,KAAK,GAAL,EAAA,KAAA;CAAlC,IAAM,SAASA,IACT,kBAAkB,WAAW,eAAe,WAAW,SAYpDC;yCAAmB,KAAA,mBAAA,oBAAC,sBAAD,CAAuB,CAAA,GAA1C,EAAA,KAAA;CACDC,IAAAA;CAAkB,AAAA,EAAA,OAAA,qBAAlB,KAAA,oBAAC,WAAD;EAAkB;EAAO,iBAAiB;CAAQ,CAAA,GAAhC,EAAA,KAAA;CAHtBC,IAAAA;CAEKF,AAAAA,EAAAA,OAAAA,MAAAA,EAAAA,QACDC,MAHJ,KAAA,oBAAC,KAAD;EAAK,SAAS;EACZ,UAAA,qBAAC,OAAD;GAAO,KAAK;GAAZ,UAAA,CACGD,IACDC,EACK;;CACJ,CAAA,GAHAD,EAAAA,KAAAA,IACDC,EAAAA,MAAAA;CAVNE,IAAAA;CADF,OAIa,EAAA,QAAA,WAAA,EAAA,QAFL,YAAA,EAAA,QAMJD,MAPF,KAAA,oBAAC,QAAD;EACE,IAAI;EACJ,QAAO;EACP,SAAS;EACT,SAAS;EACT,OAAO;EAEPA,UAAAA;CAMM,CAAA,GAVG,EAAA,MAAA,SAFL,EAAA,MAAA,UAMJA,EAAAA,MAAAA,8BAPFC;AAeJ;ACzBA,SAAwB,YAAY,EAClC,OACA,iBAAiB,KACjB,UACA,WACA,GAAG,SAQF;CACD,IAAM,SAASE,YAAU,GACnB,EAAC,gBAAe,sBAAsB,GAEtC,UAAU,aAAa,KAAK,GAC5B,YAAY,OAA+B,IAAI,GAC/C,qBAAqB,OAAuB,IAAI,GAChD,CAAC,OAAO,YAAY,SAAgB,GAGpC,aAAa,cAAc;EAC/B,IAAI;GACF,OAAO,cAAc,OAAO;IAAC;IAAU;IAAU;GAAK,CAAC;EACzD,SAAS,GAAG;GAEV,SAAa,UAAU,4BAA4B,EAAC,OAAO,EAAC,CAAC,CAAC;GAC9D;EACF;CACF,GAAG,CAAC,KAAK,CAAC,GAEJ,gBAAgB,cAAc;EAClC,IAAK,YACL,OAAO,sBAAsB,OAAO,UAAU;CAChD,GAAG,CAAC,OAAO,UAAU,CAAC,GAEhB,MAAM,cAAc;EACxB,IAAK,cACA,eACL,OAAO,qBACC,YAAY;GAAC;GAAe;EAAM,CAAC,IACxC,MAAa;GACZ,SAAS,CAAC;EAEZ,CACF;CACF,GAAG;EAAC;EAAe;EAAY;CAAM,CAAC,GAEhC,SAAS,cACN,qBACC,aAAa;EAAC;EAAO;EAAQ,OAAO;CAAc,CAAC,IACxD,MAAa;EACZ,SAAS,CAAC;CAEZ,CACF,GACC;EAAC;EAAO;EAAQ;CAAc,CAAC,GAE5B,cAAc,cAAc;EAChC,IAAI;GAEF,OAAO,IADS,IAAI,GACb,CAAA,CAAI,aAAa,IAAI,OAAO;EACrC,QAAQ;GACN;EACF;CACF,GAAG,CAAC,GAAG,CAAC,GACF,WAAW,cAAc;EAC7B,IAAK,cACD,eAAe,WAAW,OAE9B,OAAO,qBACC,YAAY,QAAQ,YAAY,GAAG,IACxC,MAAa;GACZ,SAAS,CAAC;EAEZ,CACF;CACF,GAAG;EAAC;EAAQ,eAAe;EAAQ;CAAU,CAAC,GACxC,SAOU,cAAc;EAC5B,IAAI;GACF,IAAM,gBAKF;IACF,UAAU,KAAA;IACV,WAAW,KAAA;IACX,YAAY,KAAA;IACZ,KAAK,KAAA;GACP;GAYA,OAVI,gBACF,cAAc,WAAW,aACzB,cAAc,YAAY,aAC1B,cAAc,aAAa,cAGzB,aACF,cAAc,MAAM,WAGf,EAAC,GAAG,cAAa;EAC1B,QAAQ;GACN;EACF;CACF,GAAG,CAAC,aAAa,QAAQ,CAAC,GAEpB,CAAC,OAAO,WAAW,OAAO,MAAM,gBAAgB,OAAA,CAAQ,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM,GAC7E,oBACJ,MAAM,qBAAqB,OAAO,MAAM,KAAK,IAAI,KAAK,IAAI,QAAS,SACjE,cAAc,KAAK,IAAI,MAAkB,iBAAiB;CAU9D,OATI,YACF,cAAc,MAAM,mBAEhB,MAAM,mBAAmB,MAAA,IAO7B,qBAAAC,UAAA,EAAA,UAAA;EACE,qBAAC,MAAD;GACE,KAAK;GACL,MAAK;GACL,OAAO;IACQ;IACb,UAAU;IACV,GAAI,WAAW;KAAC,SAAS;KAAQ,YAAY;IAAU;GACzD;GAPF,UAAA;IASG,OAAO,UACN,qBAAAA,UAAA,EAAA,UAAA,CACG,WACC,oBAAC,WAAD,EACE,OAAO;KACL,SAAS;KACT,OAAO;KACP,QAAQ;KACR,UAAU;KACV,KAAK;KACL,MAAM;KACN,QAAQ;IACV,EACD,CAAA,GAEH,qBAAC,UAAD;KAAU,UAAU;KAApB,UAAA,CACE,oBAAC,WAAD;MACE,QAAQ,UAAU,KAAA,IAAY;MAC9B,KAAK;MACL,GAAI;MACJ,aAAA;MACY;MACJ;MACR,SAAQ;MACR,aAAY;MACZ,UAAU;OACR,aAAa;OACb,gBAAA;OACA,WAAW;MACb;MACA,OAAO;MACP,YAAY;MACZ,OAAO;OACL,GAAI,CAAC,WAAW,EAAC,QAAQ,OAAM;OAC/B,OAAO;OACP,SAAS;OACT,WAAW;OACX,GAAI,WAAW,EAAC,WAAW,MAAK;MAClC;KACD,CAAA,GACA,QACO;IACV,CAAA,CAAA,EAAA,CAAA;IAEH,QACC,oBAAC,OAAD;KACE,OAAO;MACL,UAAU;MACV,KAAK;MACL,MAAM;MACN,WAAW;KACb;KAEA,UAAA,qBAAC,MAAD;MAAM,OAAA;MAAN,UAAA,CACE,oBAAC,kBAAD,EAAkB,OAAO,EAAC,aAAa,SAAQ,EAAI,CAAA,GAClD,OAAO,SAAU,YAAY,aAAa,SAAS,OAAO,MAAM,WAAY,WACzE,MAAM,UACN,qBACA;;IACH,CAAA,IACH;IACH;GACG;;EAEL,gBAAgB,oBACf,oBAAC,qBAAD;GACS;GAEP,aAAa,WAAW,SAAS;EAClC,CAAA;EAEF,gBAAgB,mBAAmB,oBAAC,gBAAD,EAAuB,MAAQ,CAAA;EAClE,gBAAgB,eAAe,oBAAC,iBAAD,EAAwB,MAAQ,CAAA;CAChE,EAAA,CAAA;AAEN;AAEA,SAAgB,aAAa,OAA2B;CACtD,OAAO,MAAM,MAAM,0BAA0B;AAC/C;ACvOA,MAAM,0BAA0B,IAAY,cAAsB;CAChE,OACE,qBAAC,MAAD,EAAA,UAAA,CAAI,6BACuB,oBAAC,QAAD,EAAA,UAAO,SAAe,CAAA,CAC7C,EAAA,CAAA;CAEN,UACE,qBAAC,MAAD,EAAA,UAAA,CAAI,cACQ,oBAAC,QAAD,EAAA,UAAO,GAAS,CAAA,CACxB,EAAA,CAAA;CAEN,aAAa,oBAAC,oBAAD,CAAqB,CAAA;AACpC;AAEA,SAAgB,kBAAkB,OAA+B;eACzD,EAAC,QAAQ,UAAS,OAGIC;CAA6BC,AAAAA,EAAAA,OAAAA,MAAAA,OAAAA,EAAAA,OAAWC,MAAAA,SAAxC,KAAA,uBAAuB,MAAM,KAAK,MAAM,KAAK,GAAhBD,EAAAA,KAAAA,MAAAA,KAAWC,EAAAA,KAAAA,MAAAA;CAAlEC,IAAAA;CADF,OACoF,EAAA,OAAA,UAAA,EAAA,OAAxDH,MAA1B,KAAA,oBAAC,sBAAD;EAAsB,GAAIA;EAAwD;CAAS,CAAA,GAAT,EAAA,KAAA,QAAxDA,EAAAA,KAAAA,4BAA1BG;AAEJ;ACxBA,SAAgB,QAAA,IAA8B;eAAtB,EAAC,SAADE,IACgBC;qDAAC,KAAA,EAAA,mBAAmB,GAAI;CAA9D,IAAM,UAAU,gBAAgB,MAAMA,EAAyB,GAExDC;CAAP,OAAoB,EAAA,OAAA,uBAAb,KAAA,oBAAC,QAAD;EAAM,OAAO;EAAU,UAAA;CAAc,CAAA,GAAxB,EAAA,KAAA,qBAAbA;AACT;ACFA,SAAgB,YAAY,OAAmE;gBACvF,EAAC,aAAY,OACb,YAAY,YAAY,gBAAgB,YAAY,SAAS,YAO7DE;CAEK,AAAA,EAAA,OAAA,YAAA,EAAA,OACW,aAHhB,KAAA,oBAAC,KAAD;EAAK,SAAS;EACZ,UAAA,oBAAC,MAAD;GAAM,MAAM;GACT,UAAA,WACC,qBAAAM,UAAA,EAAA,UAAA,CAAE,WAAQ,aAAa,oBAAC,SAAD,EAAS,MAAM,UAAY,CAAA,CAAI,EAAA,CAAA,IAEtD,oBAAAA,UAAA,EAAA,UAAE,uBAAsB,CAAA;EAEtB,CAAA;CACH,CAAA,GANA,EAAA,KAAA,UACW,EAAA,KAAA;CAQmB,IAAA,KAAA,CAAC,UAAiB,KAAA,CAAC,UACtDL;qDAAC,KAAA,oBAAA,UAAD,CAAW,CAAA;CADbC,IAAAA;CAAqCC,AAAAA,EAAAA,OAAAA,MAAAA,EAAAA,OAAkBA,MAAvD,KAAA,oBAAC,cAAD;EAAc,MAAK;EAAU,QAAQA;EAAW,OAAOA;EAAW,MAAM;EACtEF,UAAAA;CACY,CAAA,GAFuBE,EAAAA,KAAAA,IAAkBA,EAAAA,KAAAA;CAfzDC,IAAAA;CADF,OAKMJ,EAAAA,OAAAA,MAAAA,EAAAA,OAWFE,MAfF,KAAA,oBAAC,SAAD;EACE,SAAA;EACA,QAAA;EACA,SACEF;EAWFE,UAAAA;CAGO,CAAA,GAdLF,EAAAA,KAAAA,IAWFE,EAAAA,KAAAA,4BAfFE;AAoBJ;ACxBA,SAAgB,gBAAgB,OAAmE;gBAC3F,EAAC,aAAY,OACb,YAAY,YAAY,gBAAgB,YAAY,SAAS,YAO7DG;CAEK,AAAA,EAAA,OAAA,YAAA,EAAA,OACc,aAHnB,KAAA,oBAAC,KAAD;EAAK,SAAS;EACZ,UAAA,oBAAC,MAAD;GAAM,MAAM;GACT,UAAA,WACC,qBAAAM,UAAA,EAAA,UAAA,CAAE,cAAW,aAAa,oBAAC,SAAD,EAAS,MAAM,UAAY,CAAA,CAAI,EAAA,CAAA,IAEzD,oBAAAA,UAAA,EAAA,UAAE,gBAAe,CAAA;EAEf,CAAA;CACH,CAAA,GANA,EAAA,KAAA,UACc,EAAA,KAAA;CAQiB,IAAA,KAAA,CAAC,UAAiB,KAAA,CAAC,UACvDL;qDAAC,KAAA,oBAAA,aAAD,CAAc,CAAA;CADhBC,IAAAA;CAAsCC,AAAAA,EAAAA,OAAAA,MAAAA,EAAAA,OAAkBA,MAAxD,KAAA,oBAAC,cAAD;EAAc,MAAK;EAAW,QAAQA;EAAW,OAAOA;EAAW,MAAM;EACvEF,UAAAA;CACY,CAAA,GAFwBE,EAAAA,KAAAA,IAAkBA,EAAAA,KAAAA;CAf1DC,IAAAA;CADF,OAKMJ,EAAAA,OAAAA,MAAAA,EAAAA,OAWFE,MAfF,KAAA,oBAAC,SAAD;EACE,SAAA;EACA,QAAA;EACA,SACEF;EAWFE,UAAAA;CAGO,CAAA,GAdLF,EAAAA,KAAAA,IAWFE,EAAAA,KAAAA,4BAfFE;AAoBJ;ACLA,MAAM,wBAAwB;CAC5B,UAAU;CACV,WAAW;CACX,UAAU;AACZ;AAEA,SAAgB,gBAAgB,OAA6B;gBACrD,EAAC,MAAM,QAAQ,UAAU,YAAY,UAAS,OAC9C,QACH,SAAS,MAAMkf,KAAQ,KAAK,eAAe,MAAMA,KAAQ,KAC1D,SAAS,MAAMA,KAAQ,KACvB,SAAS,MAAMA,KAAQ,IACnB,MAAMA,QACN,MAGE/e;CAAgCC,AAAAA,EAAAA,OAAAA,MAAAA,wBAAAA,EAAAA,OAAsB,cAAA,EAAA,OAAkBC,MAAAA,OAAxE,KAAA,0BAA0B,MAAM,sBAAsB,YAAY,MAAM,GAAG,GAA3CD,EAAAA,KAAAA,MAAAA,sBAAsB,EAAA,KAAA,YAAkBC,EAAAA,KAAAA,MAAAA;CAGhF,IAAM,EAAC,UAAU,UAAU,cAAa,cACtCO,IACA,qBACF,GAEeL;CAGgB,AAAA,EAAA,OAAA,aAAA,EAAA,OAAA,YAAA,EAAA,OAD1B,YAAA,EAAA,OAEsB,YAJZ,KAAA,YAAY,OACzB,qBAAC,QAAD;EAAQ,KAAK;EAAb,UAAA;GACG,YAAY,SAAS,SAAS,KAAK,oBAAC,yBAAD,EAAmC,SAAW,CAAA;GAClF,oBAAC,iBAAD,EAAiB,UAAU,SAAW,CAAA;GACtC,oBAAC,aAAD,EAAa,UAAU,SAAW,CAAA;EAC5B;KALK,EAAA,KAAA,WAGgB,EAAA,KAAA,UAD1B,EAAA,KAAA,UAEsB,EAAA,KAAA;CAJ3B,IAAM,SAASA,IAUNC;CAAuC,AAAA,EAAA,OAAA,YAAA,EAAA,QAAV,YAAA,EAAA,QAA+B,SAA5D,KAAA,4BAA4B;EAAC;EAAU;EAAU,UAAU,EAAC,MAAK;CAAC,CAAC,GAA5B,EAAA,KAAA,UAAV,EAAA,MAAA,UAA+B,EAAA,MAAA;CAA5D,IAAA,KAAA,IADPC;CADF,OAIU,EAAA,QAAA,QAAA,EAAA,QADS,aAAA,EAAA,QAEP,UAAA,EAAA,QACA,UAAA,EAAA,QAJHC,MADP,KAAA,oBAAC,sBAAD;EACE,GAAKA;EACL,eAAe;EACT;EACE;EACA;CACT,CAAA,GAHO,EAAA,MAAA,MADS,EAAA,MAAA,WAEP,EAAA,MAAA,QACA,EAAA,MAAA,QAJHA,EAAAA,MAAAA,8BADPD;AAQJ;;;;;ACnDA,SAAS,oBACP,MACA,YACA,aACkC;CAKlC,OAJI,SAAS,KACJ,KAGF,QAAU,cAAc,WAAW,QAAiB,eAAe;AAC5E;AAEA,SAAgB,gBAAgB,OAA6B;gBACrD,EAAC,YAAY,iBAAgB,OAC7B,MAAM,cAAc,SAAS,cAAc,WAC3C,KAAK,aAAa,MAAM,IACxB,uBAAuB,wBAAwB,GAC/C,SAAS,UAAU,GACnB,mBAAmB,oBAAoB,EAAE,GACzC,gBAAgB,GAAQ,cAAc,WAAW,QAAQ,OAAO,IAAI,WAAW,IAAI,IAExEI;;EACf,IAAI,CAAC,KAAA;GAAK,KAAO;GAAP,MAAA;;EAEV,IAAI,CAAC,cAAc,CAAC,eAAe;GAC1BC,IAAAA;GAAP,AAAiC,EAAA,OAAA,mBAA1B,KAAA,oBAAC,mBAAD,EAAmB,OAAO,IAAM,CAAA,GAAN,EAAA,KAAA,iBAAjC,KAAOA;GAAP,MAAA;EACF;EAKUC,IAAAA;EAA+B,AAAA,EAAA,OAAA,0BAA/B,KAAA,oBAAoB,KAAA,GAAW,YAAY,YAAY,GAAxB,EAAA,KAAA;EAFvCC,IAAAA;EADF,AAMW,EAAA,OAAA,OAAA,EAAA,OACG,oBAAA,EAAA,OALY,wBAAA,EAAA,OAEV,cAAA,EAAA,OADND,MAFR,KAAA,oBAAC,iBAAD;GACwB;GACtB,MAAMA;GACM;GACZ,QAAO;GACP,OAAO;GACP,UAAU;EACX,CAAA,GAFQ,EAAA,KAAA,KACG,EAAA,KAAA,kBALY,EAAA,KAAA,sBAEV,EAAA,KAAA,YADNA,EAAAA,KAAAA,4BAHV,KACEC;;CARJ,IAAM,WAAWH,IAwBLI;CAAwBC,AAAAA,EAAAA,QAAAA,MAAb,aAAa,mBAAxB,KAAA,EAAC,IAAI,MAAM,aAAa,GAAE,GAAFA,EAAAA,MAAAA,MAAb,aAAa;CAJlCC,IAAAA;CADF,OAYK,EAAA,QAAA,YAAA,EAAA,QAPOF,MAJV,KAAA,oBAAC,aAAD;EACE,sBAAA;EACA,IAAI;EACJ,QAAO;EACP,QAAQA;EACR,WAAQ;EACR,WAAQ;EACR,SAAS;EACT,QAAQ;EACR,MAAK;EAEJ;CACU,CAAA,GADV,EAAA,MAAA,UAPOA,EAAAA,MAAAA,8BAJVE;AAcJ;ACnEA,MAAM,YAAY,OAAO,GAAG,CAAC,CAAA,WAAA;;;AAEf,CAAA,CAAA,YAAA,UAAe,MAAM,MAAM,OAAO,MAAM,KAAK,GAAG,0CAM5C,UAAe,MAAM,MAAM,OAAO,MAAM,KAAK,MAAM,GAAG,KAIlE,mBAGA,UAAU;gBACR,SAAS,UAAU;CACzB,IAAI,CAAC,MAAM,UAAU;EACZE,IAAAA;EAAP,2DAAQ,KAAA,oBAAA,YAAD,CAAa,CAAA,2BAAbA;CACT;CAEA,IAAI,CAAC,MAAM,YAAY,QAAQ;EAE3BC,IAAAA;EADF,2DACG,KAAA,oBAAA,MAAD;GAAM,QAAA;GAAO,QAAQ;GAAG,SAAS;GAC/B,UAAA,oBAAC,MAAD;IAAM,MAAM;IAAG,UAAA;GAAuC,CAAA;EAClD,CAAA,2BAFNA;CAIJ;CAIGC,IAAAA,IACEC;CAH+BC,IAAAA,EAAAA,OAAAA,MAAAA,cAAAA,EAAAA,OAIX,QAAA;EAJKC,IAAAA;EAAMD,AAAAA,EAAAA,OAAAA,MAAAA,0BAAN,KAAA,MAAM,cAAc,CAAC,GAAfA,EAAAA,KAAAA,MAAAA;EAApC,IAAM,gBAAgB,QAAQC,EAAsB;EAEjD,KAAA,WACE,KAAA,eAAe,KAAK,iBAAiB;GACpC,IAAM,aAAa,OAAO,IAAI,aAAa,IAAI;GAE/C,OACE,oBAAC,MAAD;IAEE,cAAc;IACd,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,OAAO,EAAC,UAAU,SAAQ;IAE1B,UAAA,oBAAC,KAAD,EAAA,UACE,oBAAC,iBAAD;KAA+B;KAA0B;IAAa,CAAA,EACnE,CAAA;GACD,GAVC,aAAa,EAUd;EAEV,CAAC,GApB+BD,EAAAA,KAAAA,MAAAA,YAIX,EAAA,KAAA;;CAFvBE,IAAAA;CADF,OACGJ,EAAAA,OAAAA,MAAAA,EAAAA,OACEC,MADH,KAAA,oBAACD,IAAD,EAAA,UACGC,GAkBQ,CAAA,GAnBVD,EAAAA,KAAAA,IACEC,EAAAA,KAAAA,8BADHG;AAqBJ;AC/CA,SAAwB,aAAA,IAYrB;gBAZkC,EACnC,OACA,YACA,mBACA,cACA,sBALmCE,IAa7B,SAASgB,YAAU,GACnB,CAAC,OAAO,YAAY,SAExB,oBAAoB,GAChB,CAAC,aAAa,kBAAkB,SAAS,EAAI,GAC7C,QAAQ,SAAS,GAEbf;CAIaC,AAAAA,EAAAA,OAAAA,YAAAA,UAAAA,EAAAA,OAHiB,qBAAA,EAAA,OAAlC,SADI,WAAM;EACd,AAAI,UAAU,wBAAwB,qBAGtC,SAAS,YAAY,SAAS,eAAe,SAAS;CACxD,GADuBA,EAAAA,KAAAA,YAAAA,QAHiB,EAAA,KAAA,mBAAlC,EAAA,KAAA;CAIHC,IAAAA;CALH,AAKW,EAAA,OAAA,cAAA,EAAA,OAAY,qBAAA,EAAA,OAAnB,SAAD,KAAA;EAAC;EAAO;EAAY;CAAiB,GAA7B,EAAA,KAAA,YAAY,EAAA,KAAA,mBAAnB,EAAA,KAAA,+BALJ,UAAUF,IAKPE,EAAsC;CAEzCC,IAAAA;CAI4C,AAAA,EAAA,OAAA,SAAA,EAAA,OAAR,UAAA,EAAA,QAAe,eAAA,EAAA,QAH7C,SAAA,EAAA,QAMF,qBAAA,EAAA,QADA,SANJ,KAAA,eAAe,gBAAgB;EAC7B,IAAI,UAAU,WAAW;EAEzB,SAAS,qBAAqB;EAC9B,IAAM,SAAS,MAAM,YAAY;GAAC;GAAQ;GAAO;EAAW,CAAC;EAC7D,AAAI,WAAW,MACb,MAAM,KAAK;GAAC,OAAO;GAA8B,QAAQ;EAAS,CAAC,GACnE,kBAAkB,KACT,WAAW,gBACpB,MAAM,KAAK;GACT,OAAO;GACP,aAAa;GACb,QAAQ;EACV,CAAC,GACD,kBAAkB,MAElB,MAAM,KAAK;GAAC,OAAO;GAAyB,QAAQ;EAAO,CAAC,GAE5D,SAAS,gBAAgB;CAE7B,GAhB4C,EAAA,KAAA,OAAR,EAAA,KAAA,QAAe,EAAA,MAAA,aAH7C,EAAA,MAAA,OAMF,EAAA,MAAA,mBADA,EAAA,MAAA;CANJ,IAAe,gBAAfA,IAmCaC;;EACL,WAAW;EACX,SAAS;EACT,YAAY;EACZ,gBAAgB;CAClB;CAGGC,IAAAA;iCAAU,KAAA,UAAA,wBACT,qBAAAW,UAAA,EAAA,UAAA,CACE,oBAAC,SAAD;EAAS,MAAM;EAAG,UAAA;CAAyC,CAAA,GAC3D,oBAAC,YAAD,CAAa,CAAA,CACb,EAAA,CAAA,GAJH,EAAA,MAAA;CAMAV,IAAAA;CAIgBC,AAAAA,EAAAA,QAAAA,cAAAA,EAAAA,QAIuC,qBAAA,EAAA,QARvD,SAAU,KAAA,UAAA,gBACT,qBAAAS,UAAA,EAAA,UAAA;EACE,oBAAC,SAAD;GAAS,MAAM;GAAG,UAAA;EAAoC,CAAA;EACtD,qBAAC,MAAD;GAAM,MAAM;GAAG,OAAO,EAAC,cAAc,OAAM;GAA3C,UAAA;IACE;IAAW,YAAY;IAAO;IAAU,cAAc,WAAW,SAAS,KAAK;IAAK;IACpF;GAEI;;EACN,oBAAC,iBAAD;GAA6B;GAAY,UAAU,CAAC;EAAoB,CAAA;CACxE,EAAA,CAAA,GALaT,EAAAA,MAAAA,YAIuC,EAAA,MAAA,mBARvD,EAAA,MAAA;CAWAC,IAAAA;CAuBkB,AAAA,EAAA,QAAA,iBAAA,EAAA,QAhBA,eAAA,EAAA,QAPlB,SAAU,KAAA,UAAA,aACT,qBAAAQ,UAAA,EAAA,UAAA;EACE,oBAAC,SAAD;GAAS,MAAM;GAAG,UAAA;EAAoD,CAAA;EACtE,oBAAC,MAAD;GAAM,MAAM;GAAG,UAAA;EAAiC,CAAA;EAChD,qBAAC,OAAD;GAAO,KAAK;GAAG,SAAS;GAAxB,UAAA;IACE,qBAAC,MAAD;KAAM,OAAM;KAAS,IAAG;KAAxB,UAAA,CACE,oBAAC,UAAD;MACE,SAAS;MACT,gBAAgB,eAAeP,OAAe;KAC/C,CAAA,GACD,oBAAC,MAAD;MAAM,OAAO,EAAC,QAAQ,SAAQ;MAAG,UAAA;KAAyB,CAAA,CACtD;;IACN,qBAAC,MAAD;KAAM,OAAM;KAAS,IAAG;KAAxB,UAAA,CACE,oBAAC,UAAD;MAAU,UAAA;MAAS,SAAA;KAAS,CAAA,GAC5B,oBAAC,MAAD;MAAM,OAAO,EAAC,QAAQ,SAAQ;MAAG,UAAA;KAA+B,CAAA,CAC5D;;IACN,oBAAC,KAAD,EAAA,UACE,oBAAC,QAAD;KACE,MAAM;KACN,UAAU;KACV,SAAS;KACT,MAAK;KACL,MAAK;KACL,SAAS;KACT,UAAU;MAAC;MAAuB;MAAsB;KAAY,CAAC,CAAC,MACnE,MAAM,MAAM,KACf;IACD,CAAA,EACE,CAAA;GACA;;CACP,EAAA,CAAA,GAPe,EAAA,MAAA,eAhBA,EAAA,MAAA,aAPlB,EAAA,MAAA;CAgCAC,IAAAA;iCAAU,KAAA,UAAA,yBACT,qBAAAM,UAAA,EAAA,UAAA,CACE,oBAAC,SAAD;EAAS,MAAM;EAAG,UAAA;CAA0B,CAAA,GAC5C,oBAAC,YAAD,CAAa,CAAA,CACb,EAAA,CAAA,GAJH,EAAA,MAAA;CAMAL,IAAAA;iCAAU,KAAA,UAAA,oBACT,qBAAAK,UAAA,EAAA,UAAA,CACE,oBAAC,SAAD;EAAS,MAAM;EAAG,UAAA;CAA8B,CAAA,GAChD,oBAAC,MAAD;EAAM,MAAM;EAAG,UAAA;CAA+D,CAAA,CAC9E,EAAA,CAAA,GAJH,EAAA,MAAA;CAjELJ,IAAAA;CAUKP,AAAAA,EAAAA,QAAAA,MAAAA,EAAAA,QAMAC,MAAAA,EAAAA,QAWAE,MAAAA,EAAAA,QAgCAE,MAAAA,EAAAA,QAMAC,MAjEL,MAAA,oBAAC,MAAD;EACE,SAAS;EACT,OAAOP;EAOP,UAAA,qBAAC,OAAD;GAAO,KAAK;GAAZ,UAAA;IACGC;IAMAC;IAWAE;IAgCAE;IAMAC;GAMI;;CACH,CAAA,GA9DDN,EAAAA,MAAAA,IAMAC,EAAAA,MAAAA,IAWAE,EAAAA,MAAAA,IAgCAE,EAAAA,MAAAA,IAMAC,EAAAA,MAAAA;CA3EPE,IAAAA;CADF,OAMa,EAAA,QAAA,gBAAA,EAAA,QAKTD,OAVF,MAAA,oBAAC,QAAD;EACE,SAAA;EACA,QAAQ;EACR,SAAS;EACT,IAAG;EACH,SAAS;EACT,gBAAgB;EAChB,OAAO;EACP,UAAS;EAETA,UAAAA;CAyEM,CAAA,GA9EG,EAAA,MAAA,cAKTA,EAAAA,MAAAA,iCAVFC;AAqFJ;AAxCmD,SAAAI,QAAC,MAAA;CAAS,OAAA,CAAC;;ACxG9D,MAAM,mBAAmB,iCAMtB,EAAC,eAAe,SACV,cAAc,YACR,gEACX,EAAC,GAAE,GACH,EACE,YAAY,mBACd,CACF,CACD;ACfD,SAAwB,iBAAiB,KAAyB;CAChE,IAAM,KAAK,IAAI,WAAW,IAAI,OAAO,IAC/B,OAAO,IAAI,MAAM,6BACnB,IAAI,KAAK,OAAO,IAAI,KAAK,UAAU,IAAI,GAAI,IAC3C,IAAI,KAAK,IAAI,cAAc,IAAI,cAAc,KAAK,IAAI,CAAC;CAE3D,OAAO;EACL,OAAO,IAAI,YAAY,GAAG,MAAM,GAAG,EAAE;EACjC;EACJ,YAAY,IAAI;EAChB,WAAW;EACX,UAAU,IAAI,MAAM,WAAW,cAAc,IAAI,MAAM,QAAQ,IAAI,KAAA;EACnE,cAAc,IAAI,MAAM;EACxB,cAAc,IAAI,MAAM;EACxB,uBAAuB,IAAI,MAAM;EACjC,uBAAuB,IAAI,MAAM;EACjC,aACE,IAAI,MAAM,QAAQ,QAAQ,UAAiC,MAAM,SAAS,MAAM,KAAK,CAAC;CAC1F;AACF;ACLA,SAAwB,gBAAgB,OAA0B;gBAC1D,gBAAgB,iBAAiB,GACjC,QAAQ,SAAS,GACjB,SAASiB,YAAU,GAGRhB;CAAC,AAAA,EAAA,OAAA,iBAAA,EAAA,OAA+BC,MAAN,MAAM,OAAhC,KAAA;EAAC;EAAe,IAAI,MAAM,MAAM;CAAG,GAAlC,EAAA,KAAA,eAA+BA,EAAAA,KAAAA,MAAN,MAAM;CADjD,IAAM,CAAC,YAAY,qBAAqB,iBACtCC,EACF,GAEmDC;CAAYC,AAAAA,EAAAA,OAAAA,MAAAA,qBAAZ,WAAM,MAAM;CAA/D,IAAM,CAAC,eAAe,oBAAoB,SAASD,EAAiB,GAC9D,CAAC,UAAU,eAAe,SAAS,MAAM,MAAM,QAAQ,GACvD,WAAW,aAAa,cAAc,UAExBE;CAAkC,AAAA,EAAA,OAAA,YAAA,EAAA,OAAPD,MAAAA,SAA3B,KAAA,iBAAiB;EAAC,GAAG,MAAM;EAAO;CAAQ,CAAC,GAAT,EAAA,KAAA,UAAPA,EAAAA,KAAAA,MAAAA;CAA/C,IAAM,cAAcC,IAEd,CAAC,OAAO,YAAY,SAA4B,MAAM,GAEVC;qDAAC,KAAA,EAAA,WAAW,GAAI;CAAlE,IAAM,EAAC,aAAa,gBAAe,eAAeA,EAAiB,GAEnEC;CAG0BH,AAAAA,EAAAA,OAAAA,MAAAA,SAAAA,EAAAA,QAAlB,eAAA,EAAA,QAFF,SADN,KAAA,eAAe,eAAe;EAC5B,AAAI,UAAU,WACd,SAAS,WAAW,GACpB,MAAM,YAAY,MAAM,KAAK,GAC7B,SAAS,MAAM;CACjB,GAF0BA,EAAAA,KAAAA,MAAAA,OAAlB,EAAA,MAAA,aAFF,EAAA,MAAA;CADN,IAAe,eAAfG,IAOAC;CAGM,AAAA,EAAA,QAAA,YAAA,EAAA,QAKJ,SAAA,EAAA,QAPI,SADN,KAAA,SAAS,cAAc;EACrB,AAAI,UAAU,WAEV,WACF,SAAS,SAAS,IAIpB,MAAM,YAAY;CACpB,GANM,EAAA,MAAA,UAKJ,EAAA,MAAA,OAPI,EAAA,MAAA;CADN,IAAS,cAATA,IAWAC;CAGmB,AAAA,EAAA,QAAA,SAAA,EAAA,QAFb,SADN,KAAA,SAAS,aAAa,aAAsB;EAC1C,AAAI,UAAU,cAEV,eAAa,MAAM,YAAY,GAEnC,SAAS,MAAM;CACjB,GAHmB,EAAA,MAAA,OAFb,EAAA,MAAA;CADN,IAAS,eAATA,IAQAC;CAKU,AAAA,EAAA,QAAA,UAAA,EAAA,QAAmC,YAAA,EAAA,QAcfC,cAAAA,YAAAA,EAAAA,QAdPC,SAAAA,EAAAA,QAJjB,SAAA,EAAA,QAMF,SAPJ,KAAA,eAAe,cAAc;EAC3B,IAAI,UAAU,QACd;YAAS,QAAQ;GAEjB,IAAI;IAQF,AAPA,MAAM,OAAO,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,EAAC,SAAQ,CAAC,CAAC,CAAC,OAAO,GAC3D,kBAAkB,UAAU;KAAC,GAAG;KAAM;IAAQ,EAAE,GAChD,MAAM,KAAK;KACT,OAAO;KACP,aAAa,cAAc;KAC3B,QAAQ;IACV,CAAC,GACD,MAAM,YAAY;GACpB,SAASC,IAAO;IAAP,IAAA,QAAA;IAMP,AALA,MAAM,KAAK;KACT,OAAO;KACP,QAAQ;KACR,aAAa,OAAO,SAAU,WAAW,QAAQ;IACnD,CAAC,GACD,YAAY,cAAc,QAAQ;GACpC;GAEA,SAAS,MAAM;EApBE;CAqBnB,GAlBU,EAAA,MAAA,QAAmC,EAAA,MAAA,UAcfF,EAAAA,MAAAA,cAAAA,UAdPC,EAAAA,MAAAA,OAJjB,EAAA,MAAA,OAMF,EAAA,MAAA;CAPJ,IAAe,cAAfF,IAyBOI;CAAP,OAUE,EAAA,QAAA,gBAAA,EAAA,QAJA,eAAA,EAAA,QAFA,YAAA,EAAA,QAKA,eAAA,EAAA,QAGA,gBAAA,EAAA,QACA,eAAA,EAAA,QAVA,YAAA,EAAA,QAFA,cAAA,EAAA,QACA,qBAAA,EAAA,QASA,eAAA,EAAA,QAJA,SAPK,KAAA;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,GAJE,EAAA,MAAA,cAJA,EAAA,MAAA,aAFA,EAAA,MAAA,UAKA,EAAA,MAAA,aAGA,EAAA,MAAA,cACA,EAAA,MAAA,aAVA,EAAA,MAAA,UAFA,EAAA,MAAA,YACA,EAAA,MAAA,mBASA,EAAA,MAAA,aAJA,EAAA,MAAA,iCAPKA;AAeT;AC9DA,MAAM,cAOA,UAAA;gBAEFG;CAKkBC,AAAAA,EAAAA,OAAAA,MAAAA,YAAAA,EAAAA,OAJNC,MAAAA,SAAAA,EAAAA,OAGKC,MAAAA,WAAAA,EAAAA,OADIC,MAAAA,eAAAA,EAAAA,OADNC,MAAAA,SAFf,KAAA,oBAAC,WAAD;EACE,IAAI,MAAM;EACV,OAAO,MAAM;EACb,aAAa,MAAM;EACnB,SAAS,MAAM;EACf,UAAU,MAAM;CACjB,CAAA,GADiBJ,EAAAA,KAAAA,MAAAA,UAJNC,EAAAA,KAAAA,MAAAA,OAGKC,EAAAA,KAAAA,MAAAA,SADIC,EAAAA,KAAAA,MAAAA,aADNC,EAAAA,KAAAA,MAAAA;CAHjBC,IAAAA;CAAAA,OAAkDC,EAAAA,OAAAA,MAAAA,eAAAA,EAAAA,OAA1BL,MAAAA,SAAAA,EAAAA,OACtBF,MADF,KAAA,oBAAC6E,mBAAD;EAAW,OAAO,MAAM;EAAO,aAAa,MAAM;EAAa,SAAS,MAAM;EAC5E7E,UAAAA;CAOS,CAAA,GARuCO,EAAAA,KAAAA,MAAAA,aAA1BL,EAAAA,KAAAA,MAAAA,OACtBF,EAAAA,KAAAA,4BADFM;GAWI,gBAA6C,UAAU;iBACrD,CAAC,KAAK,UAAU,SAAmC,SAAS,GAC5D,EACJ,aACA,UACA,UACA,YACA,mBACA,aACA,OACA,UACA,aACA,cACA,aACA,cACA,gBACE,gBAAgB,KAAK,GAEnB,WAAW,UAAU,UAGrB,CAAC,iBAAiB,sBAAsB,SAAwB,IAAI,GACpE,cAAc,OAAuB,IAAI,GACrCE,IAIPC;CAJH,oDAAU,WAAM;EACd,AAAK,YAAY,WAAa,2BAA2B,YAAY,WAErE,mBAAmB,YAAY,QAAQ,sBAAsB,CAAC,CAAC,MAAM;CACvE,GAAG,KAAA,CAAC,mDAJJ,UAAUD,IAIPC,EAAE;CAKO,IAAA,KAAA,YAAY,OAkBDC;CAAM,AAAA,EAAA,OAAA,wBAAN,WAAM,SAAS,UAAU,GAAnB,EAAA,KAAA;CACL,IAAA,KAAA,YAAY,aARxBC;CAOWD,AAAAA,EAAAA,OAAAA,MAAAA,EAAAA,OACCE,MARZ,KAAA,oBAAC,QAAD;EACE,MAAM;EACN,UAAU;EACV,SAAS;EACT,MAAK;EACL,MAAK;EACL,MAAK;EACL,SAASF;EACT,UAAUE;CACX,CAAA,GAFUF,EAAAA,KAAAA,IACCE,EAAAA,KAAAA;CAUA,IAAA,KAAA,YAAY,aACX,KAAA,eAAe,SAT5BC;CAOW,AAAA,EAAA,OAAA,gBAAA,EAAA,OACCD,MAAAA,EAAAA,OACCE,MATb,KAAA,oBAAC,QAAD;EACE,MAAM;EACN,UAAU;EACV,SAAS;EACT,MAAK;EACL,MAAK;EACL,MAAK;EACL,SAAS;EACT,UAAUF;EACV,WAAWE;CACZ,CAAA,GAHU,EAAA,KAAA,cACCF,EAAAA,KAAAA,IACCE,EAAAA,KAAAA;CApBfC,IAAAA;CACEJ,AAAAA,EAAAA,QAAAA,MAAAA,EAAAA,QAUAE,MAXF,KAAA,qBAAC,MAAD;EAAM,KAAK;EAAX,UAAA,CACEF,IAUAE,EAWI;KArBJF,EAAAA,MAAAA,IAUAE,EAAAA,MAAAA;CAYDG,IAAAA;CAUyB,AAAA,EAAA,QAAA,eAAA,EAAA,QADX,YAAA,EAAA,QATd,YAAA,EAAA,QAQY,eARZ,MAAA,YACC,oBAAC,QAAD;EACE,MAAM;EACN,UAAU;EACV,SAAS;EACT,MAAK;EACL,MAAK;EACL,MAAK;EACL,SAAS;EACT,WAAW,YAAY;EACvB,UAAU,YAAY;CACvB,CAAA,GADuB,EAAA,MAAA,aADX,EAAA,MAAA,UATd,EAAA,MAAA,UAQY,EAAA,MAAA;CAjCjBC,IAAAA;CAyBKD,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAvBDD,MAFJ,MAAA,oBAAC,MAAD;EAAM,SAAS;EACb,UAAA,qBAAC,MAAD;GAAM,SAAQ;GAAgB,OAAM;GAApC,UAAA,CACEA,IAuBCC,GAaG;;CACF,CAAA,GAdDA,EAAAA,MAAAA,KAvBDD,EAAAA,MAAAA;CAyCLG,IAAAA;CAOK,AAAA,EAAA,QAAA,SAAA,EAAA,QAFU,cAAA,EAAA,QADO,qBAAA,EAAA,QADC,YAAA,EAAA,QAHvB,SAAU,MAAA,UAAA,cACT,oBAAC,cAAD;EACE,OAAO,MAAM;EACb,oBAAoB,SAAS,MAAM;EAChB;EACP;EACZ,yBAAyB;GACvB,MAAM,YAAY;EACpB;CACD,CAAA,GAFG,EAAA,MAAA,OAFU,EAAA,MAAA,YADO,EAAA,MAAA,mBADC,EAAA,MAAA,UAHvB,EAAA,MAAA;CAaAC,IAAAA;CAMkB,AAAA,EAAA,QAAA,gBAAA,EAAA,QAeR,YAAA,EAAA,QArBV,SAAU,MAAA,UAAA,aACT,oBAAC,QAAD;EACE,SAAA;EACA,QAAQ;EACR,SAAA;EACA,IAAG;EACH,eAAe,aAAa,EAAK;EACjC,sBAAsB,aAAa,EAAK;EACxC,OAAO;EACP,UAAS;EACT,QACE,oBAAC,MAAD;GAAM,SAAS;GACb,UAAA,qBAAC,MAAD;IAAM,SAAQ;IAAgB,OAAM;IAApC,UAAA,CACE,oBAAC,QAAD;KACE,MAAM;KACN,UAAU;KACV,SAAS;KACT,MAAK;KACL,MAAK;KACL,eAAe,aAAa,EAAI;IACjC,CAAA,GACA,YACC,oBAAC,QAAD;KACE,MAAM;KACN,UAAU;KACV,SAAS;KACT,MAAK;KACL,MAAK;KACL,MAAK;KACL,eAAe,aAAa,EAAK;IAClC,CAAA,CAEC;;EACF,CAAA;EAGR,UAAA,oBAAC,MAAD;GAAM,SAAS;GACb,UAAA,qBAAC,OAAD;IAAO,OAAO,EAAC,WAAW,SAAQ;IAAG,KAAK;IAA1C,UAAA,CACE,oBAAC,SAAD;KAAS,MAAM;KAAG,UAAA;IAAqC,CAAA,GACvD,oBAAC,MAAD;KAAM,MAAM;KAAG,UAAA;IAA4C,CAAA,CACtD;;EACH,CAAA;CACA,CAAA,GApCS,EAAA,MAAA,cAeR,EAAA,MAAA,UArBV,EAAA,MAAA;CA+CQC,IAAAA;sDACL,MAAA,EAAA,eAAe,cACjB;CAKaC,IAAAA;;EAAC;EAAU;EAAU;CAAK;CAInCC,IAAAA;CAAO,AAAA,EAAA,QAAA,iCAAP,MAAA,OAAO,mBAAoB,WACvB,EACE,WAAW,gBACb,IACA,KAAA,GAJG,EAAA,MAAA;CAQoC,IAAA,MAAA,MAAM,MAAM,YAAY,IAAnEC;CAA0BC,AAAAA,EAAAA,QAAAA,MAAAA,SAAAA,EAAAA,QAAiBC,OAA3C,MAAA,oBAAC,aAAD;EAAa,OAAO,MAAM;EAAO,UAAUA;CAAgC,CAAA,GAAjDD,EAAAA,MAAAA,MAAAA,OAAiBC,EAAAA,MAAAA;CAC1CC,IAAAA;CAOoBC,AAAAA,EAAAA,QAAAA,YAAAA,eAAAA,EAAAA,QACPH,MAAAA,SAAAA,EAAAA,QARb,OAAQ,MAAA,QAAA,aACP,qBAAAsD,UAAA,EAAA,UAAA,CACE,oBAAC,mBAAD;EACE,OAAO,MAAM;EACb,UAAA;EACA,gBAAA;EACA,QACE,aAAa,eACb,MAAM,MAAM,MAAM,QAAQ,OACxBlD,OACF,KACA,CAAC;CAEJ,CAAA,GACD,oBAAC,WAAD,EAAW,OAAO,MAAM,MAAQ,CAAA,CAChC,EAAA,CAAA,GARiBD,EAAAA,MAAAA,YAAAA,aACPH,EAAAA,MAAAA,MAAAA,OARb,EAAA,MAAA;CAFHK,IAAAA;CACEN,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QACCG,OAFH,MAAA,qBAAC,OAAD;EAAO,KAAK;EAAG,MAAM;EAAG,QAAO;EAA/B,UAAA,CACEH,KACCG,GAiBI;KAlBLH,EAAAA,MAAAA,KACCG,EAAAA,MAAAA;CAyBYI,IAAAA;sDAAM,YAAA,OAAO,SAAS;CACrB,IAAA,MAAA,QAAQ,WANpBC;CAMYC,AAAAA,EAAAA,QAAAA,qBANZ,MAAA,oBAAC,KAAD;EACE,iBAAc;EACd,MAAM;EACN,IAAG;EACH,OAAM;EACN,SAASF;EACT,UAAUE;CACX,CAAA,GADWA,EAAAA,MAAAA;CAMH,IAAA,MAAA,WAAW,aAAa,IAAI,WAAW,OAAO,KAAK,MACjDC;sDAAM,YAAA,OAAO,YAAY;CACxB,IAAA,MAAA,QAAQ,cANpBC;CAISC,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAEGC,OANZ,MAAA,oBAAC,KAAD;EACE,iBAAc;EACd,MAAM;EACN,IAAG;EACH,OAAOD;EACP,SAASF;EACT,UAAUG;CACX,CAAA,GAHQD,EAAAA,MAAAA,KAEGC,EAAAA,MAAAA;CAfdC,IAAAA;CACEN,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAQAG,OATF,MAAA,qBAAC,SAAD;EAAS,KAAK;EAAd,UAAA,CACEH,KAQAG,GAQO;KAhBPH,EAAAA,MAAAA,KAQAG,EAAAA,MAAAA;CAYQ,IAAA,MAAA,QAAQ,WACTI;sDAAC,MAAA,EAAA,WAAW,aAAY;CAMpB,IAAA,MAAA,YAAY,IACVC;CAAO,AAAA,EAAA,QAAA,6BAAP,OAAC,MAAM,YAAY,EAAE,cAAc,KAAK,GAAjC,EAAA,MAAA;CACN,IAAA,MAAA,UAAU,QALtBC;CAGSC,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QACEF,OAAAA,EAAAA,QACCG,OALZ,MAAA,oBAAC,YAAD;EACE,OAAM;EACN,aAAY;EACZ,OAAOD;EACP,SAASF;EACT,UAAUG;CACX,CAAA,GAHQD,EAAAA,MAAAA,KACEF,EAAAA,MAAAA,KACCG,EAAAA,MAAAA;CAGTC,IAAAA;CAAaC,AAAAA,EAAAA,QAAAA,YAAAA,0BAAb,MAAA,aAAa,YACZ,oBAAC,UAAD;EACE,MAAM,aAAa,YAAY;EAC/B,MAAM;EACN,MAAM;CACP,CAAA,GALWA,EAAAA,MAAAA,YAAAA;CAObC,IAAAA;CAAaC,AAAAA,EAAAA,QAAAA,YAAAA,uCAAb,MAAA,aAAa,yBACZ,oBAAC,UAAD;EACE,MAAM,mBAAmB,YAAY;EACrC,MAAM;EACN,MAAM;CACP,CAAA,GALWA,EAAAA,MAAAA,YAAAA;CAObC,IAAAA;CAAaC,AAAAA,EAAAA,QAAAA,YAAAA,uCAAb,MAAA,aAAa,yBACZ,oBAAC,UAAD;EACE,MAAM,eAAe,YAAY;EACjC,MAAM;EACN,MAAM;CACP,CAAA,GALWA,EAAAA,MAAAA,YAAAA;CAObC,IAAAA;CAAaC,AAAAA,EAAAA,QAAAA,YAAAA,8BAAb,MAAA,aAAa,gBACZ,oBAAC,UAAD;EACE,MAAM,iBAAiB,YAAY;EACnC,MAAM;EACN,MAAM;CACP,CAAA,GALWA,EAAAA,MAAAA,YAAAA;CAQUC,IAAAA;CAAYC,AAAAA,EAAAA,QAAAA,YAAAA,2BAAZ,MAAA,YAAY,UAAU,mBAAmB,MAAM;EACnE,MAAM;EACN,OAAO;EACP,KAAK;EACL,MAAM;EACN,QAAQ;EACR,QAAQ;CACV,CAAC,GAPiCA,EAAAA,MAAAA,YAAAA;CAA5B,IAAA,MAAA,gBAAgBD,OADxBE;CACQC,AAAAA,EAAAA,QAAAA,qBADR,MAAA,oBAAC,UAAD;EACE,MAAMA;EAQN,MAAM;EACN,MAAM;CACP,CAAA,GAVOA,EAAAA,MAAAA;CAWQ,IAAA,MAAA,aAAa,YAAY,MAAzCC;CAAgBC,AAAAA,EAAAA,QAAAA,qBAAhB,MAAA,oBAAC,UAAD;EAAU,MAAMA;EAA+B,MAAM;EAAS,MAAM;CAAI,CAAA,GAAxDA,EAAAA,MAAAA;CAChBC,IAAAA;CAAuCC,AAAAA,EAAAA,QAAAA,YAAAA,8BAAvC,MAAA,oBAAC,aAAD,EAAa,cAAc,YAAY,aAAe,CAAA,GAAfA,EAAAA,MAAAA,YAAAA;CA1CzCC,IAAAA;CACGhB,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAOAE,OAAAA,EAAAA,QAOAE,OAAAA,EAAAA,QAOAE,OAAAA,EAAAA,QAODI,OAAAA,EAAAA,QAYAE,OAAAA,EAAAA,QACAE,OA1CF,MAAA,qBAAC,OAAD;EAAO,KAAK;EAAZ,UAAA;GACGd;GAOAE;GAOAE;GAOAE;GAODI;GAYAE;GACAE;EACK;KA1CJd,EAAAA,MAAAA,KAOAE,EAAAA,MAAAA,KAOAE,EAAAA,MAAAA,KAOAE,EAAAA,MAAAA,KAODI,EAAAA,MAAAA,KAYAE,EAAAA,MAAAA,KACAE,EAAAA,MAAAA;CAlDJG,IAAAA;CACEpB,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAOAmB,OARF,MAAA,qBAAC,OAAD;EAAO,KAAK;EAAZ,UAAA,CACEnB,KAOAmB,GA4CK;KAnDLnB,EAAAA,MAAAA,KAOAmB,EAAAA,MAAAA;CAdJE,IAAAA;CAGUC,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAGRF,OANF,MAAA,oBAAC,UAAD;EACE,mBAAgB;EAChB,IAAG;EACH,QAAQE;EACR,OAAOxB;EAEPsB,UAAAA;CAqDQ,CAAA,GAxDAE,EAAAA,MAAAA,KAGRF,EAAAA,MAAAA;CAyDQ,IAAA,MAAA,QAAQ,cAEmC,MAAA,CAAC,mBAApDG;CAA6B,AAAA,EAAA,QAAA,cAAA,EAAA,QAAsBC,OAAnD,MAAA,oBAAC,iBAAD;EAA6B;EAAY,UAAUA;CAAqB,CAAA,GAA3C,EAAA,MAAA,YAAsBA,EAAAA,MAAAA;CALrDC,IAAAA;CAGUC,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAERH,OALF,MAAA,oBAAC,UAAD;EACE,mBAAgB;EAChB,IAAG;EACH,QAAQG;EAERH,UAAAA;CACQ,CAAA,GAHAG,EAAAA,MAAAA,KAERH,EAAAA,MAAAA;CApFJI,IAAAA;CACE9B,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,SAkBAwB,OAAAA,EAAAA,SA4DAI,OA/EF,MAAA,qBAAC,OAAD;EAAO,KAAK;EAAG,MAAM;EAAG,QAAO;EAA/B,UAAA;GACE5B;GAkBAwB;GA4DAI;EAOK;KArFL5B,EAAAA,MAAAA,KAkBAwB,EAAAA,OAAAA,KA4DAI,EAAAA,OAAAA;CAxHNG,IAAAA;CAcM9C,AAAAA,EAAAA,SAAAA,OAAAA,EAAAA,SAOFO,OAAAA,EAAAA,SAoBAsC,OAzCJ,MAAA,oBAAC,MAAD;EACE,SAAS;EACT,QAAO;EACP,OAAO/C;EAIP,UAAA,qBAAC,MAAD;GACE,QAAO;GACP,KAAK;GACL,WAAWC;GACX,OAAM;GACN,KAAK;GACL,OACEC;GAPJ,UAAA,CAcEO,KAoBAsC,GAuFI;;CACF,CAAA,GAnHA7C,EAAAA,OAAAA,KAOFO,EAAAA,OAAAA,KAoBAsC,EAAAA,OAAAA;CAvJNE,IAAAA;CADF,OAGwBC,EAAAA,SAAAA,YAAAA,SAAAA,EAAAA,SAGX,eAAA,EAAA,SAKPrD,OAAAA,EAAAA,SA2CDC,OAAAA,EAAAA,SAaAC,OAAAA,EAAAA,SA4CDiD,OA9GF,MAAA,qBAAC,QAAD;EACE,SAAA;EACA,QAAQG;EACR,SAAS;EACT,IAAG;EACH,SAAS;EACT,gBAAgB;EAChB,OAAO;EACP,UAAS;EACT,QACEtD;EAVJ,UAAA;GAqDGC;GAaAC;GA4CDiD;EAkIM;KA9OcE,EAAAA,OAAAA,YAAAA,OAGX,EAAA,OAAA,aAKPrD,EAAAA,OAAAA,KA2CDC,EAAAA,OAAAA,KAaAC,EAAAA,OAAAA,KA4CDiD,EAAAA,OAAAA,mCA9GFC;AAkPJ,GAEM,eAAA,OAAoE;eAArD,EAAC,iBAADG;CACnB,IAAI,cAAc;EACTC,IAAAA;EAAP,4CAAoB,KAAA,aAAA,IAAIC,QAOvB,GAPM,EAAA,KAAA,0BAAAD;CAQT;CACOE,IAAAA;CAAP,2DAAQ,KAAA,oBAAA,UAAD;EAAU,MAAM;EAAkB,MAAM;EAAS,MAAM;CAAI,CAAA,2BAA3DA;AACT,GAEM,gBAAgB,WAA2B;CAC/C,QAAQ,QAAR;EACE,KAAK,OACH,OAAO;EACT,KAAK,UACH,OAAO;EACT,KAAK,UACH,OAAO;EACT,SACE,OAAO;CACX;AACF;AA/HsB,SAAAI,QAAC,OAAA;CAAiC,OAAA,MAAM,SAAS;;AAwG3C,SAAAC,SAAC,OAAA;CACvB,OAAA,oBAAC,UAAD;EAEE,MAAM,gBAAgB,aAAa,MAAM,MAAM,EAAE,KAAK,MAAM;EAC5D,MAAM;EACN,MAAM;CACP,GAJM,MAAM,EAIZ;;AC5UP,MAAM,iBAAiB,UAAuC;;CAC5D,IAAI,CAAC,MAAM,OACT,OAAO;CAiBJC,IAAAA,IAZFC,IAYcC,IACVC,IAGDC,IAMCC,IAtBOC,IACTC;CAHsCC,IAAAA,EAAAA,OAAAA,MAAAA,OAAAA;EAA3C,IAAM,cAAc,iBAAiB,MAAM,KAAK;EAE7C,KAAA,OAAW,KAAA,GACT,KAAA,YAAY,SACX,oBAAC,MAAD;GACE,MAAM;GACN,QAAO;GACP,OAAO,EACL,UAAU,aACZ;GAEC,UAAA,YAAY;EACT,CAAA,GAEP,KAAA,QAAY,KAAA,GACV,KAAA,aAAa,YACZ,oBAAC,UAAD;GAAU,MAAM,YAAY;GAAU,MAAM;GAAW,MAAM;GAAG,OAAA;EAAO,CAAA,GAEzE,KAAA,oBAAC,UAAD;GACE,MAAM,YAAY,UAAU,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;GACrD,MAAM;GACN,MAAM;GACN,OAAA;EACD,CAAA,GACA,KAAA,YAAY,SAAS,YAAY,GAAG,MAAM,GAAG,EAAE,KAC9C,oBAAC,UAAD;GAAU,MAAM,YAAY,GAAG,MAAM,GAAG,EAAE;GAAG,MAAM;GAAS,MAAM;GAAG,OAAA;EAAO,CAAA,GAzBzCA,EAAAA,KAAAA,MAAAA;;CAcvCC,IAAAA;CAACT,AAAAA,EAAAA,OAAAA,MAAAA,EAAAA,QAAYE,MAAAA,EAAAA,QACVC,MAAAA,EAAAA,QAGDC,MAAAA,EAAAA,QAMCC,MAVH,KAAA,qBAACL,IAAD;EAAQ,KAAKE;EAAb,UAAA;GACGC;GAGDC;GAMCC;EAGK;KAbPL,EAAAA,KAAAA,IAAYE,EAAAA,MAAAA,IACVC,EAAAA,MAAAA,IAGDC,EAAAA,MAAAA,IAMCC,EAAAA,MAAAA;CAtBLK,IAAAA;CADF,OACGT,EAAAA,QAAAA,MAAAA,EAAAA,QAAWK,MAAAA,EAAAA,QACTC,MAAAA,EAAAA,QAWDE,MAZF,KAAA,qBAACR,IAAD;EAAO,KAAKK;EAAZ,UAAA,CACGC,IAWDE,EAcK;KA1BNR,EAAAA,MAAAA,IAAWK,EAAAA,MAAAA,IACTC,EAAAA,MAAAA,IAWDE,EAAAA,MAAAA,8BAZFC;AA4BJ,GCzBM,aAAa,OAAO,OAAA,WAAA;;;AAAM,CAAA,CAAA;AA6DhC,SAAwB,eAAA,IAQrB;gBARoC,EACrC,UACA,QACA,UAHqCE,IAS/B,CAAC,aAAa,kBAAkB,SAAsB,EAAK,GACtCC;CAAiB,AAAA,EAAA,OAAA,SAAA,EAAA,OAAX,YAAN,WAAM,WAAW,KAAK,GAAL,EAAA,KAAA,OAAX,EAAA,KAAA;CAAjC,IAAM,SAASC,IACUC;CAAe,AAAA,EAAA,OAAA,SAAA,EAAA,OAAT,UAAN,WAAM,SAAS,KAAK,GAAL,EAAA,KAAA,OAAT,EAAA,KAAA;CAA/B,IAAM,OAAOC,IACP,EAAC,oBAAmB,6BAA6B;CAEvD,IAAI,CAAC,OACH,OAAO;CAGcC,IAAAA;CAAkB,AAAA,EAAA,OAAA,qBAAlB,KAAA,kBAAkB,KAAK,GAAL,EAAA,KAAA;CAAzC,IAAM,iBAAiBA,IACHC;CACuB,AAAA,EAAA,OAAA,mBAAA,EAAA,OAArBC,gBAAAA,UADF,WAAM;EACxB,AAAI,gBAAgB,WAAW,SAAS,CAAC,kBACvC,eAAe,iBAAiB,IAEhC,eAAe,cAAc;CAEjC,GAL2C,EAAA,KAAA,iBAArBA,EAAAA,KAAAA,gBAAAA;CADtB,IAAM,cAAcD,IAaTE;sDACL,KAAA,EAAA,UAAU,WACZ;CAECC,IAAAA;CAAgBF,AAAAA,EAAAA,QAAAA,gBAAAA,uBAAhB,KAAA,gBAAgB,WAAW,YAC1B,oBAAC,SAAD;EACE,SAAA;EACA,SACE,oBAAC,MAAD;GAAM,SAAS;GAAG,QAAQ;GACxB,UAAA,oBAAC,UAAD;IAAU,MAAM;IAAU,MAAK;IAAyB,MAAM;GAAI,CAAA;EAC9D,CAAA;EAER,WAAU;EACV,oBAAoB,CAAC,OAAO,QAAQ;EACpC,QAAA;EAEA,UAAA,oBAAC,MAAD;GACE,MAAK;GACL,OAAO;IACL,cAAc;IACd,UAAU;IACV,MAAM;IACN,KAAK;IACL,QAAQ;GACV;GACA,SAAS;GACT,QAAA;GAEA,UAAA,oBAAC,MAAD;IAAM,OAAA;IAAM,MAAM;IAChB,UAAA,oBAAC,UAAD,CAAW,CAAA;GACP,CAAA;EACF,CAAA;CACC,CAAA,GA5BMA,EAAAA,MAAAA,gBAAAA;CA8BhBG,IAAAA;CAAgBH,AAAAA,EAAAA,QAAAA,gBAAAA,uBAAhB,KAAA,gBAAgB,WAAW,SAC1B,oBAAC,SAAD;EACE,SAAA;EACA,SACE,oBAAC,MAAD;GAAM,SAAS;GAAG,QAAQ;GACxB,UAAA,oBAAC,UAAD;IAAU,MAAM;IAAU,MAAK;IAAsB,MAAM;GAAI,CAAA;EAC3D,CAAA;EAER,WAAU;EACV,oBAAoB,CAAC,OAAO,QAAQ;EACpC,QAAA;EAEA,UAAA,oBAAC,MAAD;GACE,MAAK;GACL,OAAO;IACL,cAAc;IACd,UAAU;IACV,MAAM;IACN,KAAK;IACL,QAAQ;GACV;GACA,SAAS;GACT,QAAA;GAEA,UAAA,oBAAC,MAAD;IAAM,OAAA;IAAM,MAAM;IAAG,QAAO;IAAW,OAAO,EAAC,OAAO,yBAAwB;IAC5E,UAAA;GACI,CAAA;EACF,CAAA;CACC,CAAA,GA5BMA,EAAAA,MAAAA,gBAAAA;CAiCRI,IAAAA;sDACL,KAAA,EAAA,kBAAkB,8BACpB;CAECC,IAAAA;uCAAgB,KAAA,gBAAA,qBACf,oBAAC,kBAAD,EACE,eAAe;EACb,eAAe,cAAc;CAC/B,EACD,CAAA,GALF,EAAA,MAAA;CAOAC,IAAAA;CACqB,AAAA,EAAA,QAAA,SAAA,EAAA,QAEC,eAAA,EAAA,QAHtB,eAAgB,MAAA,gBAAA,iBACf,oBAAC,aAAD;EAAoB;EAAO,UAAA;EAAS,kBAAkB;CAAyB,CAAA,IAE/E,qBAAC,YAAD;EAAY,SAAS;EAArB,UAAA,CACE,oBAAC,OAAD;GAAK,aAAA;GACH,UAAA,oBAAC,UAAD,CAAW,CAAA;EACR,CAAA,GACJ,aAAa,KAAK,IACjB,oBAAC,OAAD;GACE,OAAO;IACL,aAAa;IACb,SAAS;IACT,YAAY;IACZ,gBAAgB;GAClB;GAEA,UAAA,oBAAC,WAAD;IAAW,OAAM;IAAM,QAAO;GAAO,CAAA;EAClC,CAAA,IAEL,oBAAC,gBAAD,EAAuB,MAAQ,CAAA,CAEvB;KApBQ,EAAA,MAAA,OAEC,EAAA,MAAA,aAHtB,EAAA,MAAA;CAuBDC,IAAAA;CAAsB,AAAA,EAAA,QAAA,uBAAtB,MAAA,oBAAC,eAAD,EAAsB,MAAQ,CAAA,GAAR,EAAA,MAAA;CAEbC,IAAAA;;EACL,SAAS;EACT,OAAO;EACP,YAAY;EACZ,gBAAgB;EAChB,KAAK;CACP;CAECC,IAAAA;CASY,AAAA,EAAA,QAAA,YAAA,EAAA,QAAA,UATZ,MAAA,YACC,oBAAC,QAAD;EACE,MAAM;EACN,UAAU;EACV,SAAS;EACT,MAAK;EACL,MAAK;EACL,OAAO,EAAC,MAAM,EAAC;EACf,MAAK;EACL,SAAS;CACV,CAAA,GAVF,EAAA,MAAA,UASY,EAAA,MAAA;CASJC,IAAAA;sDAAC,MAAA,EAAA,MAAM,EAAC;CANjBC,IAAAA;CAOW,AAAA,EAAA,QAAA,sBAPX,MAAA,oBAAC,QAAD;EACE,MAAM;EACN,UAAU;EACV,SAAS;EACT,MAAK;EACL,MAAK;EACL,OAAOD;EACP,SAAS;CACV,CAAA,GADU,EAAA,MAAA;CA5BbE,IAAAA;CASGH,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAYDE,OArBF,MAAA,qBAAC,OAAD;EACE,OAAOH;EADT,UAAA,CASGC,KAYDE,GASG;KArBFF,EAAAA,MAAAA,KAYDE,EAAAA,MAAAA;CA3DJE,IAAAA;CAcGP,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAuBDC,OAAAA,EAAAA,QACAK,OAAAA,EAAAA,QA/BCP,MAPH,MAAA,qBAAC,OAAD;EACE,KAAK;EACL,QAAO;EACP,OAAOD;EAHT,UAAA;GAOGC;GAOAC;GAuBDC;GACAK;EA+BK;KAvDJN,EAAAA,MAAAA,KAuBDC,EAAAA,MAAAA,KACAK,EAAAA,MAAAA,KA/BCP,EAAAA,MAAAA;CA5ELS,IAAAA;CADF,OAsEID,EAAAA,QAAAA,OAAAA,EAAAA,QA5DCX,MAAAA,EAAAA,QA8BAC,MAvCH,MAAA,qBAAC,MAAD;EACE,QAAA;EACA,SAAS;EACT,QAAO;EACP,QAAQ;EACR,OAAOF;EALT,UAAA;GASGC;GA8BAC;GA8BDU;EAsEI;KAtEJA,EAAAA,MAAAA,KA5DCX,EAAAA,MAAAA,IA8BAC,EAAAA,MAAAA,gCAvCHW;AA6IJ;AClOA,SAAwB,cAAA,IAAsD;gBAAxC,EAAC,UAAU,WAAXE,IAC9B,EAAC,QAAQ,WAAW,aAAa,gBAAgB,SAAS,SAAQ,UAAU,GAC5E,CAAC,MAAM,WAAW,SAAiB,CAAC,GAEpC,YAAY,KAAK,MAAM,OAAO,SAAS,EAAS,IAAI,GACpD,CAAC,aAAa,kBAAkB,SAA4C,IAAI,GAE9EC;CAA6BC,AAAAA,EAAAA,OAAAA,UAAAA,EAAAA,OAAAA,eAA7B,KAAA,OAAO,MAAM,MAAM,EAAE,QAAQ,aAAa,GAAG,KAAK,aAAlD,EAAA,KAAA,QAA6BA,EAAAA,KAAAA;CADrC,IAAM,mBAAmBC,IAKnB,YAAY,OAAO,IACnB,UAAU,YAAY,IAEtB,YAAY,WAAW,UAAU,QAGDC;qDAAC,KAAA,EAAA,WAAW,OAAM;CAMnCC,IAAAA;CAAqC,AAAA,EAAA,OAAA,8BAArC,MAAC,MAAoC,eAAe,EAAE,cAAc,KAAK,GAApC,EAAA,KAAA;CAHhDC,IAAAA;CACS,AAAA,EAAA,OAAA,eAAA,EAAA,OAEED,MAHX,KAAA,oBAAC,WAAD;EACE,OAAO;EACP,MAAM;EACN,SAASA;EACT,aAAY;CACb,CAAA,GAJQ,EAAA,KAAA,aAEEA,EAAAA,KAAAA;CAGXE,IAAAA;CAA4B,AAAA,EAAA,OAAA,WAAA,EAAA,QAAe,QAA3C,KAAA,oBAAC,mBAAD;EAA4B;EAAe;CAAO,CAAA,GAAtB,EAAA,KAAA,SAAe,EAAA,MAAA;CAC3CC,IAAAA;CAAoB,AAAA,EAAA,QAAA,QAAA,EAAA,QAA+B,aAAnD,KAAA,oBAAC,cAAD;EAAoB;EAAe;EAAS,OAAO;CAAY,CAAA,GAA3C,EAAA,MAAA,MAA+B,EAAA,MAAA;CARrDC,IAAAA;CACEH,AAAAA,EAAAA,QAAAA,MAAAA,EAAAA,QAMAC,MAAAA,EAAAA,QACAC,MARF,KAAA,qBAAC,MAAD;EAAM,OAAM;EAAS,KAAK;EAA1B,UAAA;GACEF;GAMAC;GACAC;EACI;KARJF,EAAAA,MAAAA,IAMAC,EAAAA,MAAAA,IACAC,EAAAA,MAAAA;CAEDE,IAAAA;qCAAc,KAAA,cAAA,UACb,qBAAC,QAAD;EAAQ,KAAK;EAAb,UAAA;GACE,oBAAC,qBAAD,CAAsB,CAAA;GACtB,oBAAC,gBAAD,CAAiB,CAAA;GACjB,oBAAC,cAAD,CAAe,CAAA;EACT;KALT,EAAA,MAAA;CAXHC,IAAAA;CACEF,AAAAA,EAAAA,QAAAA,MAAAA,EAAAA,QAUCC,MAXH,KAAA,qBAAC,MAAD;EAAM,SAAQ;EAAgB,OAAM;EAApC,UAAA,CACED,IAUCC,EAOG;KAjBJD,EAAAA,MAAAA,IAUCC,EAAAA,MAAAA;CASAE,IAAAA;CAAQC,AAAAA,EAAAA,QAAAA,OAAAA,UAAAA,EAAAA,QAGJ,eAHJ,MAAA,QAAQ,SAAS,KAChB,qBAAC,OAAD;EAAO,OAAA;EAAP,UAAA;GACG,OAAO;GAAO;GAAO,OAAO,SAAS,IAAI,MAAM;GAAM;GACrD,cAAc,aAAa,YAAY,KAAK;EACxC;KAJAA,EAAAA,MAAAA,OAAAA,QAGJ,EAAA,MAAA;CAKIC,IAAAA;sDACL,MAAA,EAAA,qBAAqB,wCACvB;CAECC,IAAAA;CAKa,IAAA,EAAA,QAAA,UAAA,EAAA,QAAA,YAAA,EAAA,QALW,WAAA,EAAA,QAAX,WAAA;EAAwBC,IAAAA;EAKxB,EAAA,QAAA,0BALwB,OAAC,UACrC,oBAAC,gBAAD;GAES;GACP,QAAQ;GACE;EACX,GAJM,MAAM,GAIZ,GADW,EAAA,MAAA,wBALb,MAAA,OAAO,MAAM,WAAW,OAAO,CAAC,CAAC,IAAIA,GAOrC,GAPA,EAAA,MAAA,QAKa,EAAA,MAAA,UALW,EAAA,MAAA,SAAX,EAAA,MAAA;;CANhBC,IAAAA;CAMGF,AAAAA,EAAAA,QAAAA,qBANH,MAAA,oBAAC,MAAD;EACE,KAAK;EACL,OAAOD;EAINC,UAAAA;CAQG,CAAA,GARHA,EAAAA,MAAAA;CAbLG,IAAAA;CACGN,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAMDK,OAPF,MAAA,qBAAC,OAAD;EAAO,KAAK;EAAZ,UAAA,CACGL,KAMDK,GAeK;KArBJL,EAAAA,MAAAA,KAMDK,EAAAA,MAAAA;CAgBDE,IAAAA;sCAAa,MAAA,aAAA,oBAAC,YAAD,CAAa,CAAA,GAA1B,EAAA,MAAA;CAEAC,IAAAA;CAAqBP,AAAAA,EAAAA,QAAAA,OAAAA,UAAAA,EAAAA,QAApB,aAAA,EAAA,QAGK,eAHN,MAAA,CAAC,aAAa,OAAO,WAAW,KAC/B,oBAAC,MAAD;EAAM,SAAS;EAAG,UAAU;EAAG,UAAU;EAAG,QAAA;EAAO,QAAQ;EAAG,MAAK;EACjE,UAAA,oBAAC,MAAD;GAAM,OAAM;GAAS,OAAA;GAAM,MAAM;GAC9B,UAAA,cAAc,wBAAwB,YAAY,KAAK;EACpD,CAAA;CACF,CAAA,GALcA,EAAAA,MAAAA,OAAAA,QAApB,EAAA,MAAA,WAGK,EAAA,MAAA;CAhDTQ,IAAAA;CAoBEH,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAuBCC,OAAAA,EAAAA,QAEAC,OAAAA,EAAAA,QA5CDT,MADF,MAAA,qBAAC,OAAD;EAAO,SAAS;EAAG,KAAK;EAAG,OAAOP;EAAlC,UAAA;GACEO;GAmBAO;GAuBCC;GAEAC;EAOI;KAhCLF,EAAAA,MAAAA,KAuBCC,EAAAA,MAAAA,KAEAC,EAAAA,MAAAA,KA5CDT,EAAAA,MAAAA;CAoDDW,IAAAA;6CACC,MAAA,oBAAA,oBAAC,cAAD;EAAc,mBAAmB,eAAe,IAAI;EAAG,OAAO;CAAmB,CAAA,GADlF,EAAA,MAAA;CAtDHC,IAAAA;CADF,OAC6C,EAAA,QAAA,UAAA,EAAA,QACzCF,OAAAA,EAAAA,QAqDCC,OAtDH,MAAA,qBAAC,mCAAD;EAA2C;EAA3C,UAAA,CACED,KAqDCC,GAGgC;KAzDQ,EAAA,MAAA,QACzCD,EAAAA,MAAAA,KAqDCC,EAAAA,MAAAA,iCAtDHC;AA2DJ;AC1FA,MAAM,cAAsC,WAAW;eAGjDE;CAAuB,AAAA,EAAA,OAAA,sBAAvB,KAAA,oBAAC,eAAD,EAAuB,OAAS,CAAA,GAAT,EAAA,KAAA;CADzBC,IAAAA;CADF,OACyCC,EAAAA,OAAAA,OAAAA,cAAAA,EAAAA,OACrCF,MADF,KAAA,oBAAC,oBAAD;EAAoB,YAAY,OAAO;EACrCA,UAAAA;CACkB,CAAA,GAFmBE,EAAAA,KAAAA,OAAAA,YACrCF,EAAAA,KAAAA,4BADFC;AAIJ,GAEa,sBAAsB;CACjC,MAAM;CACN,OAAO;AACT;AAEA,SAAwB,iBAAiB,QAA4B;CACnE,IAAM,aAAa,OAAO,OAAO,QAAS,WAAW,OAAO,OAAO;CACnE,OAAO;EACL,MAAM;EACN,MAAM,WAAW,QAAQ,oBAAoB;EAC7C,OAAO,WAAW,SAAS,oBAAoB;EAC/C,YAAY,UAAe,oBAAC,YAAD;GAAY,GAAI;GAAQ,GAAI;EAAQ,CAAA;CACjE;AACF;ACxBA,MAAa,oBAAoB,WAAyB;eAClD,OAAO,eAAe,GAG1BG;CAACC,AAAAA,EAAAA,OAAAA,UAAAA,EAAAA,OACKC,MAAAA,SADN,KAAA,CAAC,QAAQ,8BAA8B,UACvC,MAAM,OAAO,MAAM,SAAS,OAAO,6BAA6B,SAAS,KAAK,IAAI,CAAC,GADlFD,EAAAA,KAAAA,QACKC,EAAAA,KAAAA,MAAAA;CAFR,IAAM,kBACJF,IAGKG;CAAP,OAAQ,EAAA,OAAA,+BAAD,KAAA,EAAC,gBAAe,GAAf,EAAA,KAAA,6BAADA;AACT,GCPM,OAAO;CAAC;CAAW;CAAQ;CAAc;CAAU;CAAa;AAAU,GACnE,0BAA0B,UACrC,kBACE,YAAY,KAAK,IAAI,MAAM,OAAO,IAClC,IACF,GCCW,iBAAiB,UAA+B;eACrD,SAASS,YAAU,GACnB,YAAY,aAAa,GACzB,UAAU,WAAW;CAiBiB,AAAxC,OAAO,MAAM,mBAAmB,QAAQ,OAAO,MAAM,mBAAmB;CAhBxCP,IAAAA;;EAIlC,IACE,OAAO,MAAM,mBAAmB,UAChC,OAAO,MAAM,mBAAmB,WAAW,YAC3C;GACA,KAAO;GAAP,MAAA;EACF;EAEA,IAAM,QAAQ,OAAO,MAAM,mBAAmB;EAC9C,IAAI,CAAC,SAAS,MAAM,WAAW,GAAG;GAChC,KAAO;GAAP,MAAA;EACF;EACA,KAAO,MAAM,KAAKC,OAAqC;;CAfzD,IAAM,8BAA8BD;CAoBjB,AAAhB,OAAO,SAAS,OAAO;CAF1B,IAAM,cACE,CAAC,CAAC,OAAO,YAAY,OAAO,WAAW,eAAe,8BAKxD,iBAAiB,OAAO,EAAK,GAGjCE;CAGiDC,AAAAA,EAAAA,OAAAA,SAAAA,EAAAA,OADN,UAAA,EAAA,OACV,WAHjC,KAAA,YAAY;EACV,IAAI;GACF,IAAM,EAAC,SAAQ,MAAM,kBAAkB,MAAM,CAAC,CAAC,QAA0B;IACvE,KAAK,sBAAsB,QAAQ,QAAQ,MAAO;IAClD,iBAAiB;IACjB,QAAQ;IACR,OAAO;GACT,CAAC;GACD,IAAI,CAAC,OAAO,OAAO,CAAC,MAAM;GAK1B,AAJA,MAAM,OACH,MAAM,MAAM,GAAG,CAAC,CAChB,IAAI;IAAC,QAAQ,KAAK;IAAQ,MAAM,iBAAiB,IAAI;GAAC,CAAC,CAAC,CACxD,OAAO,EAAC,iBAAiB,GAAK,CAAC,GAClC,eAAe,UAAU;EAC3B,SAASC,IAAO;GAAP,IAAA,QAAA;GAGP,AAAK,eAAe,YAClB,eAAe,UAAU,IACzB,QAAQ,MAAM,gDAAgD;IAC5D,SAAS,OAAO;IAChB,YAAY,OAAO;IACnB;GACF,CAAC;EAEL;CACF,GAvBiDD,EAAAA,KAAAA,OADN,EAAA,KAAA,QACV,EAAA,KAAA;CAwBjCE,IAAAA;CA7BF;EA6BG,iBAAiB;EAAM,mBAAmB;EAAM,kBAAkB;CAAI,2BA7BlE,OACL,cAAc,IAAI,UAAU,qBAAqB,QAAQ,QAAQ,OAAO,YAAY,MACpFH,IA2BAG,EACF;AACF;AAzCsB,SAAAG,QAAC,MAAA;CAAS,OAAA,KAAK,WAAW;;AChBhD,SAAS,kBAAkB,OAAc;gBACjC,EAAC,UAAU,eAAc,OACzB,EAAC,MAAM,cAAa,SAAS,GAC7B,WAAW,OAAO,IAAI,GACqCC;CAkB7D,AAAA,EAAA,OAAA,aAAA,EAAA,OAYgBC,cA9B6C,KAAA,EAE/D,aAAa,KAAK,cAAc;EAgB9B,AAfA,QAAQ,MAAM,IAAI,SAAS,CAAC,GAC5B,QAAQ,eAAe,eAAe,GACtC,QAAQ,MAAM,GAAG,GACjB,QAAQ,SAAS,GACb,IAAI,UACN,QAAQ,eAAe,aAAa,GACpC,QAAQ,IAAI,IAAI,KAAK,GACrB,QAAQ,SAAS,IAEf,WAAW,mBACb,QAAQ,eAAe,0BAA0B,GACjD,QAAQ,IAAI,UAAU,cAAc,GACpC,QAAQ,SAAS,IAEnB,QAAQ,SAAS,GACjB,UAAU;GACR,QAAQ;GACR,OAAO;GACP,aACE,oBAAC,MAAD;IAAM,OAAM;IACV,UAAA,qBAAC,QAAD;KAAQ,KAAK;KAAb,UAAA,CACE,qCACA,oBAAC,QAAD;MACE,SAAS;MACT,UAAU;MACV,OAAO,EAAC,WAAW,kBAAiB;MACpC,MAAK;MACL,MAAM,WAAW;MACjB,eAAe;OACb,AAAI,SAAS,WACX,eAAe,SAAS,SAAS;QAC/B,UAAU;QACV,YAAY;QACZ,OAAO;OACT,CAAC;MAEL;KACD,CAAA,CACK;;GACJ,CAAA;EAEV,CAAC;CACH,EACF,GA5BI,EAAA,KAAA,WAYgBA,EAAAA,KAAAA;CA9BpB,IAAM,EAAC,eAAe,UAAU,OAAO,UAAS,iBAAiBD,EA8ChE,GAC+BE;CAI9B,AAAA,EAAA,OAAA,qBAJ8B,WAAM;EAIpC,AAFA,MAAM,CAAC,IAAI,CAAC,GAEZ,MAAM;CACR,GADE,EAAA,KAAA;CAJF,IAAM,cAAcC;CAOpB,IAAI,UAAU;EAEqBC,IAAAA;;GAAC;GAAG;GAAG;GAAG;EAAC;EAEHA,IAAAA;;GAAC;GAAG;GAAG;GAAG;EAAC;EAC5CC,IAAAA;sDAAC,KAAA,qBAAA,SAAD;GAAS,IAAG;GAAZ,UAAA;IACE;IAAI,oBAAC,QAAD,EAAA,UAAO,KAAW,CAAA;IAAC;GAChB;;EACRC,IAAAA;gCAAO,KAAA,OAAA,WACN,oBAAC,MAAD;GAAM,SAAS;GAAG,MAAK;GAAW,QAAQ;GAAG,QAAQ;GACnD,UAAA,oBAAC,MAAD,EAAA,UAAO,MAAM,QAAc,CAAA;EACvB,CAAA,GAHPC,EAAAA,KAAAA;EAKDC,IAAAA;EACmB,AAAA,EAAA,QAAA,4BADnB,KAAA,oBAAC,QAAD,EAAA,UACE,oBAAC,QAAD;GAAQ,SAAS;GAAa,MAAK;EAAS,CAAA,EACtC,CAAA,GADW,EAAA,MAAA;EAZzBC,IAAAA;EADF,OAOSH,EAAAA,QAAAA,MAAAA,EAAAA,QAKDE,MAXN,KAAA,oBAAC,MAAD;GAAM,KAAK;GAAU,UAAUJ;GAAc,QAAO;GAAO,QAAQ;GAAG,UAAS;GAC7E,UAAA,oBAAC,MAAD;IAAM,SAAQ;IAAa,OAAM;IAAS,QAAO;IAC/C,UAAA,qBAAC,MAAD;KAAM,qBAAqB;KAAG,KAAKA;KAAnC,UAAA;MACEC;MAGCC;MAKDE;KAGI;;GACF,CAAA;EACF,CAAA,GAVCF,EAAAA,MAAAA,IAKDE,EAAAA,MAAAA,8BAXNC;CAkBJ;CAEOC,IAAAA;CAAP,OAAQ,EAAA,QAAA,iBAAA,EAAA,QAAe,YAAhB,KAAA,oBAAC,eAAD,EAAgB,SAAwB,CAAA,GAAvC,EAAA,MAAA,eAAe,EAAA,MAAA,oCAAhBA;AACT;AAEA,IAAA,4BAAe,KAAK,iBAAiB;AC/FrC,MAAa,sBAAsB;eAEnBE;qDAAC,KAAA,EAAA,SAAS,EAAC;CAIZC,IAAAA;;EAAC,aAAa;EAAQ,OAAO;EAAQ,cAAc;CAAK;CAG7DC,IAAAA;qDAAC,KAAA,oBAAA,SAAD,EAAS,OAAA,GAAO,CAAA;CAPtBC,IAAAA;CADF,2DACG,KAAA,oBAAA,OAAD;EAAK,OAAOH;EACV,UAAA,oBAAC,MAAD;GACE,QAAQ;GACR,QAAO;GACP,OAAOC;GAEP,UAAA,qBAAC,MAAD;IAAM,OAAM;IAAS,WAAU;IAAS,QAAO;IAAO,SAAQ;IAA9D,UAAA,CACEC,IACA,oBAAC,KAAD;KAAK,WAAW;KACd,UAAA,oBAAC,MAAD;MAAM,OAAM;MAAS,OAAA;MAAM,MAAM;MAC/B,UAAA;KACI,CAAA;IACH,CAAA,CACD;;EACF,CAAA;CACH,CAAA,2BAfLC;AAiBJ;ACPA,SAAwB,QAAQ,OAAqB;gBAC7C,EAAC,mBAAkB,OACME;CAAM,AAAA,EAAA,OAAA,8BAAN,WAAM,eAAe,SAAS,GAAxB,EAAA,KAAA;CAArC,IAAM,aAAaC,IACb,EAAC,oBAAmB,iBAAiB,MAAM,MAAM,GAIvCC;qDAAC,KAAA,EAAA,SAAS,EAAC;CAIZC,IAAAA,IAKGC;qDALH,KAAA;EACL,aAAa;EACb,OAAO;EACP,WAAW;CACb,GACU,KAAA;EAAC;EAAG;EAAG;EAAG;CAAC;CAKgBA,IAAAA;;EAAC;EAAG;EAAG;EAAG;CAAC;CAC5CC,IAAAA;qDAAC,KAAA,oBAAA,QAAD;EAAQ,UAAU;EAChB,UAAA,oBAAC,OAAD;GAAK,OAAO,EAAC,QAAQ,OAAM;GACzB,UAAA,oBAAC,SAAD,CAAU,CAAA;EACP,CAAA;CACC,CAAA;CACRC,IAAAA;qDAAC,KAAA,oBAAA,QAAD;EAAQ,UAAU;EAChB,UAAA,oBAAC,SAAD;GAAS,MAAM;IAAC;IAAG;IAAG;IAAG;GAAC;GACxB,UAAA;EACO,CAAA;CACH,CAAA;CAzBlBC,IAAAA;CADF,OA6BmF,EAAA,OAAA,cAAA,EAAA,OADpE,mBA3Bb,KAAA,oBAAAE,UAAA,EAAA,UACE,oBAAC,OAAD;EAAK,OAAOP;EACV,UAAA,oBAAC,MAAD;GACE,SAAQ;GACR,QAAO;GACP,OAAOC;GAKP,UAAUC;GACV,QAAQ;GACR,MAAK;GAEL,UAAA,oBAAC,MAAD;IAAM,SAAQ;IAAa,OAAM;IAC/B,UAAA,qBAAC,MAAD;KAAM,qBAAqB;KAAG,KAAKA;KAAnC,UAAA;MACEC;MAKAC;MAKA,oBAAC,QAAD;OAAQ,UAAU;OACf,UAAA,kBACC,oBAAC,QAAD;QAAQ,MAAK;QAAQ,MAAM;QAAU,MAAK;QAAgB,SAAS;OAAa,CAAA,IAEhF,oBAAC,MAAD;QAAM,SAAS;SAAC;SAAG;SAAG;QAAC;QAAG,QAAQ;QAAG,QAAQ;QAAG,MAAK;QACnD,UAAA,oBAAC,MAAD,EAAA,UACE,sFAEI,CAAA;OACF,CAAA;MAEF,CAAA;KACJ;;GACF,CAAA;EACF,CAAA;CACH,CAAA,EACL,CAAA,GAd+E,EAAA,KAAA,YADpE,EAAA,KAAA,2CA3BbC;AA4CJ;AC7DA,SAAgB,wBAAwB,MAAc,WAAmB,QAAc;CACrF,OAAO,IAAI,YAIR,eAAe;EAChB,IAAM,UAAU,QAAQ,aAAa;GACnC,UAAU;GACV,MAAM;GACN,kBAAkB;EACpB,CAAC,GAEK,uBAAuB;GAK3B,AAJA,WAAW,KAAK;IACd,MAAM;IACN,IAAI;GACN,CAAC,GACD,WAAW,SAAS;EACtB,GAEM,gBAAgB,SAAsB,WAAW,MAAU,MAAM,KAAK,OAAO,OAAO,CAAC,GAErF,mBAAmB,SAChB,WAAW,KAAK;GAAC,MAAM;GAAY,SAAS,KAAK;EAAM,CAAC,GAG3D,uBAAuB;GAE3B,AADA,QAAQ,MAAM,GACd,WAAW,KAAK;IACd,MAAM;IACN,IAAI;GACN,CAAC;EACH,GAEM,sBAAsB;GAE1B,AADA,QAAQ,OAAO,GACf,WAAW,KAAK;IACd,MAAM;IACN,IAAI;GACN,CAAC;EACH;EAQA,OANA,QAAQ,GAAG,WAAW,cAAc,GACpC,QAAQ,GAAG,SAAS,YAAY,GAChC,QAAQ,GAAG,YAAY,eAAe,GACtC,QAAQ,GAAG,WAAW,cAAc,GACpC,QAAQ,GAAG,UAAU,aAAa,SAErB,QAAQ,MAAM;CAC7B,CAAC;AACH;;;;;;;;;;;;AC1CA,SAAgB,qBAAqB,KAAqB;CAExD,IAAM,oBAAoB,OACjB,kDAAkD;CAI3D,IAAI;EAEF,IAAM,UAAU,IAAI,KAAK,GACnB,SAAS,IAAI,IAAI,OAAO;EAG9B,IAAI,OAAO,aAAa,oBACtB,MAAU,MAAM,+BAA+B;EAIjD,IAAM,KAAK,OAAO,aAAa,IAAI,IAAI,KAAK;EAC5C,IAAI,GAAG,QACL,OAAO,iBAAiB,EAAE;EAI5B,IAAM,OAAO,OAAO,SAAS,MAAM,GAAG,KAAK,CAAC;EAG5C,IAAI,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,GAAG,GAAG;GAC/C,IAAM,QACJ,KAAK,WAAW,UACP,UAAU,GAClB,IAAI;GAEP,OAAO,iBADQ,KAAK,GAAG,KAAK,KAAK,EACH;EAChC;EAGA,IAAI,KAAK,SAAS,SAAS,GAAG;GAC5B,IAAM,QACJ,KAAK,WAAW,UACP,UAAU,SAClB,IAAI;GAEP,OAAO,iBADU,KAAK,GAAG,KAAK,KAAK,EACH;EAClC;EAGA,MAAU,MAAM,yBAAyB;CAC3C,QAAQ;EAEN,OAAO;CACT;AACF;;;;;;AC1DA,SAAgB,cAAc,OAAoC;CAChE,IAAI,OAAO,SAAU,UAAU;CAC/B,IAAM,UAAU,MAAM,KAAK;CAC3B,IAAI,CAAC,QAAQ,SAAS,IAAI,GAAG;CAC7B,IAAM,IAAI,OAAO,QAAQ,MAAM,GAAG,EAAE,CAAC;CACrC,IAAI,CAAC,OAAO,SAAS,CAAC,GAAG;CACzB,IAAI,UAAU,KAAK,MAAM,CAAC;CAG1B,OADI,YAAY,MAAG,UAAU,IAAI,IAAI,KAAK,IACnC,GAAG,QAAQ;AACpB;ACDA,SAAS,+BAA+B,UAA+B;CACrE,IAAM,SAAS,SAAS;CACxB,IAAK,QACL,KAAK,IAAM,SAAS,QAAQ;EAC1B,IAAM,UAAW,MAAuD;EACxE,IAAI,CAAC,SAAS;EAEd,IAAM,KAAK,cAAc,QAAQ2P,iBAAoB,GAC/C,KAAK,cAAc,QAAQC,eAAkB,GAC7C,IAAI,cAAc,QAAQC,KAAQ;EAIxC,AAFI,OAAI,QAAQF,oBAAuB,KACnC,OAAI,QAAQC,kBAAqB,KACjC,MAAG,QAAQC,QAAW;CAC5B;AACF;AAEA,SAAS,wBAAwB,MAAsB;CACrD,OAAO,KAAK,QAAQ,2BAA2B,QAAQ,QAAQ;EAC7D,IAAM,IAAI,OAAO,GAAG;EACpB,IAAI,CAAC,OAAO,SAAS,CAAC,GAAG,OAAO;EAChC,IAAI,UAAU,KAAK,MAAM,CAAC;EAE1B,OADI,YAAY,MAAG,UAAU,IAAI,IAAI,KAAK,IACnC,IAAI,QAAQ;CACrB,CAAC;AACH;AAEA,SAAS,aAAa,QAAsB,MAAc;CACxD,OAAO,kBAAkB,MAAM,CAAC,CAAC,WAAW,QAAQ;EAClD,KAAK,uBAAuB,OAAO,OAAO,CAAC,CAAC,QAAQ,GAAG;EACvD,iBAAiB;EACjB,QAAQ;EACR,OAAO;CACT,CAAC;AACH;AAEA,SAAgB,UAAU,EACxB,KACA,UACA,UAMC;CACD,OAAO,QAAQ,GAAG,CAAC,CAAC,KAClB,WAAW,aACF,OACL,GAAG;EAAC,MAAM;EAAgB,KAAK;CAAQ,CAAC,GACxC,sBAAsB,MAAM,CAAC,CAAC,KAC5B,WAAW,SAAS;EAClB,IAAI,CAAC,QAAQ,CAAC,KAAK,QACjB,OAAO,iBAAiB,gBAAI,MAAM,qBAAqB,CAAC;EAE1D,IAAM1P,SAAOC,KAAa,GACpB,UAAU;EAGhB,AAFA,AAAoB,QAAQ,UAAQ,CAAC,EAAC,MAAM,QAAO,CAAC,GACpD,QAAQ,MAAM,EAAE,CAAE,MAAM,UACxB,+BAA+B,OAAO;EAEtC,IAAM,QAAgC,EACpC,SAAS,wBAAwB,KAAK,UAAU,OAAO,CAAC,EAC1D,GACM,WAAW,SAAS,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;EAC/C,AAAI,aACF,MAAM0P,WAAc;EAGtB,IAAM,UAAU,OAAO,OAAO,CAAC,CAAC;EAChC,OAAO,YACL,kBAAkB,MAAM,CAAC,CAAC,WAAW,QAAQ;GAC3C,KAAK,sBAAsB;GAC3B,iBAAiB;GACjB,QAAQ;GACR,SAAS;IACP,kBAAkB3P;IAClB,gBAAgB;GAClB;GACA,OAAO;IAAC,GAAG;IAAO,GAAG;GAAoB;EAC3C,CAAC,CACH,CAAC,CAAC,KACA,UAAU,WAAW;GACnB,IAAM,QACH,UAAU,OAAO,WAAW,OAAO,QAAQ,MAAM,OAAO,QAAQ,EAAE,CAAC,YACpE;GAKF,OAHK,QAGE,GAAG;IAAC,MAAM;IAAoB,IAAIA;IAAM;GAAK,CAAC,IAF5C,iBAAiB,gBAAI,MAAM,4BAA4B,CAAC;EAGnE,CAAC,CACH;CACF,CAAC,CACH,CACF,CACD,CACH;AACF;AAEA,SAAgB,WAAW,EACzB,UACA,QACA,MACA,aAMC;CACD,OAAO,SAAS,IAAI,CAAC,CAAC,KACpB,WAAW,gBACF,OACL,GAAG;EAAC,MAAM;EAAiB,MAAM;CAAW,CAAC,GAC7C,sBAAsB,MAAM,CAAC,CAAC,KAC5B,WAAW,SAAS;EAClB,IAAI,CAAC,QAAQ,CAAC,KAAK,QACjB,OAAO,iBAAiB,gBAAI,MAAM,qBAAqB,CAAC;EAE1D,IAAMA,SAAOC,KAAa,GACpB,OAAO;EAGb,OAFA,+BAA+B,IAAI,GAE5B,OACL,GAAG;GAAC,MAAM;GAAiB,MAAA;EAAI,CAAC,GAChC,YACE,kBAAkB,MAAM,CAAC,CAAC,WAAW,QAUlC;GACD,KAAK,uBAAuB,OAAO,OAAO,CAAC,CAAC;GAC5C,iBAAiB;GACjB,QAAQ;GACR,SAAS;IACP,kBAAkBD;IAClB,gBAAgB;GAClB;GACA;GACA,OAAO;EACT,CAAC,CACH,CAAC,CAAC,KACA,UAAU,WACD,wBAAwBA,QAAM,OAAO,OAAO,KAAK,IAAI,CAAC,CAAC,KAE5D,UAAU,UACJ,MAAM,SAAS,YAGZ,KAAK,8BAA8B,QAAQA,QAAM,SAAS,CAAC,CAAC,CAAC,KAClE,UAAU,QAAQ,GAAG;GAAC,GAAG;GAAO,OAAO;EAAG,CAAC,CAAC,CAC9C,IAJS,GAAG,KAAK,CAKlB,GACD,YAAY,QAEH,aAAa,QAAQA,MAAI,CAAC,CAAC,KAAK,eAAe,iBAAiB,GAAG,CAAC,CAAC,CAC7E,CACH,CACD,CACH,CACF;CACF,CAAC,CACH,CACF,CACD,CACH;AACF;AAgBA,SAAS,UAAU,QAAsB,SAAiB;CACxD,IAAM,EAAC,YAAW,OAAO,OAAO;CAChC,OAAO,kBAAkB,MAAM,CAAC,CAAC,QAAwB;EACvD,KAAK,uBAAuB,QAAQ,GAAG;EACvC,iBAAiB;EACjB,QAAQ;EACR,OAAO;CACT,CAAC;AACH;AAEA,SAAS,WAAW,QAAsB,MAAuC;CAC/E,IACI,cACA,QAAQ,GACR,SACA;CACJ,OAAO,IAAI,SAAS,SAAS,WAAW;EACtC,eAAgB,YAA0C,YAAY;GACpE,IAAI;IACF,SAAS,MAAM,UAAU,QAAQ,IAAI;GACvC,SAAS,KAAK;IACZ,OAAO,GAAG;IACV;GACF;GAUA,AATA,UAAU,UAAU,OAAO,QAAQ,OAAO,KAAK,UAC3C,YACF,cAAc,YAAY,GAC1B,QAAQ,MAAM,IAEZ,QAAQ,OACV,cAAc,YAAY,GAC1B,OAAO,gBAAI,MAAM,uBAAuB,CAAC,IAE3C;EACF,GAAG,GAAI;CACT,CAAC;AACH;AAEA,eAAe,8BACb,QACA,MACA,YACA;CACA,IAAI,QACA;CACJ,IAAI;EACF,SAAS,MAAM,WAAW,QAAQ,IAAI;CACxC,SAAS,KAAK;EACZ,OAAO,QAAQ,OAAO,GAAG;CAC3B;CACA,IAAI;EACF,QAAQ,MAAM,SAAS,QAAQ,OAAO,KAAK,QAAQ;CACrD,SAAS,KAAK;EACZ,OAAO,QAAQ,OAAO,GAAG;CAC3B;CAEA,IAAM,MAAM;EACV,KAAK;EACL,OAAO;EACP,QAAQ,MAAM,KAAK;EACnB,MAAM,MAAM;EACZ,SAAS,MAAM,KAAK;EACpB,YAAY,MAAM,KAAK,aAAa,EAAE,EAAE;EACxC,UAAU,OAAO,KAAK;CACxB;CACA,OAAO,OAAO,gBAAgB,GAAG,CAAC,CAAC,WAC1B,GACR;AACH;AAEA,SAAS,SAAS,MAAY;CAC5B,IAAI,OAAO,SAAW,OAAe,gBAAgB,OAAO,MAAM;EAChE,IAAM,cAAc,gBAAgB,CAAC,GAAG,IAAI;EAC5C,OAAO,GAAG,WAAW;CACvB;CACA,OAAO,iBAAiB,gBAAI,MAAM,cAAc,CAAC;AACnD;AAEA,SAAS,QAAQ,KAAiC;CAChD,IAAM,QAAQ,gBAAI,MAAM,aAAa;CACrC,IAAI,OAAO,OAAQ,UACjB,OAAO,iBAAiB,KAAK;CAE/B,IAAI,eAAe,IAAI,KAAK;CAC5B,eAAe,qBAAqB,YAAY;CAChD,IAAI;CACJ,IAAI;EACF,SAAS,IAAI,IAAI,YAAY;CAC/B,QAAQ;EACN,OAAO,iBAAiB,KAAK;CAC/B;CAIA,OAHI,UAAU,CAAC,OAAO,SAAS,MAAM,cAAc,IAC1C,iBAAiB,KAAK,IAExB,GAAG,YAAY;AACxB;AAEA,SAAS,gBAAgB,MAAoC,MAAY;CACvE,IAAI,OAAO,SAAW,OAAiB,gBAAgB,OAAO,MAG9D,OAAO;EACL,MAAM,KAAK,qBAAqB,KAAQ,KAAA,IAAY,KAAK;EACzD,MAAM,KAAK;CACb;AACF;AClTA,SAAgB,WAAW,KAAsB;CAC/C,IAAI;EACF,IAAM,SAAS,IAAI,IAAI,GAAG;EAC1B,OAAO,UAAU,CAAC,CAAC,OAAO,SAAS,MAAM,cAAc;CACzD,QAAQ;EACN,OAAO;CACT;AACF;;;;;AAMA,SAAgB,cAAc,OAAoC;CAChE,OACE,gBAAgB,SAChB,OAAO,MAAM,cAAe,YAC5B,OAAO,MAAM,cACb,MAAM,cAAc;AAExB;;;;;;AChBA,SAAgB,oBAAoB,cAA4B;CAC9D,IAAM,QAAQ,MAAM,KAAK,aAAa,SAAS,CAAC,CAAC,GAC3C,QAAQ,MAAM,KAAK,aAAa,SAAS,CAAC,CAAC;CAIjD,OAHI,SAAS,MAAM,SAAS,IACnB,QAAQ,QAAQ,KAAK,IAEvB,eAAe,KAAK,CAAC,CAAC,MAAM,QAAQ,IAAI,KAAK,CAAC;AACvD;AAEA,SAAS,eAAe,OAA2B;CACjD,OAAO,QAAQ,IACb,MAAM,KAAK,SAAS;EAElB,IAAI,KAAK,SAAS,UAAU,KAAK,kBAAkB;GACjD,IAAI;GAEJ,IAAI;IACF,QAAQ,KAAK,iBAAiB;GAChC,QAAQ;IACN,OAAO,CAAC,KAAK,UAAU,CAAC;GAC1B;GAIA,OAHK,QAGE,MAAM,cAAc,KAAK,KAAK,IAAI,CAAC,KAAK,UAAU,CAAC,IAFjD,CAAC;EAGZ;EAGA,IAAI,KAAK,SAAS,QAAQ;GACxB,IAAM,OAAO,KAAK,UAAU;GAC5B,OAAO,QAAQ,QAAQ,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC;EAC3C;EAGA,OAAO,IAAI,SAAS,YAAY,KAAK,YAAY,OAAO,CAAC,CAAC,CAAC,MAAM,QAC/D,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,GAAG,eAAe,EAAC,MAAM,KAAK,KAAI,CAAC,CAAC,IAAI,CAAC,CAC/D;CACF,CAAC,CACH;AACF;AAEA,SAAS,OAAO,OAAsD;CACpE,OAAO,MAAM;AACf;AACA,SAAS,YAAY,OAA2D;CAC9E,OAAO,MAAM;AACf;AAEA,SAAS,KAAK,OAA6B;CACzC,IAAI,OAAO,KAAK,GACd,OAAO,IAAI,SAAS,YAAY,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,IAAI,CAAC;CAG5E,IAAI,YAAY,KAAK,GAAG;EACtB,IAAM,MAAM,MAAM,aAAa;EAC/B,OAAO,IAAI,SAAc,YAAY,IAAI,YAAY,OAAO,CAAC,CAAC,CAC3D,MAAM,YAA+B,QAAQ,QAAQ,SAAS,CAAC,KAAK,KAAK,WAAW,GAAG,CAAC,CAAC,CAAC,CAC1F,MAAM,YAAY,QAAQ,IAAI,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,QAAQ,IAAI,KAAK,CAAC,CAAC;CAC/E;CACA,OAAO,QAAQ,QAAQ,CAAC,CAAC;AAC3B;ACrDA,SAAwB,aAAA,IAKd;eAL2B,EACnC,OAAO,eACP,UACA,gBACA,WAJmCE,IAOjCC;CAEI,AAAA,EAAA,OAAA,YAAA,EAAA,OAEqCC,eAAAA,OAAAA,EAAAA,OAQvC,kBAZF,MAAC,gBAAgB;EAYf,AAXK,aAAa,OAChB,SAAS,WAAW,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAE1C,YAAY,QAAQ,eAAe,OACrC,SACE,WAAW,KAAK,CACd,aAAa;GAAC,OAAO,CAAC;GAAG,OAAO;EAAW,CAAC,GAC5C,IAAI;GAAC,OAAO;GAAa,OAAO;GAAM,MAAM,YAAY;EAAG,GAAG,CAAC,OAAO,CAAC,CACzE,CAAC,CACH,GAEF,eAAe,EAAK;CACtB,GAXI,EAAA,KAAA,UAEqCA,EAAAA,KAAAA,eAAAA,KAQvC,EAAA,KAAA;CAbJ,IAAM,eAAeC,IAkBdC;CAAP,OAAsD,EAAA,OAAA,UAAA,EAAA,OAAtB,gBAAzB,KAAA,oBAAC,eAAD;EAAe,UAAU;EAAsB;CAAS,CAAA,GAAT,EAAA,KAAA,QAAtB,EAAA,KAAA,sCAAzBA;AACT;;AC9BA,MAAM,eAAe,OAAO,MAAM,CAAC,CAAA,WAAA;;;;AAMnC,SAAwB,aAAA,IAOrB;gBAPkC,EACnC,gBACA,OACA,UACA,WAJmCE,IAQ7B,KAAK,eAAe,MAAM,KACAC;CAAM,AAAA,EAAA,OAAA,8BAAN,WAAM,eAAe,EAAK,GAApB,EAAA,KAAA;CAAtC,IAAM,cAAcC,IAShBC;CAES,AAAA,EAAA,OAAA,SAAA,EAAA,OADC,UAAA,EAAA,OAEE,YAAA,EAAA,OACM,kBAJlB,KAAA,oBAACG,cAAD;EACU;EACD;EACG;EACM;CACjB,CAAA,GAHQ,EAAA,KAAA,OADC,EAAA,KAAA,QAEE,EAAA,KAAA,UACM,EAAA,KAAA;CAXpBF,IAAAA;CADF,OAKa,EAAA,OAAA,eAAA,EAAA,OADL,MAAA,EAAA,OAIJD,MAPF,KAAA,oBAAC,cAAD;EACE,sBAAA;EACA,QAAO;EACH;EACJ,SAAS;EACT,OAAO;EAEPA,UAAAA;CAMY,CAAA,GATH,EAAA,KAAA,aADL,EAAA,KAAA,IAIJA,EAAAA,KAAAA,8BAPFC;AAeJ;ACjCA,MAAa,mBAAmB,OAA2B,aAAwC;eAC3F,SAASM,YAAU,GACNH;CAAnB,OACO,EAAA,OAAA,SAAA,EAAA,OAKmB,UAAA,EAAA,OAFxB,YAJiB,WAAM;EACvB,AAAK,UAGL,SAAS,WAAW,KAAK,MAAM,CAAC,CAAC,GAC7B,MAAM,WACH,iBAAiB,QAAQ,MAAM,OAAO,GAEzC,MAAM,OACH,OAAO,OAAO,MAAM,GAAG;CAEhC,GAVO,EAAA,KAAA,OAKmB,EAAA,KAAA,QAFxB,EAAA,KAAA,kCAJKC;AAYT,GCnBa,cAAc,OAAO,IAAA,WAAA;;;AAAG,CAAA,CAAA,iFCK/B,cAAc,OAAO,IAAI,CAAC,CAAA,WAAA;;;4CAK1B,cAAc,OAAO,IAAI,CAAC,CAAA,WAAA;;;6CAK1B,cAAc,OAAO,KAAK,CAAC,CAAA,WAAA;;;kCAK3B,cAAc,OAAO,IAAI,CAAC,CAAA,WAAA;;;kHAYnB,kBAAA,OAUP;gBAVyB,EAC7B,UAAA,IACA,UACA,UACA,MAAA,OAJ6BG,IAC7B,WAAA,OAAA,KAAA,IAAW,MAAXC,IAGA,OAAA,OAAA,KAAA,IAAO,cAAPC,IASM,mBAAmB,YAAY,IAMDC,IAAyBC;qDAAzB,KAAA;EAAC;EAAG;EAAG;EAAG;CAAC,GAAc,KAAA;EAAC;EAAU;EAAU;CAAK;CAIlD,IAAA,KAAA,YAAsB,OAA7CC;CAAuBC,AAAAA,EAAAA,OAAAA,kBAAvB,KAAA,oBAAC,aAAD;EAAa,MAAM;EAAIA,UAAAA;CAAyC,CAAA,GAAzCA,EAAAA,KAAAA;CAJ7BC,IAAAA;CAIMF,AAAAA,EAAAA,OAAAA,MAAAA,EAAAA,OADC,QAHP,KAAA,oBAAC,MAAD;EAAM,SAAQ;EAAS,KAAKF;EAAc,WAAWC;EACnD,UAAA,oBAAC,MAAD;GAAM,MAAM;GACV,UAAA,qBAAC,QAAD;IAAQ,KAAK;IAAb,UAAA,CACG,MACDC,EACM;;EACJ,CAAA;CACF,CAAA,GAHAA,EAAAA,KAAAA,IADC,EAAA,KAAA;CAMPG,IAAAA;CACyB,AAAA,EAAA,OAAA,wBADzB,KAAA,oBAAC,MAAD;EAAM,WAAW;EAAG,QAAQ;EAAG,QAAQ;EACrC,UAAA,oBAAC,gBAAD,EAAgB,OAAO,SAAW,CAAA;CAC9B,CAAA,GADmB,EAAA,KAAA;CAX3BC,IAAAA;CACEF,AAAAA,EAAAA,OAAAA,MAAAA,EAAAA,QASAC,MAVF,KAAA,qBAAC,aAAD,EAAA,UAAA,CACED,IASAC,EAGW,EAAA,CAAA,GAZXD,EAAAA,KAAAA,IASAC,EAAAA,MAAAA;CAKDE,IAAAA;CAOa,AAAA,EAAA,QAAA,oBAAA,EAAA,QAPb,YACC,MAAA,WAAA,oBAAC,QAAD;EACE,UAAU;EACV,MAAK;EACL,MAAK;EACL,MAAK;EACL,SAAS;EACT,UAAU;CACX,CAAA,IACC,MAFU,EAAA,MAAA,kBAPb,EAAA,MAAA;CAjBLC,IAAAA;CADF,OAkBOD,EAAAA,QAAAA,OAAAA,EAAAA,QAfDD,MAFJ,MAAA,oBAAC,aAAD;EAAa,MAAK;EAAU,SAAS;EAAG,QAAA;EAAO,QAAO;EACpD,UAAA,qBAAC,aAAD;GAAa,OAAM;GAAS,SAAQ;GAAgB,QAAO;GAAO,WAAU;GAAM,KAAK;GAAvF,UAAA,CACEA,IAeCC,GAUU;;CACF,CAAA,GAXRA,EAAAA,MAAAA,KAfDD,EAAAA,MAAAA,gCAFJE;AA8BJ,GCjEM,UAAU,EAAC,OAAO,SAAS,UAAU,UAAU,aAAmB;CACtE,IAAM,YAAY,cACZ,OAAO,WAAW,cACb,wBAEL,OAAO,WAAW,uBACb,gCAEL,OAAO,WAAW,YACb,sBAEL,OAAO,WAAW,WAGX,OAAO,WAAW,QAK5B,CAAC,KAAK,CAAC,GACJ,8BAA8B,cAAuB;EAIzD,IACE,OAAO,MAAM,mBAAmB,UAChC,OAAO,MAAM,mBAAmB,WAAW,YAE3C,OAAO;EAIT,IAAM,QAAQ,OAAO,MAAM,mBAAmB;EAI9C,OAHI,CAAC,SAAS,MAAM,WAAW,IACtB,KAEF,MAAM,MAAM,SAAS,KAAK,WAAW,WAAW;CAEzD,GAAG,CAAC,OAAO,MAAM,mBAAmB,QAAQ,OAAO,MAAM,mBAAmB,KAAK,CAAC,GAC5E,UAAU,OAAuB,IAAI,GACrC,UAAU,OAAuB,IAAI,GACrC,qBAAqB,gBAAgB,OAAO,QAAQ;CAqC1D,OAnCA,gBAAgB;EACd,IAAM,QAAQ,SAAS,cAAc,OAAO;EAM5C,AALA,MAAM,YAAY,0CAEd,QAAQ,SAAS,cACnB,QAAQ,QAAQ,WAAW,YAAY,KAAK,GAE1C,SAAS,SAAS,cACpB,QAAQ,QAAQ,WAAW,YAAY,MAAM,UAAU,EAAI,CAAC;CAEhE,GAAG,CAAC,CAAC,GAEL,gBAAgB;EACd,IAAI,OAAO,WAAW,WAGpB,MAFA,mBAAmB,GAET,MAAM,MAAM,MAAM,QAAQ,UAAU,KAAK,GAAG,CAAC;CAE3D,GAAG;EAAC,MAAM,MAAM,QAAQ;EAAU,OAAO;EAAQ;CAAkB,CAAC,GAEhE,CAAC,SAAS,CAAC,MAAM,SACZ,OAGL,YAEA,oBAAC,gBAAD;EACE,UAAU;EACV,UAAU,OAAO;EACjB,MAAO,cAAc,MAAQ,aAAc;EAC3C,UAAU,WAAW,KAAA,UAAkB,mBAAmB;CAC3D,CAAA,IAKH,qBAAC,aAAD;EAAoB;EAAO,WAAW,QAAQ;EAA9C,UAAA,CACG,WAAW,oBAAC,aAAD;GAAa,MAAK;GAAc,UAAA;EAAqB,CAAA,GAChE,+BACC,oBAAC,MAAD;GACE,SAAS;GACT,QAAQ;GACR,OAAO;IACL,YAAY;IACZ,UAAU;IACV,KAAK;IACL,MAAM;GACR;GAEA,UAAA,oBAAC,MAAD;IAAM,MAAM;IAAG,OAAO,EAAC,OAAO,uBAAsB;IAAG,UAAA;GAEjD,CAAA;EACF,CAAA,CAEG;;AAEjB;ACjHA,SAAgB,qBAAqB,QAAgD;CACnF,OAAO,eAAe,OAAO,MAAM,KAAK,OAAO;AACjD;AAEA,SAAgB,eAAe,MAIpB;CACT,IAAM,EAAC,MAAM,QAAQ,cAAa,MAC5B,uBAAuB,UAAU,SAAS,UAAU,OACpD,sBAAsB,IAAI,UAAU,QACpC,UAAU,OAAO,KAAK,KAAK;CAEjC,OAAO;EACL,sBAAsB,KAAK,eAAe,oBAAoB;EAC9D,UAAU,qBAAqB,MAAM;EACrC,sBAAsB,KAAK,SAAS,IAAI,oBAAoB,KAAK;EACjE,uBAAuB,KAAK,SAAS,qBAAqB;CAC5D,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;AACb;AClBA,MAAa,aAAa,uBAAO,QAAQ,CAAC,CAAA,WAAA;;;AAAE,CAAA,CAAA,EAAA,EAAC,YAAW;CAEtD,IAAM,EAAC,cAAa,MAAM,QAEpB,OAAO,MAAM,OAAO,MAAM;CAGhC,OAAO,GAAG,6EAKU,eAAe;EAAC;EAAM,QAAA;GAP1B,OAAO;GAAG,OAAO;EAOS;EAAQ;CAAS,CAAC,EAAE;AAoBhE,CAAC;ACvBD,SAAgB,kBACd,OAIA;gBAEQ,MAEN,QACA,SAOA,UANA,UAHI,QAIJ,UACA,UAKA,KACG,MALHE,IAEA,MADA;CAKE,AAAA,EAAA,OAAA,kNAdE,CACJ,MAAM,MACN,IAAI,QACJ,QACA,SACA,UACA,UACA,UACA,KAAA,IACA,WACA,MACA,UACA,KACA,GAAA,QACE;CANF,IAAA,MAAA,OAAA,KAAA,IAAM,IAANA,IAOI,SAAS,MAAM,GACf,KAAK,UAAU,QAGnBC;CACM,AAAA,EAAA,QAAA,yBADN,MAAC,UAA+C;EAC9C,AAAI,YAAY,MAAM,OAAO,SAC3B,SAAS,MAAM,KAAK,MAAM,OAAO,KAAK,CAAC;CAE3C,GAHM,EAAA,MAAA;CAFR,IAAM,eAAeC,IAYhBC;CAEe,AAAA,EAAA,QAAA,QAAA,EAAA,QAAA,YAAA,EAAA,QADW,OAAA,EAAA,QAAP,QADnB,KAAA,QACC,oBAAC,KAAD;EAAK,aAAa,OAAO,MAAM,KAAA;EAC7B,UAAA,qBAAC,MAAD;GAAM,MAAM;GAAZ,UAAA,CACG,eAAe,IAAI,KAAK,MACxB,mBAAmB,IAAI,KAAK,oBAAC,MAAD,CAAO,CAAA,CAChC;;CACH,CAAA,GANN,EAAA,MAAA,MAEe,EAAA,MAAA,UADW,EAAA,MAAA,KAAP,EAAA,MAAA;CASnBC,IAAAA;CAC+B,AAAA,EAAA,QAAA,YAAA,EAAA,QAD/B,QAAA,EAAA,QACc,aADd,KAAA,QACC,oBAAC,MAAD;EAAM,OAAO;EAAW,MAAM;EAAU,cAAa;EAClD,UAAA;CACG,CAAA,GAFwB,EAAA,MAAA,UAD/B,EAAA,MAAA,MACc,EAAA,MAAA;CAbjBC,IAAAA;CAEGF,AAAAA,EAAAA,QAAAA,MAAAA,EAAAA,QAUAC,MAZH,KAAA,qBAAC,MAAD;EAAM,OAAM;EAAS,SAAQ;EAA7B,UAAA,CAEGD,IAUAC,EAKG;KAfHD,EAAAA,MAAAA,IAUAC,EAAAA,MAAAA;CAbL,IAAM,UACJC,IAyBEC;CAEU,AAAA,EAAA,QAAA,UAAA,EAAA,QACC,WAAA,EAAA,QAMC,YAAA,EAAA,QAHA,gBAAA,EAAA,QAFN,MAAA,EAAA,QACM,YALZ,KAAA,oBAAC,SAAD;EACE,eAAY;EACJ;EACC;EACL;EACM;EACV,UAAU;EACV,MAAK;EACL,OAAM;EACI;CACX,CAAA,GARS,EAAA,MAAA,QACC,EAAA,MAAA,SAMC,EAAA,MAAA,UAHA,EAAA,MAAA,cAFN,EAAA,MAAA,IACM,EAAA,MAAA;CATdC,IAAAA;CADF,OAEK,EAAA,QAAA,WAAA,EAAA,QAD0C,YAAA,EAAA,QAAd,MAAA,EAAA,QAA6B,OAAA,EAAA,QAA5C,QAAA,EAAA,QAIdD,MAJF,KAAA,qBAAC,YAAD;EAAY,GAAI;EAAM,SAAS;EAAc;EAAe;EAA5D,UAAA,CACG,SAGDA,EAWU;KAdT,EAAA,MAAA,SAD0C,EAAA,MAAA,UAAd,EAAA,MAAA,IAA6B,EAAA,MAAA,KAA5C,EAAA,MAAA,MAIdA,EAAAA,MAAAA,8BAJFC;AAiBJ;AC7DA,MAAM,WAAW,OAAO,IAAI,CAAC,CAAA,WAAA;;;8FASvB,aAAa,OAAO,MAAM,CAAC,CAAA,WAAA;;;yCAM3B,gBAAgB,UACb,MAAM,UAAU;AAGzB,SAAS,kBACP,OAQA;gBACM,EAAC,OAAO,UAAU,aAAa,gBAAgB,UAAU,UAAU,WAAU,OAC7E,CAAC,MAAM,WAAW,SAAS,EAAK,GAChC,CAAC,aAAa,cAAc,SAAgC,IAAI,GAChE,WAAyB,kBAAkB,KAAK,CAAC,EAAE,WAAW,UAC9D,EAAC,oBAAmB,iBAAiB,MAAM,MAAM,GACLE;qDAAC,KAAA,EAAA,WAAW,GAAI;CAAlE,IAAM,EAAC,aAAa,gBAAe,eAAeA,EAAiB,GAEvCC;CAAM,AAAA,EAAA,OAAA,wBAAN,WAAM,SAAS,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,GAAnC,EAAA,KAAA;CAAlC,IAAM,UAAUC,IAEiBC;CAEb,AAAA,EAAA,OAAA,SAAA,EAAA,OAAZ,eAFyB,KAAA,YAAY;EAE3C,AADA,QAAQ,EAAK,GACb,MAAM,YAAY,KAAK;CACzB,GADoB,EAAA,KAAA,OAAZ,EAAA,KAAA;CAFR,IAAM,eAAeC,IAKXC,IAKPC;CALH,AACc,EAAA,OAAA,eAAA,EAAA,OAAR,QADI,WAAM;EACd,AAAI,QAAQ,eAEV,QAAQ,EAAK;CAEjB,GAAG,KAAA,CAAC,aAAa,IAAI,GAJP,EAAA,KAAA,aAAR,EAAA,KAAA,sDADN,UAAUD,IAKPC,EAAmB;CAGpBC,IAAAA;sDAAM,WAAA,QAAQ,EAAK;CACnBC,IAAAA;CAFF,AAES,EAAA,QAAA,4BAAP,WAAM,CAAC,WAAW,GAAX,EAAA,MAAA,0BAFT,qBACED,IACAC,EACF;CAIKC,IAAAA;oCACC,KAAA,YAAA,oBAAC,SAAD;EACE,SAAA;EACA,SACE,oBAAC,KAAD;GAAK,SAAS;GACZ,UAAA,oBAAC,MAAD;IAAM,OAAA;IAAM,MAAM;IAChB,UAAA;GACI,CAAA;EACH,CAAA;EAEP,WAAU;EACV,QAAA;EAEA,UAAA,oBAAC,UAAD;GAAU,QAAQ;GAAG,QAAQ;GAAG,QAAO;GAAO,MAAK;GACjD,UAAA,oBAAC,YAAD;IAAY,MAAM;IAAU,MAAK;IAAQ,MAAK;GAAY,CAAA;EAClD,CAAA;CACH,CAAA,GAhBV,EAAA,MAAA;CAsBKC,IAAAA;sDAAC,KAAA,oBAAA,KAAD;EAAK,SAAS;EACZ,UAAA,oBAAC,OAAD;GAAO,OAAA;GAAM,MAAM;GACjB,UAAA;EACK,CAAA;CACJ,CAAA;CACLC,IAAAA;CACU,AAAA,EAAA,QAAA,UAAA,EAAA,QAEE,YAAA,EAAA,QAEA,YALZ,KAAA,oBAAC,mBAAD;EACU;EACR,MAAM;EACI;EACV,MAAK;EACL,UAAU;EACV,UAAU;CACX,CAAA,GANS,EAAA,MAAA,QAEE,EAAA,MAAA,UAEA,EAAA,MAAA;CAGZC,IAAAA;CAGiB,AAAA,EAAA,QAAA,gCAHjB,MAAA,oBAAC,UAAD;EACE,MAAM;EACN,MAAK;EACL,eAAe,eAAe,cAAc;CAC7C,CAAA,GADgB,EAAA,MAAA;CAEhBC,IAAAA;CAAa,AAAA,EAAA,QAAA,SAAA,EAAA,QAeC,gBAAA,EAAA,QACa,eAAA,EAAA,QAAZ,YAAA,EAAA,QAXK,kBALpB,MAAA,aAAa,KAAK,KACjB,qBAAAU,UAAA,EAAA,UAAA;EACE,oBAAC,UAAD;GACE,MAAM;GACN,MAAK;GACL,eAAe,eAAe,gBAAgB;EAC/C,CAAA;EACD,oBAAC,UAAD;GACE,MAAM;GACN,MAAK;GACL,eAAe,eAAe,eAAe;EAC9C,CAAA;EACD,oBAAC,UAAD;GACE,MAAM;GACN,MAAK;GACL,SAAS;GACT,UAAU,YAAY;EACvB,CAAA;CACD,EAAA,CAAA,GAlBU,EAAA,MAAA,OAeC,EAAA,MAAA,cACa,EAAA,MAAA,aAAZ,EAAA,MAAA,UAXK,EAAA,MAAA;CAerBT,IAAAA;sDAAC,MAAA,oBAAA,aAAD,CAAc,CAAA;CACdC,IAAAA;CAGiB,AAAA,EAAA,QAAA,gCAHjB,MAAA,oBAAC,UAAD;EACE,MAAM;EACN,MAAK;EACL,eAAe,eAAe,WAAW;CAC1C,CAAA,GADgB,EAAA,MAAA;CAEjBD,IAAAA;sDAAC,MAAA,oBAAA,aAAD,CAAc,CAAA;CACbE,IAAAA;CAKoB,AAAA,EAAA,QAAA,mBAAA,EAAA,QAAA,kBALpB,MAAA,mBACC,qBAAAO,UAAA,EAAA,UAAA,CACE,oBAAC,UAAD;EACE,MAAM;EACN,MAAK;EACL,eAAe,eAAe,SAAS;CACxC,CAAA,GACD,oBAAC,aAAD,CAAc,CAAA,CACd,EAAA,CAAA,GARH,EAAA,MAAA,iBAKoB,EAAA,MAAA;CAKrBN,IAAAA;CAIW,AAAA,EAAA,QAAA,WAAA,EAAA,QACC,YALZ,MAAA,oBAAC,UAAD;EACE,MAAK;EACL,MAAM;EACN,MAAK;EACL,SAAS;EACT,UAAU;CACX,CAAA,GAFU,EAAA,MAAA,SACC,EAAA,MAAA;CA7DdC,IAAAA;CAcEN,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAKCC,OAAAA,EAAAA,QAqBDE,OAAAA,EAAAA,QAMCC,OAAAA,EAAAA,QAUDC,OAAAA,EAAAA,QAlDAN,MANF,MAAA,qBAAC,MAAD;EAAM,KAAK;EAAX,UAAA;GACED;GAKAC;GAQAC;GAKCC;GAoBDC;GACAC;GAKAD;GACCE;GAUDC;EAOI;KAjDJL,EAAAA,MAAAA,KAKCC,EAAAA,MAAAA,KAqBDE,EAAAA,MAAAA,KAMCC,EAAAA,MAAAA,KAUDC,EAAAA,MAAAA,KAlDAN,EAAAA,MAAAA;CA8DJQ,IAAAA;CAKI,AAAA,EAAA,QAAA,gCALJ,MAAA,oBAAC,QAAD;EACE,MAAM;EACN,MAAK;EACL,UAAU;EACV,eAAe;GAEb,AADA,eAAe,EAAK,GACpB,QAAQ,EAAI;EACd;CACD,CAAA,GAHG,EAAA,MAAA;CA5ENC,IAAAA;CAqEQ,AAAA,EAAA,QAAA,QAAA,EAAA,QAlEJF,OAAAA,EAAAA,QAoEFC,OAvEF,MAAA,oBAAC,SAAD;EACE,SAAA;EACA,SACED;EAiEF,QAAA;EACM;EAENC,UAAAA;CASO,CAAA,GAXD,EAAA,MAAA,MAlEJD,EAAAA,MAAAA,KAoEFC,EAAAA,MAAAA;CA1FJE,IAAAA;CADF,OAoBID,EAAAA,QAAAA,OAAAA,EAAAA,QAlBCX,MADH,MAAA,qBAAC,QAAD;EAAQ,KAAK;EAAG,SAAS;EAAzB,UAAA,CACGA,IAkBDW,GAiFM;KAjFNA,EAAAA,MAAAA,KAlBCX,EAAAA,MAAAA,gCADHY;AAsGJ;AAEA,IAAA,4BAAe,KAAK,iBAAiB;ACrLrC,SAAgB,iBAAiB,cAA4B,aAAsB;gBAC3E,CAAC,UAAU,eAAe,SAAwB,IAAI,GACtD,CAAC,mBAAmB,wBAAwB,SAAS,EAAK,GAC1D,CAAC,2BAA2B,gCAAgC,SAAS,EAAK,GAEtEG;CAqB0B,AAAA,EAAA,OAAA,eAAA,EAAA,OAePC,aAAAA,SAAAA,EAAAA,OAlCVC,aAAAA,QAAAA,EAAAA,OAKUC,aAAAA,OAPnB,WAAM;EAEd,IAAI,aAAa,SAAS,OAAO;GAI/B,AAFA,qBAAqB,EAAK,GAC1B,6BAA6B,EAAK,GAClC,YAAY,IAAI;GAChB,IAAM,MAAM,aAAa,KAGnB,gBAAgB,YAAY;IAChC,qBAAqB,EAAI;IACzB,IAAI;KAEF,IAAM,iBAAgB,MADC,MAAM,KAAK,EAAC,QAAQ,OAAM,CAAC,EAAA,CACnB,QAAQ,IAAI,gBAAgB,GACrD,cAAc,gBAAgB,SAAS,eAAe,EAAE,IAAI;KAMlE,AAJA,qBAAqB,EAAK,GACtB,eACF,YAAY,WAAW,GAErB,gBAAgB,QAAQ,gBAAgB,KAAA,KAE1C,6BAA6B,EAAI;IAErC,QAAQ;KAIN,AAHA,QAAQ,KAAK,uCAAuC,GAEpD,6BAA6B,EAAI,GACjC,qBAAqB,EAAK;IAC5B;GACF;GAEK,cAAc;EACrB;EACA,AAAI,aAAa,SAAS,UACxB,YAAY,aAAa,MAAM,EAAE,CAAE,IAAI;CAE3C,GAjBoC,EAAA,KAAA,aAePF,EAAAA,KAAAA,aAAAA,OAlCVC,EAAAA,KAAAA,aAAAA,MAKUC,EAAAA,KAAAA,aAAAA;CA+B1BC,IAAAA;CAtCH,AAsCI,EAAA,OAAA,eAAA,EAAA,OAAa,gBAAd,KAAA;EAAC;EAAa;EAAc,aAAa;CAAI,GAA5C,EAAA,KAAA,aAAa,EAAA,KAAA,sCAtCjB,UAAUJ,IAsCPI,EAA8C;CAE1CC,IAAAA;CAAP,OAGE,EAAA,OAAA,6BAAA,EAAA,OAFA,YAAA,EAAA,QACA,qBAFK,KAAA;EACL;EACA;EACA;CACF,GADE,EAAA,KAAA,2BAFA,EAAA,KAAA,UACA,EAAA,MAAA,6CAFKA;AAKT;ACzCA,SAAgB,iBAAiB,cAA4B;eACrD,CAAC,oBAAoB,yBAAyB,SAAoC,IAAI,GACtF,CAAC,mBAAmB,wBAAwB,SAAS,EAAK,GACtDE;CAIoBC,AAAAA,EAAAA,OAAAA,aAAAA,SAAAA,EAAAA,OADXC,aAAAA,QAAAA,EAAAA,OAOSC,aAAAA,OAVlB,WAAM;EACd,IAAI,WAAW;EAEf,IAAI,aAAa,SAAS,QAAQ;GAChC,IAAM,OAAO,aAAa,MAAM;GAChC,WAAW,IAAI,gBAAgB,IAAK;EACtC;EAeA,IAZI,aAAa,SAAS,UACxB,WAAW,aAAa,MAI1B,sBAAsBC,OAKpB,GAEE,CAAC,UAAU,OAAOC;EAEtB,qBAAqB,EAAI;EACzB,IAAM,eAAe,SAAS,cAAc,OAAO;EACnD,aAAa,UAAU;EAEvB,IAAM,oBAAoB,OAClB;GACJ,qBAAqB,EAAK;EAC5B,SACM;GACJ,IAAM,WAAW,aAAa,UACxB,QAAQ,aAAa,YACrB,SAAS,aAAa,aACtB,cAAc,SAAS,KAAK,UAAU,GACtC,cAAc,QAAQ;GAC5B,uBAAuB,WACd;IACL,GAAGC;IACO;IACH;IACC;IACK;IACA;GACf,EACD;EACH,CACF,GAEM,gBAAgB,YAA8B;GAClD,IAAM,kBAAkB,SAAS;GASjC,AARI,YACF,kBAAkB,SAAS,aACzB,QAAQ,oBAAoB,kBAAkB,QAAQ,CACxD,GACA,QAAQ,UAAU,MAClB,QAAQ,MAAM,IACd,QAAQ,KAAK,IAEX,iBAAiB,WAAW,OAAO,KACrC,IAAI,gBAAgB,eAAe;EAEvC;EAcA,OAbA,kBAAkB,WAAW,iBAAiB,aAAa,YAAY,GAAG,CAAC,CAAC,GAE5E,aAAa,gBAAgB;GAG3B,AAFA,qBAAqB,EAAK,GAC1B,QAAQ,KAAK,8CAA8C,GAC3D,aAAa,YAAY;EAC3B,GAEA,kBAAkB,SAAS,eACzB,aAAa,iBAAiB,kBAAkBC,UAAQ,CAC1D,GACA,aAAa,MAAM,gBAEN;GACX,aAAa,YAAY;EAC3B;CACF,GA5E8BN,EAAAA,KAAAA,aAAAA,OADXC,EAAAA,KAAAA,aAAAA,MAOSC,EAAAA,KAAAA,aAAAA;CAsEzBK,IAAAA;CAhFH,AAgFIC,EAAAA,OAAAA,4BAAD,KAAA,CAAC,aAAa,MAAM,YAAY,GAA/BA,EAAAA,KAAAA,0BAhFJ,UAAUT,IAgFPQ,EAAiC;CAE7BE,IAAAA;CAAP,OAGE,EAAA,OAAA,qBAAA,EAAA,OAFA,sBADK,KAAA;EACL;EACA;EACA;CACF,GADE,EAAA,KAAA,mBAFA,EAAA,KAAA,4CADKA;AAKT;AAlE0B,SAAAG,WAAA;CAAM,OAAA;;AAPN,SAAAD,QAAC,KAAA;CAAS,OAAA;EAC9B,GAAG;EACH,UAAU,KAAA;EACV,OAAO,KAAA;EACP,QAAQ,KAAA;CACV;;;;;;;;;ACzBJ,SAAgB,6BACd,WACA,SAe2B;CAC3B,IAAI,CAAC,UAAU,WAAW,CAAC,UAAU,UACnC,OAAO;CAGT,IAAM,OAAO,UAAU,QAAQ,IACzB,UAAU,UAAU,WAAW,IAO/B,cAAc,cAAsB,SAAoB;EAC5D,IAAM,mBAAmB,SAAS,oBAAoB,KAAK,GACrD,aAAa,mBAAmB,KAAK,mBAAmB,GAGxD,OAAO,SAAS,MAFR,aAAa,OAAO,OACpB,aAAa,OAAO,MAE5B,KAAM,eAAe,MAAO,MAC9B,UAAU,KAAK,MAAM,EAAE;EAG3B,OADI,YAAY,MAAG,UAAU,KAAK,IAAI,KAAK,IACpC,GAAG,QAAQ;CACpB,GAEM,qBAAqB,OAA2B,SAAwC;EAC5F,IAAI,CAAC,OAAO,OAAO;EACnB,IAAM,UAAU,MAAM,KAAK;EAC3B,IAAI,QAAQ,SAAS,IAAI,GACvB,OAAO,cAAc,OAAO;EAE9B,IAAI,QAAQ,SAAS,GAAG,GAAG;GACzB,IAAM,IAAI,OAAO,QAAQ,MAAM,GAAG,EAAE,CAAC;GAErC,OADK,OAAO,SAAS,CAAC,IACf,WAAW,GAAG,IAAI,IADO;EAElC;EACA,OAAO;CACT;CAKA,IAAI,UAAU,kBAAkB;EAC9B,IAAM,aAAa,UAAU,iBAAiB,OACxC,kBACJ,SAAS,UAAU,OAAO,kBAAkB,YAAY,GAAG,IAAI;EACjE,OAAO;GACL,GAAG,UAAU;GACb,mBACE,SAAS,UAAU,OACd,kBAAkB,UAAU,iBAAiB,mBAAmB,GAAG,KACpE,UAAU,iBAAiB,oBAC3B,UAAU,iBAAiB;GACjC,iBACE,SAAS,UAAU,OACd,kBAAkB,UAAU,iBAAiB,iBAAiB,GAAG,KAClE,UAAU,iBAAiB,kBAC3B,UAAU,iBAAiB;GACjC,OAAO,mBAAmB,GAAG,KAAK;GAClC,SAAS,UAAU,iBAAiB,WAAW,GAAG,KAAK,MAAM,UAAU,GAAG,EAAE;EAC9E;CACF;CAEA,IAAM,WAAW,UAAU,YAAY;EAAC,GAAG;EAAI,GAAG;CAAE,GAiB9C,gBAAgB,UAAkB,KAAK,IAAI,MAAM,KAAK,IAAI,KAAK,KAAK,CAAC,GAIrE,mBAAmB,UAGhB,GADW,UAAU,KAAK,OAAO,GAAG,OAAO,EAAE,KAAK,KAAK,IAAI,KAAK,IAAI,OACrD,MAAO,MAAM,IAG/B,oCAAoC,MASpC,mBAAmB,SAAS,oBAAoB,KAAK,GACrD,mBAAmB,UAAU,oBAAoB,GACjD,sCAAsC,KAAK,IAC/C,GACA,KAAK,IAAI,KAAM,OAAO,mBAAoB,gBAAgB,CAC5D,GAEM,YAAY,oCAAoC,GAChD,aAAa,sCAAsC,GAEnD,aAAa,aACjB,KAAK,IAAI,SAAS,IAAI,WAAW,MAAM,iCAAiC,CAC1E,GACM,YAAY,aAChB,KAAK,IAAI,SAAS,IAAI,YAAY,MAAM,mCAAmC,CAC7E,GAEM,QAAQ,SAAS,SAAS,KAC1B,UAAU,UAAU,OAAO,WAAW,YAAY,GAAG,IAAI,gBAAgB,UAAU;CAazF,OAAO;EARL,gBAAgB;EAChB,iBALc,UAAU,OAAO,WAAW,WAAW,GAAG,IAAI,gBAAgB,SAAS;EAMrF,kBAAkB;EAClB,mBAAmB;EACnB,OAPY,UAAU,OAAO,WAAW,MAAM,GAAG,IAAI,GAAG,KAAK;EAQ7D,SAAS,GAAG,KAAK,MAAM,UAAU,GAAG,EAAE;CAGjC;AACT;;;;;;;;;;;ACpJA,SAAwB,YAAY,OAAe,KAAK,IAAO,KAAK,GAAG;CACrE,IAAM,SAAS,KAAK,MAAO;CAE3B,IAAI,KAAK,IAAI,KAAK,IAAI,QACpB,OAAO,QAAQ;CAGjB,IAAM,QAAQ,KACV;EAAC;EAAM;EAAM;EAAM;EAAM;EAAM;EAAM;EAAM;CAAI,IAC/C;EAAC;EAAO;EAAO;EAAO;EAAO;EAAO;EAAO;EAAO;CAAK,GACvD,IAAI,IACF,IAAI,MAAM;CAEhB;EAEE,AADA,SAAS,QACT,EAAE;QACK,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,MAAM,SAAS;CAE7E,OAAO,MAAM,QAAQ,EAAE,IAAI,MAAM,MAAM;AACzC;ACrBA,MAAM,aAAa,OAAO,MAAA,WAAA;;;AAAK,CAAA,CAAA,6rBAwCzB,mBAAmB,OAAO,IAAA,WAAA;;;AAAuB,CAAA,CAAA,8CAGzC,UAAU,MAAM,SAAS;AA0BvC,SAAwB,mBAAmB,EACzC,WACA,UACA,cACA,mBAC0B;CAC1B,IAAM,CAAC,YAAY,iBAAiB,SAAS,EAAK,GAC5C,CAAC,WAAW,gBAAgB,SAAS;EAAC,GAAG;EAAG,GAAG;CAAC,CAAC,GACjD,CAAC,eAAe,oBAAoB,SAAS;EAAC,GAAG;EAAG,GAAG;CAAC,CAAC,GACzD,eAAe,OAAuB,IAAI,GAC1C,qBAAqB,OAA8B,IAAI,GACvD,CAAC,eAAe,oBAAoB,SAAS,UAAU,YAAY;EAAC,GAAG;EAAI,GAAG;CAAE,CAAC,GAEjF,WAAW,eACX,OAAO,UAAU,QAAQ,IACzB,UAAU,UAAU,WAAW,IAE/B,uBAAuB,UAA6C;EACxE,IAAI,CAAC,OAAO,OAAO;EACnB,IAAM,UAAU,MAAM,KAAK;EAC3B,IAAI,CAAC,QAAQ,SAAS,GAAG,GAAG,OAAO;EACnC,IAAM,MAAM,OAAO,QAAQ,MAAM,GAAG,EAAE,CAAC;EAEvC,OADK,OAAO,SAAS,GAAG,IACjB,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,MAAM,GAAG,CAAC,IADP;CAEpC,GAEM,qBAAqB,kBAAkB;EAC3C,IAAM,YAAY,cAAc;EAChC,IAAI,CAAC,WAAW,OAAO;GAAC,GAAG;GAAG,GAAG;GAAG,OAAO;GAAG,QAAQ;EAAC;EAEvD,IAAM,OAAO,UAAU,sBAAsB,GACvC,aAAa,KAAK,OAClB,aAAa,KAAK,QAElB,UAAU,iBAAiB,SAC3B,SAAS,SAAS,cAAc,GAChC,SAAS,SAAS,eAAe;EAEvC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,cAAc,CAAC,YACxC,OAAO;GAAC,GAAG;GAAG,GAAG;GAAG,OAAO;GAAY,QAAQ;EAAU;EAI3D,IAAM,QAAQ,KAAK,IAAI,aAAa,QAAQ,aAAa,MAAM,GACzD,WAAW,SAAS,OACpB,WAAW,SAAS;EAI1B,OAAO;GAAC,IAHS,aAAa,YAAY;GAGtB,IAFH,aAAa,YAAY;GAEV,OAAO;GAAU,QAAQ;EAAQ;CACnE,GAAG,CAAC,cAAc,eAAe,CAAC,GAE5B,qBAAqB,UAAoE;EAC7F,IAAI,CAAC,OAAO,OAAO;EACnB,IAAM,UAAU,MAAM,KAAK,GACrB,KAAK,QAAQ,SAAS,IAAI,GAC1B,MAAM,QAAQ,SAAS,GAAG,GAC1B,MAAM,OAAO,QAAQ,QAAQ,SAAS,EAAE,CAAC;EAI/C,OAHK,OAAO,SAAS,GAAG,IACpB,KAAW;GAAC,GAAG;GAAK,MAAM;EAAI,IAC9B,MAAY;GAAC,GAAG;GAAK,MAAM;EAAG,IAC3B,OAH2B;CAIpC,GAEM,sBAAsB,YAAgC;EAC1D,IAAM,OAAO,cAAc,SAAS,sBAAsB,GACpD,IAAI,MAAM,SAAS,GACnB,IAAI,MAAM,UAAU,GACpB,aAAa,IAAI,GACjB,QAAQ,aAAa,OAAO,MAC5B,QAAQ,aAAa,OAAO,MAE5B,KAAK,kBAAkB,QAAQ,iBAAiB,GAChD,KAAK,kBAAkB,QAAQ,eAAe,GAC9C,KAAK,kBAAkB,QAAQ,KAAK,GACpC,gBAAgB,oBAAoB,QAAQ,OAAO,GAEnD,SAAS,GAAyC,SAAoB;GAC1E,IAAK,GAGL,OAFI,EAAE,SAAS,MAAY,GAAG,EAAE,EAAE,KAC9B,SAAS,MAAY,GAAI,EAAE,IAAI,IAAK,MAAM,MACvC,GAAI,EAAE,IAAI,IAAK,MAAM;EAC9B,GAEM,+BACA,QAAQ,qBAAqB,SACxB;GAAC,MAAM,MAAM,IAAI,GAAG;GAAG,OAAO,KAAA;GAAW,WAAW;EAAiB,IAE1E,QAAQ,qBAAqB,UACxB;GAAC,OAAO,MAAM,IAAI,GAAG;GAAG,MAAM,KAAA;GAAW,WAAW;EAAiB,IAEvE;GAAC,MAAM;GAAO,OAAO,KAAA;GAAW,WAAW;EAAoB,GAGlE,6BACA,QAAQ,mBAAmB,QACtB;GAAC,KAAK,MAAM,IAAI,GAAG;GAAG,QAAQ,KAAA;EAAS,IAE5C,QAAQ,mBAAmB,WACtB;GAAC,QAAQ,MAAM,IAAI,GAAG;GAAG,KAAK,KAAA;EAAS,IAEzC;GAAC,KAAK;GAAO,QAAQ,KAAA;EAAS,GAGjC,SAAS,uBAAuB,GAChC,SAAS,qBAAqB,GAEhC,YAAY,OAAO;EAMvB,OALI,QAAQ,mBAAmB,aAC7B,YACE,QAAQ,qBAAqB,WAAW,0BAA0B,uBAG/D;GACL,UAAU;GACV,GAAG;GACH,GAAG;GACH;GACA,OAAO,KAAK,MAAM,IAAI,GAAG,IAAI,GAAG,KAAK;GACrC,SAAS,iBAAiB;GAC1B,QAAQ;EACV;CACF,GAEM,oBAAoB,aACvB,iBAAkC;EAIjC,AAHI,mBAAmB,WACrB,aAAa,mBAAmB,OAAO,GAEzC,mBAAmB,UAAU,iBAAiB;GAC5C,SAAS,YAAY;EACvB,GAAG,GAAG;CACR,GACA,CAAC,QAAQ,CACX;CAUA,AARA,sBACe;EACX,AAAI,mBAAmB,WACrB,aAAa,mBAAmB,OAAO;CAE3C,GACC,CAAC,CAAC,GAEL,gBAAgB;EACd,AAAI,CAAC,cAAc,UAAU,YAE3B,iBAAiB,UAAU,QAAQ;CAEvC,GAAG,CAAC,UAAU,UAAU,UAAU,CAAC;CAEnC,IAAM,kBAAkB,aACrB,MAAwB;EAIvB,AAHA,EAAE,eAAe,GACjB,cAAc,EAAI,GAClB,aAAa;GAAC,GAAG,EAAE;GAAS,GAAG,EAAE;EAAO,CAAC,GACzC,iBAAiB;GAAC,GAAG,SAAS;GAAG,GAAG,SAAS;EAAC,CAAC;CACjD,GACA,CAAC,QAAQ,CACX,GAEM,kBAAkB,aACrB,MAAkB;EACjB,IAAI,CAAC,cAAc,CAAC,cAAc,SAAS;EAG3C,IAAM,OADY,aAAa,QACR,sBAAsB,GACvC,UAAU,mBAAmB,GAC7B,WAAW,QAAQ,SAAS,KAAK,OACjC,WAAW,QAAQ,UAAU,KAAK,QAClC,KAAK,EAAE,UAAU,UAAU,GAC3B,KAAK,EAAE,UAAU,UAAU,GAE3B,gBAAiB,KAAK,WAAY,KAClC,gBAAiB,KAAK,WAAY,KAEpC,OAAO,cAAc,IAAI,eACzB,OAAO,cAAc,IAAI;EAO7B,AALA,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,IAAI,CAAC,GACtC,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,IAAI,CAAC,GAEtC,iBAAiB;GAAC,GAAG;GAAM,GAAG;EAAI,CAAC,GAEnC,kBAAkB;GAChB,GAAG;GACH,UAAU;IAAC,GAAG;IAAM,GAAG;GAAI;EAC7B,CAAC;CACH,GACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CACF,GAEM,gBAAgB,kBAAkB;EAMtC,AALA,cAAc,EAAK,GACnB,AAEE,mBAAmB,aADnB,aAAa,mBAAmB,OAAO,GACV,OAE/B,SAAS;GACP,GAAG;GACH,UAAU;EACZ,CAAC;CACH,GAAG;EAAC;EAAW;EAAe;CAAQ,CAAC;CAcvC,IAZA,gBAAgB;EACd,IAAI,YAGF,OAFA,SAAS,iBAAiB,aAAa,eAAe,GACtD,SAAS,iBAAiB,WAAW,aAAa,SACrC;GAEX,AADA,SAAS,oBAAoB,aAAa,eAAe,GACzD,SAAS,oBAAoB,WAAW,aAAa;EACvD;CAGJ,GAAG;EAAC;EAAY;EAAiB;CAAa,CAAC,GAE3C,CAAC,UAAU,UACb,OAAO;CAGT,IAAM,mBAAmB,EAAQ,UAAU,kBACrC,mBAAmB,mBACpB,oBAAoB,UAAU,kBAAkB,OAAO,KAAK,UAC7D,SAEE,aAAa,mBAAmB,GAChC,gBAAgB,WAAW,QAAQ,KAAK,WAAW,SAAS,GAE5D,8BACA,mBACK,mBAAmB,UAAU,gBAAiB,IAEnD,gBACK;EACL,MAAM,GAAG,WAAW,IAAK,SAAS,IAAI,MAAO,WAAW,MAAM;EAC9D,KAAK,GAAG,WAAW,IAAK,SAAS,IAAI,MAAO,WAAW,OAAO;EAC9D,WAAW;EACX,OAAO,GAAG,KAAK,IAAI,GAAI,OAAO,MAAO,WAAW,KAAK,EAAE;EACvD,QAAQ,aAAa,aAAa;CACpC,IAEK;EACL,MAAM,GAAG,SAAS,EAAE;EACpB,KAAK,GAAG,SAAS,EAAE;EACnB,WAAW;EACX,OAAO,GAAG,KAAK;EACf,QAAQ,aAAa,aAAa;CACpC;CAGF,OACE,oBAAC,kBAAD;EACE,KAAK;EACL,UAAU;EACV,aAAa,mBAAmB,KAAA,IAAY;EAE5C,OAAO,sBAAsB;EAE7B,UAAA,oBAAC,OAAD;GAAK,KAAK,UAAU;GAAU,KAAI;GAAY,WAAW;EAAQ,CAAA;CACjD,CAAA;AAEtB;AAUA,SAAgB,kBAAkB,EAChC,WACA,UACA,oBACA,qBACA,mBACyB;CACzB,IAAM,CAAC,UAAU,eAAe,SAAS,UAAU,YAAY,EAAE,GAC3D,CAAC,UAAU,eAAe,SAAwB,IAAI,GACtD,CAAC,cAAc,mBAAmB,SAAS,EAAK,GAChD,CAAC,SAAS,cAAc,SAAyB,IAAI,GACrD,uBAAuB,OAA8B,IAAI,GACzD,CAAC,MAAM,WAAW,SACtB,UAAU,mBAAmB,WAAW,QAC1C,GAEM,gBAAgB,OAAO,EAAK,GAE5B,mBAAmB,aAAa,cAC7B,UAAU,SAAS,MAAM,KAAK,UAAU,SAAS,MAAM,KAAK,UAAU,SAAS,OAAO,GAC5F,CAAC,CAAC,GAEC,cAAc,aACjB,QAAgB;EAKf,AAJI,qBAAqB,WACvB,aAAa,qBAAqB,OAAO,GAGtC,OAeL,gBAAgB,EAAI,GACpB,WAAW,IAAI,GACf,YAAY,IAAI,GAEhB,qBAAqB,UAAU,iBAAiB;GAC9C,IAAI;IAEF,IAAM,WAAW,IADE,IAAI,GACN,CAAA,CAAO,SAAS,YAAY;IAC7C,IAAI,iBAAiB,QAAQ,GAAG;KAG9B,AAFA,WAAW,EAAI,GACf,YAAY,IAAI,GAChB,qBAAqB,IAAI;KACzB,IAAM,MAAM,IAAI,MAAM;KAqBtB,AApBA,IAAI,eAAe;MACjB,IAAM,mBACJ,IAAI,gBAAgB,IAAI,gBAAgB,IAAI,eAAe,IAAI,gBAAgB;MAEjF,AADA,cAAc,UAAU,IACxB,SAAS;OACP,GAAG;OACH,SAAS;OACT,UAAU;OACV;MACF,CAAC;KACH,GACA,IAAI,gBAAgB;MAElB,AADA,cAAc,UAAU,IACxB,SAAS;OACP,GAAG;OACH,SAAS;OACT,UAAU;OACV,kBAAkB,UAAU;MAC9B,CAAC;KACH,GACA,IAAI,MAAM;IACZ,OAAO;KACL,IAAM,WACJ;KAKF,AAJA,WAAW,EAAK,GAChB,YAAY,QAAQ,GACpB,qBAAqB,QAAQ,GAC7B,cAAc,UAAU,IACxB,SAAS;MACP,GAAG;MACH,SAAS;MACT,UAAU,KAAA;MACV,kBAAkB,KAAA;MAClB,kBAAkB,KAAA;KACpB,CAAC;IACH;GACF,QAAQ;IACN,WAAW,EAAK;IAChB,IAAM,WAAW;IAIjB,AAHA,YAAY,QAAQ,GACpB,qBAAqB,QAAQ,GAC7B,cAAc,UAAU,IACxB,SAAS;KACP,GAAG;KACH,SAAS;KACT,UAAU,KAAA;KACV,kBAAkB,KAAA;KAClB,kBAAkB,KAAA;IACpB,CAAC;GAEH,UAAU;IACR,gBAAgB,EAAK;GACvB;EACF,GAAG,GAAG,MAhFJ,YAAY,IAAI,GAChB,WAAW,IAAI,GACf,gBAAgB,EAAK,GACrB,qBAAqB,IAAI,GACzB,cAAc,UAAU,IACxB,SAAS;GACP,GAAG;GACH,SAAS;GACT,UAAU,KAAA;GACV,kBAAkB,KAAA;EACpB,CAAC;CAuEL,GACA;EAAC;EAAW;EAAU;EAAoB;CAAgB,CAC5D;CAUA,AARA,sBACe;EACX,AAAI,qBAAqB,WACvB,aAAa,qBAAqB,OAAO;CAE7C,GACC,CAAC,CAAC,GAEL,gBAAgB;EAEd,QAAQ,UAAU,mBAAmB,WAAW,QAAQ;CAC1D,GAAG,CAAC,UAAU,gBAAgB,CAAC;CAE/B,IAAM,mBAAmB,MAA2C;EAClE,IAAM,MAAM,EAAE,OAAO;EAcrB,AAbA,YAAY,GAAG,GAEX,UAAU,YAAY,QAAQ,UAAU,aAC1C,cAAc,UAAU,IACxB,SAAS;GACP,GAAG;GACH,SAAS;GACT,UAAU,KAAA;GACV,kBAAkB,KAAA;GAClB,kBAAkB,KAAA;EACpB,CAAC,IAGH,YAAY,GAAG;CACjB,GAEM,wBAAwB,UAA8B;EAC1D,IAAI,CAAC,OAAO,OAAO;EACnB,IAAM,UAAU,MAAM,KAAK;EAC3B,IAAI,CAAC,QAAQ,SAAS,GAAG,GAAG,OAAO;EACnC,IAAM,IAAI,OAAO,QAAQ,MAAM,GAAG,EAAE,CAAC;EAIrC,OAHK,OAAO,SAAS,CAAC,IAElB,MAAM,KAAK,OAAO,GAAG,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC,IAAI,OAAgB,UAC1D,GAAG,EAAE,KAHoB;CAIlC,GAEM,yBAAyB,SAAsC;EAWnE,IAAM,SAA6B;GACjC,GAXW,UAAU,oBACkB;IACvC,gBAAgB;IAChB,iBAAiB;IACjB,kBAAkB;IAClB,mBAAmB;IACnB,OAAO,GAAG,UAAU,QAAQ,GAAG;IAC/B,SAAS,GAAG,KAAK,OAAO,UAAU,WAAW,MAAO,GAAG,EAAE;GAC3D;GAIE,GAAG;EACL;EAEA,SAAS;GACP,GAAG;GACH,SAAS;GACT,kBAAkB;IAChB,GAAG;IACH,mBACE,qBAAqB,OAAO,iBAAiB,KAAK,OAAO;IAC3D,iBAAiB,qBAAqB,OAAO,eAAe,KAAK,OAAO;GAC1E;EACF,CAAC;CACH,GAEM,2BAA2B;EAC/B,IAAM,YAAY,qBAAqB;EACvC,IAAI,CAAC,WAAW,OAAO;GAAC,GAAG;GAAG,GAAG;GAAG,OAAO;GAAG,QAAQ;EAAC;EAEvD,IAAM,OAAO,UAAU,sBAAsB,GACvC,aAAa,KAAK,OAClB,aAAa,KAAK,QAElB,UAAU,iBAAiB,SAC3B,SAAS,SAAS,cAAc,GAChC,SAAS,SAAS,eAAe;EAEvC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,cAAc,CAAC,YACxC,OAAO;GAAC,GAAG;GAAG,GAAG;GAAG,OAAO;GAAY,QAAQ;EAAU;EAG3D,IAAM,QAAQ,KAAK,IAAI,aAAa,QAAQ,aAAa,MAAM,GACzD,WAAW,SAAS,OACpB,WAAW,SAAS;EAI1B,OAAO;GAAC,IAHS,aAAa,YAAY;GAGtB,IAFH,aAAa,YAAY;GAEV,OAAO;GAAU,QAAQ;EAAQ;CACnE;CAEA,OACE,qBAAC,OAAD;EAAO,KAAK;EAAZ,UAAA,CACE,qBAAC,OAAD;GAAO,KAAK;GAAZ,UAAA;IACE,oBAAC,MAAD;KAAM,MAAM;KAAG,QAAO;KAAS,UAAA;IAEzB,CAAA;IACN,oBAAC,MAAD;KAAM,MAAM;KAAG,OAAA;KAAM,UAAA;IAGf,CAAA;IACN,qBAAC,KAAD;KAAK,OAAO;MAAC,UAAU;MAAY,OAAO;KAAM;KAAhD,UAAA,CACE,oBAAC,SAAD;MACE,MAAK;MACL,OAAO;MACP,UAAU;MACV,aAAY;MACZ,OAAO;OACL,SAAS;OACT,cACM,WAAiB,SACjB,YAAY,OACT,SADsB;OAG/B,QACM,YAAY,YAAY,KAAc,sBACtC,YAAY,KAAa,sBACtB;OAET,cAAc;OACd,OAAO;OACP,UAAU;OACV,WAAW;OACX,UAAU;MACZ;KACD,CAAA,IACC,YAAY,gBAAgB,YAAY,SACxC,qBAAC,KAAD;MACE,OAAO;OACL,UAAU;OACV,OAAO;OACP,KAAK;OACL,WAAW;OACX,SAAS;OACT,YAAY;OACZ,KAAK;MACP;MATF,UAAA;OAWG,YACC,oBAAC,QAAD;QACE,MAAK;QACL,MAAK;QACL,MAAK;QACL,eAAe;SAEb,AADA,YAAY,EAAE,GACd,YAAY,EAAE;QAChB;QACA,UAAU;QACV,OAAO;SAAC,UAAU;SAAQ,QAAQ;QAAM;OACzC,CAAA;OAEF,gBACC,oBAAC,MAAD;QAAM,MAAM;QAAG,OAAA;QAAM,UAAA;OAEf,CAAA;OAEP,YAAY,MAAQ,CAAC,gBACpB,oBAAC,qBAAD,EAAqB,OAAO;QAAC,OAAO;QAAW,UAAU;OAAM,EAAI,CAAA;OAEpE,YAAY,MAAS,CAAC,gBACrB,oBAAC,kBAAD,EAAkB,OAAO;QAAC,OAAO;QAAW,UAAU;OAAM,EAAI,CAAA;MAE/D;KAEJ,CAAA,CAAA;;IACJ,YACC,oBAAC,MAAD;KAAM,SAAS;KAAG,MAAK;KAAW,QAAQ;KACxC,UAAA,qBAAC,MAAD;MAAM,OAAM;MAAS,KAAK;MAA1B,UAAA,CACE,oBAAC,kBAAD,EAAkB,OAAO;OAAC,OAAO;OAAW,YAAY;MAAC,EAAI,CAAA,GAC7D,oBAAC,MAAD;OAAM,MAAM;OAAG,OAAO,EAAC,OAAO,UAAS;OACpC,UAAA;MACG,CAAA,CACF;;IACF,CAAA;GAEH;EAEN,CAAA,GAAA,UAAU,YACT,qBAAC,OAAD;GAAO,KAAK;GAAZ,UAAA;IACE,oBAAC,MAAD;KAAM,SAAS;KAAG,MAAK;KAAc,QAAA;KAAO,QAAQ;KAClD,UAAA,qBAAC,MAAD;MACE,OAAM;MACN,SAAQ;MACR,KAAK;MACL,OAAO;OAAC,UAAU;OAAQ,YAAY;MAAY;MAJpD,UAAA,CAME,qBAAC,OAAD;OAAO,KAAK;OAAG,OAAO;QAAC,UAAU;QAAK,MAAM;OAAC;OAA7C,UAAA,CACE,oBAAC,MAAD;QAAM,MAAM;QAAG,QAAO;QAAS,UAAA;OAEzB,CAAA,GACN,qBAAC,MAAD;QAAM,MAAM;QAAG,OAAA;QAAf,UAAA;SAAqB;SAC+C;SAClE,oBAAC,QAAD,EAAA,UAAM,mBAAsB,CAAA;SAAC;SAAe;SAC5C,oBAAC,KAAD;UACE,MAAK;UACL,QAAO;UACP,KAAI;UACL,UAAA;SAEE,CAAA;SAAC;QAEA;OACD,CAAA,CAAA;MACP,CAAA,GAAA,qBAAC,MAAD;OAAM,KAAK;OAAG,OAAO,EAAC,UAAU,OAAM;OAAtC,UAAA,CACE,oBAAC,QAAD;QACE,MAAK;QACL,MAAM,SAAS,WAAW,YAAY;QACtC,eAAe;SAEb,AADA,QAAQ,QAAQ,GAChB,SAAS;UAAC,GAAG;UAAW,SAAS;UAAM,kBAAkB,KAAA;SAAS,CAAC;QACrE;OACD,CAAA,GACD,oBAAC,QAAD;QACE,MAAK;QACL,MAAM,SAAS,WAAW,YAAY;QACtC,eAAe;SACb,QAAQ,QAAQ;SAChB,IAAM,UAAU,6BAA6B;UAAC,GAAG;UAAW,SAAS;SAAI,CAAC;SAC1E,sBAAsB,WAAW,CAAC,CAAC;QACrC;OACD,CAAA,CACG;MACF,CAAA,CAAA;;IACF,CAAA;IAEL,SAAS,YACR,oBAAC,MAAD;KAAM,SAAS;KAAG,MAAK;KAAc,QAAA;KAAO,QAAQ;KAClD,UAAA,qBAAC,OAAD;MAAO,KAAK;MAAZ,UAAA;OACE,oBAAC,MAAD;QAAM,MAAM;QAAG,QAAO;QAAS,UAAA;OAEzB,CAAA;OACN,qBAAC,MAAD;QAAM,qBAAqB,CAAC,GAAG,CAAC;QAAG,KAAK;QAAG,OAAO,EAAC,OAAO,OAAM;QAAhE,UAAA;SACE,qBAAC,OAAD;UAAO,KAAK;UAAG,OAAO,EAAC,UAAU,EAAC;UAAlC,UAAA,CACE,oBAAC,MAAD;WAAM,MAAM;WAAG,OAAA;WAAM,UAAA;UAEf,CAAA,GACN,qBAAC,UAAD;WACE,OAAO,UAAU,kBAAkB,oBAAoB;WACvD,WAAW,MACT,sBAAsB,EACpB,kBAAmB,EAAE,OAAO,SAC1B,QACJ,CAAC;WAEH,OAAO;YACL,OAAO;YACP,SAAS;YACT,QAAQ;YACR,cAAc;WAChB;WAbF,UAAA;YAeE,oBAAC,UAAD;aAAQ,OAAM;aAAO,UAAA;YAAY,CAAA;YACjC,oBAAC,UAAD;aAAQ,OAAM;aAAS,UAAA;YAAc,CAAA;YACrC,oBAAC,UAAD;aAAQ,OAAM;aAAQ,UAAA;YAAa,CAAA;WAC7B;UACH,CAAA,CAAA;;SACP,qBAAC,OAAD;UAAO,KAAK;UAAG,OAAO,EAAC,UAAU,EAAC;UAAlC,UAAA,CACE,oBAAC,MAAD;WAAM,MAAM;WAAG,OAAA;WAAM,UAAA;UAEf,CAAA,GACN,oBAAC,WAAD;WACE,OAAO,UAAU,kBAAkB,qBAAqB;WACxD,WAAW,MACT,sBAAsB,EAAC,mBAAmB,EAAE,cAAc,MAAK,CAAC;UAEnE,CAAA,CACI;;SACP,qBAAC,OAAD;UAAO,KAAK;UAAG,OAAO,EAAC,UAAU,EAAC;UAAlC,UAAA,CACE,oBAAC,MAAD;WAAM,MAAM;WAAG,OAAA;WAAM,UAAA;UAEf,CAAA,GACN,qBAAC,UAAD;WACE,OAAO,UAAU,kBAAkB,kBAAkB;WACrD,WAAW,MACT,sBAAsB,EACpB,gBAAiB,EAAE,OAAO,SACxB,SACJ,CAAC;WAEH,OAAO;YACL,OAAO;YACP,SAAS;YACT,QAAQ;YACR,cAAc;WAChB;WAbF,UAAA;YAeE,oBAAC,UAAD;aAAQ,OAAM;aAAM,UAAA;YAAW,CAAA;YAC/B,oBAAC,UAAD;aAAQ,OAAM;aAAS,UAAA;YAAc,CAAA;YACrC,oBAAC,UAAD;aAAQ,OAAM;aAAS,UAAA;YAAc,CAAA;WAC/B;UACH,CAAA,CAAA;;SACP,qBAAC,OAAD;UAAO,KAAK;UAAG,OAAO,EAAC,UAAU,EAAC;UAAlC,UAAA,CACE,oBAAC,MAAD;WAAM,MAAM;WAAG,OAAA;WAAM,UAAA;UAEf,CAAA,GACN,oBAAC,WAAD;WACE,OAAO,UAAU,kBAAkB,mBAAmB;WACtD,WAAW,MACT,sBAAsB,EAAC,iBAAiB,EAAE,cAAc,MAAK,CAAC;UAEjE,CAAA,CACI;;SACP,qBAAC,OAAD;UAAO,KAAK;UAAG,OAAO,EAAC,UAAU,EAAC;UAAlC,UAAA,CACE,oBAAC,MAAD;WAAM,MAAM;WAAG,OAAA;WAAM,UAAA;UAEf,CAAA,GACN,oBAAC,WAAD;WACE,OAAO,UAAU,kBAAkB,SAAS,GAAG,UAAU,QAAQ,GAAG;WACpE,WAAW,MAAM,sBAAsB,EAAC,OAAO,EAAE,cAAc,MAAK,CAAC;UACtE,CAAA,CACI;;SACP,qBAAC,OAAD;UAAO,KAAK;UAAG,OAAO,EAAC,UAAU,EAAC;UAAlC,UAAA,CACE,oBAAC,MAAD;WAAM,MAAM;WAAG,OAAA;WAAM,UAAA;UAEf,CAAA,GACN,oBAAC,WAAD;WACE,OACE,UAAU,kBAAkB,WAC5B,GAAG,KAAK,OAAO,UAAU,WAAW,MAAO,GAAG,EAAE;WAElD,WAAW,MAAM,sBAAsB,EAAC,SAAS,EAAE,cAAc,MAAK,CAAC;UACxE,CAAA,CACI;;QACH;;OACN,oBAAC,MAAD;QAAM,MAAM;QAAG,OAAA;QAAM,UAAA;OAEf,CAAA;MACD;;IACH,CAAA;IAGP,SAAS,YACR,qBAAAE,UAAA,EAAA,UAAA,CACE,qBAAC,KAAD,EAAA,UAAA,CACE,oBAAC,MAAD;KAAM,MAAM;KAAG,QAAO;KAEZ,iBAAA;MACN,IAAM,UAAU,UAAU,QAAQ,IAC5B,WAAW,mBAAmB,CAAC,CAAC;MAGtC,OAFK,WAEE,SADI,KAAK,IAAI,GAAG,KAAK,MAAO,UAAU,MAAO,QAAQ,CAC5C,EAAG,MAFG,SAAS,QAAQ;KAGzC,EAAA,CAAG;IACC,CAAA,GACN,oBAAC,YAAD;KACE,MAAK;KAEL,cAAc;MACZ,IAAM,UAAU,UAAU,QAAQ,IAC5B,WAAW,mBAAmB,CAAC,CAAC;MAEtC,OADK,WACE,KAAK,IAAI,GAAG,KAAK,MAAO,UAAU,MAAO,QAAQ,CAAC,IADnC;KAExB,EAAA,CAAG;KAEH,YAAY;MACV,IAAM,WAAW,mBAAmB,CAAC,CAAC;MAEtC,OADK,WACE,KAAK,IAAI,GAAG,KAAK,MAAM,WAAW,GAAI,CAAC,IADxB;KAExB,EAAA,CAAG;KAEH,YAAY;MACV,IAAM,WAAW,mBAAmB,CAAC,CAAC;MAEtC,OADK,WACE,KAAK,IAAI,GAAG,KAAK,MAAM,WAAW,EAAG,CAAC,IADvB;KAExB,EAAA,CAAG;KACH,MAAM;KACN,WAAW,MAAM;MACf,IAAM,MAAM,OAAO,EAAE,OAAO,KAAK,GAC3B,WAAW,mBAAmB,CAAC,CAAC,OAChC,UAAU,WAAY,MAAM,WAAY,MAAM,KAC9C,aAAa,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,CAAC;MACpD,SAAS;OACP,GAAG;OACH,MAAM;MACR,CAAC;KACH;IACD,CAAA,CACE,EAAA,CAAA,GAEL,qBAAC,KAAD,EAAA,UAAA,CACE,qBAAC,MAAD;KAAM,MAAM;KAAG,QAAO;KAAtB,UAAA;MAA+B;MACnB,KAAK,OAAO,UAAU,WAAW,MAAO,GAAG;MAAE;KACnD;IACN,CAAA,GAAA,oBAAC,YAAD;KACE,MAAK;KACL,OAAO,UAAU,WAAW;KAC5B,KAAK;KACL,KAAK;KACL,MAAM;KACN,WAAW,MACT,SAAS;MACP,GAAG;MACH,SAAS,OAAO,EAAE,OAAO,KAAK;KAChC,CAAC;IAEJ,CAAA,CACE,EAAA,CAAA,CACL,EAAA,CAAA;IAGJ,oBAAC,MAAD;KAAM,SAAS;KAAG,MAAK;KAAc,QAAA;KAAO,QAAQ;KAClD,UAAA,oBAAC,MAAD;MAAM,MAAM;MAAG,OAAA;MACZ,UAAA,SAAS,WACN,wDACA;KACA,CAAA;IACF,CAAA;GACD;EAEJ,CAAA,CAAA;;AAEX;AC52BA,MAAM,qBAAqB,cAAc,YAAY,CAAC,CAAC,KAAK,UAAU;CACpE,OAAO;CACP,OAAO,cAAc,cAAc,IAAI;AACzC,EAAE,GAEI,qBAGF;CACF,eAAe,wBAAwB,KAAK,UAAU;EACpD,OAAO,KAAK;EACZ,OAAO,KAAK;CACd,EAAE;CACF,WAAW;CACX,UAAU;AACZ;AASA,SAAwB,iBAAA,IAYrB;gBAZsC,EACvC,QACA,UACA,gBAHuCC,IAajC,QAAQ,OAAO,IAEyCC;qDAAC,KAAA,CAAA;CAK9CC,IAAAA;qDAAC,KAAA,EAAA,SAAS,QAAO;CACf,IAAA,KAAA,CAAC,CAAC,OAAO,eACRC;CAUI,AAAA,EAAA,OAAA,eAAA,EAAA,OARV,YAAA,EAAA,OADE,SADI,WAAM;EACd,AACE,SADE,QACO;GAAC,QAAQ;GAAS,IAAI,MAAM;GAAK,WAAW;EAAQ,IAEpD;GACP,QAAQ;GACR,IAAI,KAAK;GACT,WAAW;GACX,OAAO;IACL,MAAM;IACN,MAAM,eAAe,KAAA;IACrB,eAAe,eAAe,KAAA;GAChC;EACF,CAAC;CAEL,GALc,EAAA,KAAA,aARV,EAAA,KAAA,UADE,EAAA,KAAA;CALRC,IAAAA;CAGWC,AAAAA,EAAAA,OAAAA,MAAAA,EAAAA,OACCF,MAJZ,KAAA,oBAAC,UAAD;EACE,IAAG;EACH,OAAOD;EACP,SAASG;EACT,UAAUF;CAgBX,CAAA,GAjBUE,EAAAA,KAAAA,IACCF,EAAAA,KAAAA;CAiBZG,IAAAA;qDAAC,KAAA,oBAAA,KAAD;EAAK,MAAM;EAAG,aAAa;EACzB,UAAA,oBAAC,MAAD,EAAA,UACE,oBAAC,SAAD;GAAO,SAAQ;GAAW,UAAA;EAAwB,CAAA,EAC9C,CAAA;CACH,CAAA;CA1BPC,IAAAA;CACEH,AAAAA,EAAAA,QAAAA,mBADF,KAAA,qBAAC,MAAD;EAAM,OAAM;EAAZ,UAAA,CACEA,IAqBAE,EAKI;KA1BJF,EAAAA,MAAAA;CA2BDI,IAAAA;CAKK,AAAA,EAAA,QAAA,YAAA,EAAA,QALL,SACC,KAAA,SAAA,oBAAC,cAAD;EACE,IAAI;EACJ,OAAO,MAAM;EACb,WAAW,aACT,SAAS;GACP,QAAQ;GACR,IAAI,MAAM;GACV,WAAW;GACX,OAAO;IACL,eAAe;IACf,MAAM,cAAc,cAAc,QAAQ;GAC5C;EACF,CAAC;EAEH,SAAS,mBAAmB,MAAM;EAClC,MAAM;EACN,aAAY;EACZ,cAAcC;EAId,YAAA;EACA,cAAc,UACZ,mBAAmB,MAAM,KAAM,CAAC,MAAM,MAAM,EAAE,UAAU,KAAK,CAAC,EAAE,SAAS;EAE3E,cAAcC;CAOf,CAAA,GA5BG,EAAA,MAAA,UALL,EAAA,MAAA;CA9BLC,IAAAA;CADF,OAGMJ,EAAAA,QAAAA,MAAAA,EAAAA,QA4BCC,MA9BL,KAAA,oBAAC,WAAD;EAAW,OAAM;EAAqC,MAAMP;EAC1D,UAAA,qBAAC,OAAD;GAAO,KAAK;GAAZ,UAAA,CACEM,IA4BCC,EAmCI;;CACE,CAAA,GAhEPD,EAAAA,MAAAA,IA4BCC,EAAAA,MAAAA,8BA9BLG;AAoEJ;AAZ0B,SAAAI,SAAC,UAAA;CACb,OAAA,oBAAC,MAAD;EAAM,WAAQ;EAAS,SAAS;EAAG,QAAQ;EAAG,MAAK;EACjD,UAAA,qBAAC,MAAD;GAAM,MAAM;GAAG,cAAa;GAA5B,UAAA;IACGH,SAAO;IAAM;IAAGA,SAAO;IAAM;GAC1B;;CACF,CAAA;;AAbM,SAAAE,QAAC,OAAO,QAAA;CACpB,OAAA,OAAO,MAAM,YAAY,CAAC,CAAC,QAAQ,MAAM,YAAY,CAAC,IAAI,MAC1D,OAAO,MAAM,YAAY,CAAC,CAAC,QAAQ,MAAM,YAAY,CAAC,IAAI;;AC9FxE,SAAwB,qBAAA,IAgBrB;gBAhB0C,EAC3C,IACA,SACA,YACA,aACA,UACA,QACA,aAP2CE,IAiBrC,CAAC,OAAO,YAAY,SAAS,CAAC,GAIvB,KAAA,SAAS,MAAM,IAElB,KAAA,WAAW,gBAAgB,WAJLC;CAEnBC,AAAAA,EAAAA,OAAAA,MAAAA,EAAAA,OAEHC,MAJsB,KAAA;EAC9B,SAAS;EACT,WAAWD;EACX,YAAY;EACZ,QAAQC;EACR,cAAc;CAChB,GAJaD,EAAAA,KAAAA,IAEHC,EAAAA,KAAAA;CAJV,IAAM,WAA0BF,IAQPG;qDAAM,WAAA;EAE7B,AADA,SAAS,GAAI,GACb,iBAAiB;GACf,SAAS,CAAC;EACZ,GAAG,GAAG;CACR;CALA,IAAM,mBAAmBA,IAOFC;CAChB,AAAA,EAAA,OAAA,UAAA,EAAA,OAIK,WAAA,EAAA,OAFV,YAHqB,WAAM;EAC3B,AAAK,WACL,iBAAiB,GACjB,SAAS;GACP;GACA,OAAO,CAAC;EACV,CAAC;CACH,GANO,EAAA,KAAA,QAIK,EAAA,KAAA,SAFV,EAAA,KAAA;CAHF,IAAM,iBAAiBA,IAUrBC;CAAO,AAAA,EAAA,OAAA,2BAAP,KAAA,OAAO,eAAgB,WACrB,oBAAC,MAAD;EAAM,MAAM;EAAG,OAAA;EACZ,UAAA;CACG,CAAA,IAEN,aALK,EAAA,KAAA;CADT,IAAM,iBACJA,IAUIC;CAGW,AAAA,EAAA,QAAA,WAAA,EAAA,QAEC,YAAA,EAAA,QADA,kBAAA,EAAA,QAHN,MADN,KAAA,oBAAC,UAAD;EACM;EACJ,UAAA;EACS;EACT,UAAU;EACA;CACX,CAAA,GAHU,EAAA,MAAA,SAEC,EAAA,MAAA,UADA,EAAA,MAAA,gBAHN,EAAA,MAAA;CAOJC,IAAAA;CACG,AAAA,EAAA,QAAA,2BADH,KAAA,oBAAC,MAAD;EAAM,MAAM;EAAG,QAAO;EACnB,UAAA;CACG,CAAA,GADH,EAAA,MAAA;CAFLC,IAAAA;CAIG,AAAA,EAAA,QAAA,kBAAA,EAAA,QAHDD,MADF,KAAA,qBAAC,MAAD;EAAM,KAAK;EAAX,UAAA,CACEA,IAGC,cACG;KADH,EAAA,MAAA,gBAHDA,EAAAA,MAAAA;CAVNE,IAAAA;CADF,OAEqC,EAAA,QAAA,YAAA,EAAA,QAC/BH,MAAAA,EAAAA,QAOAE,MATJ,MAAA,oBAAC,SAAD,EAAA,UACE,qBAAC,MAAD;EAAM,KAAK;EAAG,SAAS;EAAG,OAAO;EAAjC,UAAA,CACEF,IAOAE,EAMI;CACD,CAAA,EAAA,CAAA,GAf4B,EAAA,MAAA,UAC/BF,EAAAA,MAAAA,IAOAE,EAAAA,MAAAA,gCATJC;AAkBJ;ACvEA,SAAwB,wBAAwB;eACbE;;EAC/B,OAAO;EACP,YAAY;CACd;CAHA,IAAM,YAA2BA,IAKDC;;EAC9B,SAAS;EACT,iBAAiB;EACjB,cAAc;EACd,OAAO;EACP,OAAO;CACT;CANA,IAAM,WAA0BA,IAS9BC;CADF,2DACG,KAAA,oBAAA,KAAD;EAAK,SAAS;EAAG,OAAO;EACtB,UAAA,qBAAC,MAAD;GAAM,OAAM;GAAS,KAAK;GAA1B,UAAA,CACE,oBAAC,mBAAD,CAAoB,CAAA,GACpB,oBAAC,MAAD;IAAM,MAAM;IAAG,OAAO;IACpB,UAAA;GACI,CAAA,CACF;;CACH,CAAA,2BAPLA;AASJ;ACnBA,SAAwB,eAAA,IAUrB;gBAVoC,EACrC,IACA,QACA,SACA,aAJqCE,IAW/B,mBAAmB,EAAE,OAAO,iBAAiB,OAAO,iBAAiB,OAAO,aAC5E,oBAAoB,CAAC,QAAQ,aAG/BC;qDAAC,KAAA,oBAAA,MAAD;EAAM,QAAO;EAAO,UAAA;CAAgC,CAAA;CAE9C,IAAA,KAAA,GAAG,GAAG,WAIRC;qDACE,KAAA,qBAAAY,UAAA,EAAA,UAAA,CAAA,oBAAC,MAAD;EAAM,MAAM;EAAG,OAAA;EACb,UAAA;CACI,CAAA,GACN,oBAAC,MAAD,EAAA,UAAO,uCAA6C,CAAA,CACpD,EAAA,CAAA;CAVNX,IAAAA;CAEkBC,AAAAA,EAAAA,OAAAA,OAAAA,iBAAAA,EAAAA,OAUN,YAAA,EAAA,OAXNC,MADN,KAAA,oBAAC,sBAAD;EACE,IAAIA;EACJ,SAAS,OAAO;EAChB,YAAW;EACX,aACEH;EAOQ;EACV,QAAO;CACR,CAAA,GAZiBE,EAAAA,KAAAA,OAAAA,eAUN,EAAA,KAAA,UAXNC,EAAAA,KAAAA;CAcLC,IAAAA;CAGmBC,AAAAA,EAAAA,OAAAA,OAAAA,iBAAAA,EAAAA,OAsBN,YAAA,EAAA,OAvBH,MAAA,EAAA,OAFFC,QAAAA,oBAAR,KAAA,QAAQ,oBACP,oBAAC,sBAAD;EACE,IAAI,GAAG,GAAG;EACV,SAAS,OAAO;EAChB,YAAW;EACX,aACE,qBAAAM,UAAA,EAAA,UAAA;GACE,oBAAC,MAAD;IAAM,MAAM;IAAG,OAAA;IACb,UAAA;GACI,CAAA;GACN,oBAAC,MAAD,EAAA,UAAO,qDAA2D,CAAA;GAClE,qBAAC,MAAD;IAAM,MAAM;IAAG,OAAA;IAAf,UAAA;KACE;KAAI;KACJ,oBAAC,KAAD;MACE,MAAK;MACL,QAAO;MACP,KAAI;MAEJ,UAAA;KACC,CAAA;KAAE;KACL;IACI;;EACN,EAAA,CAAA;EAGM;EACV,QAAO;CACR,CAAA,GAxBiBP,EAAAA,KAAAA,OAAAA,eAsBN,EAAA,KAAA,UAvBH,EAAA,KAAA,IAFFC,EAAAA,KAAAA,QAAAA;CA6BRC,IAAAA;CA2BmBC,AAAAA,EAAAA,QAAAA,OAAAA,cAAAA,EAAAA,QANN,YAAA,EAAA,QArBb,qBAAA,EAAA,QAEU,MAFV,KAAA,oBACC,oBAAC,sBAAD;EACE,IAAI,GAAG,GAAG;EACV,SAAS;EACT,YAAW;EACX,aACE,oBAAAI,UAAA,EAAA,UACE,qBAAC,MAAD;GAAM,MAAM;GAAG,OAAA;GAAf,UAAA;IACE;IACkB;IAClB,oBAAC,KAAD;KACE,MAAK;KACL,QAAO;KACP,KAAI;KAEJ,UAAA;IACC,CAAA;IAAE;IACL;GACI;EACN,CAAA,EAAA,CAAA;EAEM;EACV,UAAA;CACD,CAAA,IAED,oBAAC,sBAAD;EACE,IAAI,GAAG,GAAG;EACV,SAAS,OAAO;EAChB,YAAW;EACX,aACE,qBAAAA,UAAA,EAAA,UAAA;GACE,oBAAC,MAAD;IAAM,MAAM;IAAG,OAAA;IACb,UAAA;GAEI,CAAA;GACN,oBAAC,MAAD,EAAA,UAAO,qDAA2D,CAAA;GAClE,qBAAC,MAAD;IAAM,MAAM;IAAG,OAAA;IAAf,UAAA;KACE;KAAI;KACJ,oBAAC,KAAD;MACE,MAAK;MACL,QAAO;MACP,KAAI;MAEJ,UAAA;KACC,CAAA;KAAE;KACL;KAA+D;KAC/D,oBAAC,KAAD;MACE,MAAK;MACL,QAAO;MACP,KAAI;MAEJ,UAAA;KACC,CAAA;KAAE;KACL;IACI;;EACN,EAAA,CAAA;EAEM;EACV,QAAO;CACR,CAAA,GAhCiBJ,EAAAA,MAAAA,OAAAA,YANN,EAAA,MAAA,UArBb,EAAA,MAAA,mBAEU,EAAA,MAAA;CA2DVC,IAAAA;4CAAoB,KAAA,oBAAA,oBAAC,uBAAD,CAAwB,CAAA,GAA5C,EAAA,MAAA;CA3GHC,IAAAA;CADF,OAGIT,EAAAA,QAAAA,MAAAA,EAAAA,QAeCG,MAAAA,EAAAA,QA6BAG,MAAAA,EAAAA,QA6DAE,MA3GH,KAAA,qBAAC,MAAD;EAAM,KAAK;EAAX,UAAA;GACEV;GACAE;GAeCG;GA6BAG;GA6DAE;EACG;KA1GJR,EAAAA,MAAAA,IAeCG,EAAAA,MAAAA,IA6BAG,EAAAA,MAAAA,IA6DAE,EAAAA,MAAAA,8BA3GHC;AA8GJ;AC9HA,MAAa,mBAAmB;CAC9B;EAAC,OAAO;EAAS,OAAO;CAAO;CAC/B;EAAC,OAAO;EAAS,OAAO;CAAY;CACpC;EAAC,OAAO;EAAS,OAAO;CAAY;AACtC,GAEa,0BAAA,OAUP;eAViC,EACrC,IACA,QACA,UACA,2BAJqCG,IAa3BC;qDAAC,KAAA,CAAA;CAGLC,IAAAA;;EACE;EAAY;EACZ,oBAAC,KAAD;GACE,MAAK;GACL,QAAO;GACP,KAAI;GAEJ,UAAA;EACC,CAAA;EAAE;EACL;CACA,EAAA,CAAA;CAIDC,IAAAA;CAQgBC,AAAAA,EAAAA,OAAAA,UAAAA,EAAAA,OAGP,YAAA,EAAA,OAVW,MAAA,EAAA,OAEP,0BAHb,KAAA,iBAAiB,KAAA,IAAqB,UAAU;EAA1B,IAAA,EAAC,OAAO,UAARC,IACf,UAAU,GAAG,GAAG,SAAS;EAI/B,OAFI,QAAQ,yBAA+B,OAGzC,qBAAC,MAAD;GAAkB,OAAM;GAAS,KAAK;GAAtC,UAAA,CACE,oBAAC,OAAD;IACE,SAAS,OAAO,wBAAwB;IACxC,MAAK;IACL,WAAW,MACT,SAAS;KACP,QAAQ;KACR,OAAO,EAAE,cAAc;IACzB,CAAC;IAEI;IACP,IAAI;GACL,CAAA,GACD,oBAAC,MAAD;IAAM,IAAG;IAAQ,SAAS;IACvB,UAAA;GACG,CAAA,CACF;EAhBK,GAAA,KAgBL;CAEV,CAAC,GAhBgBD,EAAAA,KAAAA,QAGP,EAAA,KAAA,UAVW,EAAA,KAAA,IAEP,EAAA,KAAA;CArBlBE,IAAAA;CADF,OAmBOH,EAAAA,OAAAA,kBAlBL,KAAA,oBAAC,WAAD;EACE,MAAMF;EACN,OAAM;EACN,aACEC;EAaF,UAAA,oBAAC,MAAD;GAAM,KAAK;GAAG,MAAM;GACjBC,UAAAA;EAyBG,CAAA;CACG,CAAA,GA1BNA,EAAAA,KAAAA,gBAlBLG;AA8CJ,GChEM,uBAA4E;CAChF;EAAC,OAAO;EAAQ,OAAO;CAAM;CAC7B;EAAC,OAAO;EAAQ,OAAO;CAAM;CAC7B;EAAC,OAAO;EAAQ,OAAO;CAAM;CAC7B;EAAC,OAAO;EAAQ,OAAO;CAAM;CAC7B;EAAC,OAAO;EAAQ,OAAO;CAAM;CAC7B;EAAC,OAAO;EAAS,OAAO;CAAO;CAC/B;EAAC,OAAO;EAAS,OAAO;CAAO;CAC/B;EAAC,OAAO;EAAS,OAAO;CAAO;AACjC,GAEa,2BAAA,OAQP;gBARkC,EACtC,IACA,QACA,aAHsCG,IAUhC,iBACwB,OAAO,kBAAkB,OACnDC,KAEK,CAAA,CAAoB,SAAS,GAGhC,CAAC,eAAe,oBAAoB,SACxC,iBAAiB,aAAa,UAChC,GAGwBC;CACCC,AAAAA,EAAAA,OAAAA,OAAAA,qBAAAA,EAAAA,OAIrB,YALoB,MAAC,cAAyC;EAChE,IAAM,UAAU,OAAO;EAGvB,AAFqB,QAAQ,SAAS,SAElC,IACF,SAAS;GACP,QAAQ;GACR,OAAO,QAAQ,QAAQ,QAAMC,QAAM,SAAS;EAC9C,CAAC,IAED,SAAS;GACP,QAAQ;GACR,OAAO,CAAC,GAAG,SAAS,SAAS;EAC/B,CAAC;CAEL,GAdyBD,EAAAA,KAAAA,OAAAA,mBAIrB,EAAA,KAAA;CALJ,IAAM,kBAAkBD,IAkBCG;CAMLF,AAAAA,EAAAA,OAAAA,OAAAA,qBAAAA,EAAAA,OAFhB,YAJqB,MAAC,SAAkC;EAE1D,AADA,iBAAiB,IAAI,GAGnB,SAFE,SAAS,aAEF;GACP,QAAQ;GACR,OAAO,OAAO,kBAAkB,OAAOG,MAA4C;EACrF,IAGS;GACP,QAAQ;GACR,OAAO,OAAO,kBAAkB,OAAOC,MAAsB;EAC/D,CAAC;CAEL,GAToBJ,EAAAA,KAAAA,OAAAA,mBAFhB,EAAA,KAAA;CAJJ,IAAM,mBAAmBE,IAmBbG;qDAAC,KAAA,CAAA;CASU,IAAA,KAAA,kBAAkB,YAEjBC;CAAM,AAAA,EAAA,OAAA,gCAAN,WAAM,iBAAiB,UAAU,GAA3B,EAAA,KAAA;CAEZ,IAAA,KAAA,GAAG,GAAG,kBALZC;CACWC,AAAAA,EAAAA,OAAAA,MAAAA,EAAAA,QAECF,MAAAA,EAAAA,QAENG,MALN,KAAA,oBAAC,OAAD;EACE,SAASD;EACT,MAAK;EACL,UAAUF;EACV,OAAM;EACN,IAAIG;CACL,CAAA,GALUD,EAAAA,KAAAA,IAECF,EAAAA,MAAAA,IAENG,EAAAA,MAAAA;CAEoB,IAAA,KAAA,GAAG,GAAG,kBAAhCC;CAA0BD,AAAAA,EAAAA,QAAAA,mBAA1B,KAAA,oBAAC,MAAD;EAAM,IAAG;EAAQ,SAASA;EACxB,UAAA;CACI,CAAA,GAFoBA,EAAAA,MAAAA;CAR5BE,IAAAA;CACEJ,AAAAA,EAAAA,QAAAA,MAAAA,EAAAA,QAOAG,MARF,MAAA,qBAAC,MAAD;EAAM,OAAM;EAAS,KAAK;EAA1B,UAAA,CACEH,IAOAG,EAGI;KAVJH,EAAAA,MAAAA,IAOAG,EAAAA,MAAAA;CAMW,IAAA,MAAA,kBAAkB,YAEjBE;CAAM,AAAA,EAAA,QAAA,kCAAN,YAAM,iBAAiB,UAAU,GAA3B,EAAA,MAAA;CAEZ,IAAA,MAAA,GAAG,GAAG,kBALZC;CACWC,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAECF,OAAAA,EAAAA,QAENG,OALN,MAAA,oBAAC,OAAD;EACE,SAASD;EACT,MAAK;EACL,UAAUF;EACV,OAAM;EACN,IAAIG;CACL,CAAA,GALUD,EAAAA,MAAAA,KAECF,EAAAA,MAAAA,KAENG,EAAAA,MAAAA;CAEoB,IAAA,MAAA,GAAG,GAAG,kBAAhCC;CAA0BD,AAAAA,EAAAA,QAAAA,qBAA1B,MAAA,oBAAC,MAAD;EAAM,IAAG;EAAQ,SAASA;EACxB,UAAA;CACI,CAAA,GAFoBA,EAAAA,MAAAA;CAR5BE,IAAAA;CACEJ,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAOAG,OARF,MAAA,qBAAC,MAAD;EAAM,OAAM;EAAS,KAAK;EAA1B,UAAA,CACEH,KAOAG,GAGI;KAVJH,EAAAA,MAAAA,KAOAG,EAAAA,MAAAA;CArBJE,IAAAA;CACEP,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAYAM,OAbF,MAAA,qBAAC,MAAD;EAAM,KAAK;EAAX,UAAA,CACEN,KAYAM,GAYI;KAxBJN,EAAAA,MAAAA,KAYAM,EAAAA,MAAAA;CAeDE,IAAAA;CAMuBnB,AAAAA,EAAAA,QAAAA,OAAAA,qBAAAA,EAAAA,QAFT,MAAA,EAAA,QAJd,iBAAA,EAAA,QAOuB,mBAPvB,MAAA,kBAAkB,cACjB,qBAAC,OAAD;EAAO,KAAK;EAAZ,UAAA,CACE,qBAAC,MAAD;GAAM,OAAM;GAAS,KAAK;GAAG,SAAS,CAAC,GAAG,CAAC;GAA3C,UAAA,CACE,oBAAC,UAAD;IACE,IAAI,GAAG,GAAG;IACV,OAAO,EAAC,SAAS,QAAO;IACxB,SAAS,OAAO,kBAAkB,SAAS,SAAS;IACpD,gBAAgB,gBAAgB,SAAS;GAC1C,CAAA,GACD,oBAAC,MAAD;IAAM,IAAG;IAAQ,SAAS,GAAG,GAAG;IAC9B,UAAA;GACI,CAAA,CACF;EACN,CAAA,GAAA,qBAAC,MAAD;GAAM,OAAM;GAAS,KAAK;GAAG,SAAS,CAAC,GAAG,CAAC;GAA3C,UAAA,CACE,oBAAC,UAAD;IACE,IAAI,GAAG,GAAG;IACV,OAAO,EAAC,SAAS,QAAO;IACxB,SAAS,OAAO,kBAAkB,SAAS,YAAY;IACvD,gBAAgB,gBAAgB,YAAY;GAC7C,CAAA,GACD,oBAAC,MAAD;IAAM,IAAG;IAAQ,SAAS,GAAG,GAAG;IAC9B,UAAA;GACI,CAAA,CACF;EACD,CAAA,CAAA;KAlBeA,EAAAA,MAAAA,OAAAA,mBAFT,EAAA,MAAA,IAJd,EAAA,MAAA,eAOuB,EAAA,MAAA;CAqBvBoB,IAAAA;CAa6BpB,AAAAA,EAAAA,QAAAA,OAAAA,qBAAAA,EAAAA,QANH,MAAA,EAAA,QAP1B,iBAAA,EAAA,QAc6B,mBAd7B,MAAA,kBAAkB,cACjB,qBAAC,OAAD;EAAO,KAAK;EAAZ,UAAA;GACE,oBAAC,OAAD;IAAO,MAAM;IAAG,OAAA;IACd,UAAA;GACK,CAAA;GACP,oBAAC,MAAD;IAAM,KAAK;IAAG,MAAK;IAChB,UAAA,qBAAqB,KAAA,QAAwB;KAAnB,IAAA,EAAC,OAAO,UAARqB,KACnB,UAAU,GAAG,GAAG,eAAe;KACrC,OACE,qBAAC,MAAD;MAAkB,OAAM;MAAS,KAAK;MAAtC,UAAA,CACE,oBAAC,UAAD;OACE,IAAI;OACJ,OAAO,EAAC,SAAS,QAAO;OACxB,SAAS,OAAO,kBAAkB,SAAS,KAAK;OAChD,gBAAgB,gBAAgB,KAAK;MACtC,CAAA,GACD,oBAAC,MAAD;OAAM,IAAG;OAAQ,SAAS;OAAS,MAAM;OACtC,UAAA;MACG,CAAA,CACF;KAVK,GAAA,KAUL;IAEV,CAAC;GACG,CAAA;GACN,qBAAC,MAAD;IAAM,OAAM;IAAS,KAAK;IAAG,SAAS;KAAC;KAAG;KAAG;KAAG;IAAC;IAAjD,UAAA,CACE,oBAAC,UAAD;KACE,IAAI,GAAG,GAAG;KACV,OAAO,EAAC,SAAS,QAAO;KACxB,SAAS,OAAO,kBAAkB,SAAS,YAAY;KACvD,gBAAgB,gBAAgB,YAAY;IAC7C,CAAA,GACD,oBAAC,MAAD;KAAM,IAAG;KAAQ,SAAS,GAAG,GAAG;KAC9B,UAAA;IACI,CAAA,CACF;;EACD;KArBqBrB,EAAAA,MAAAA,OAAAA,mBANH,EAAA,MAAA,IAP1B,EAAA,MAAA,eAc6B,EAAA,MAAA;CA9EpCsB,IAAAA;CADF,OASQJ,EAAAA,QAAAA,OAAAA,EAAAA,QA4BCC,OAAAA,EAAAA,QA4BAC,OAhEP,MAAA,oBAAC,OAAD;EAAO,KAAK;EACV,UAAA,oBAAC,WAAD;GACE,MAAMf;GACN,OAAM;GACN,aAAY;GAEZ,UAAA,qBAAC,OAAD;IAAO,KAAK;IAAZ,UAAA;KAEEa;KA4BCC;KA4BAC;IAoCI;;EACE,CAAA;CACN,CAAA,GA9FDF,EAAAA,MAAAA,KA4BCC,EAAAA,MAAAA,KA4BAC,EAAAA,MAAAA,iCAhEPE;AAwGJ;AArJM,SAAA,MAAC,GAAA;CAAM,OAAA,MAAM,aAAa,MAAM;;AAkCS,SAAA,OAAC,KAAA;CAAMrB,OAAAA,QAAM,aAAaA,QAAM;;AAMhC,SAAA,OAAC,KAAA;CAAMA,OAAAA,QAAM;;ACrB5D,MAAM,uBAAuB;CAC3B;EAAC,OAAO;EAAS,OAAO;CAAO;CAC/B;EAAC,OAAO;EAAQ,OAAO;CAAM;CAC7B;EAAC,OAAO;EAAW,OAAO;CAAS;AACrC;;;;;AAMA,SAAS,yBACP,YAC6B;CAC7B,IAAM,aAAa,WAAW,SAAS,SAAS,GAC1C,yBAAyB,WAAW,MAAM,MAAM,MAAM,aAAa,MAAM,YAAY;CAM3F,OAJI,cAAc,yBACT,WAAW,QAAQ,MAAM,MAAM,aAAa,MAAM,YAAY,IAGhE;AACT;;;;;;;AAQA,SAAwB,oBAAoB,EAC1C,cACA,SACA,cACA,aACA,WAOC;CACD,IAAM,KAAK,MAAM,GACX,CAAC,0BAA0B,+BAA+B,SAAwB,IAAI,GACtF,+BAA+B,OAAuB,IAAI,GAC1D,2BAA2B,OAAyB,IAAI,GACxD,iBAAiB,OACrB,aAAa,kBAAkB,UAAU,aAAa,mCAClD,CACE;EACE,KAAK,KAAK;EACV,MAAM;EACN,eAAe,aAAa;EAC5B,MAAM,cAAc,cAAc,aAAa,gCAAgC;CACjF,CACF,IACA,CAAC,CACP,CAAC,CAAC,SAEI,CAAC,QAAQ,YAAY,YACxB,MAAoB,WAA2C;EAC9D,QAAQ,OAAO,QAAf;GACE,KAAK,iBAcH,OAZI,OAAO,UAAU,UACZ,OAAO,OAAO,CAAC,GAAG,MAAM;IAC7B,eAAe,OAAO;IACtB,mBAAmB,CAAC;IACpB,qBAAqB;IACrB,aAAa,KAAK,aAAa,QAAQ,EAAC,WAAU,SAAS,eAAe;IAC1E,eAAe;IACf,eAAe;IACf,YAAY;GACd,CAAC,IAGI,OAAO,OAAO,CAAC,GAAG,MAAM;IAC7B,eAAe,OAAO;IACtB,mBAAmB,yBAAyB,aAAa,qBAAqB,CAAC,CAAC;IAChF,qBAAqB,aAAa;IAClC,aAAa,CAAC,GAAG,gBAAgB,GAAI,KAAK,eAAe,CAAC,CAAE;GAC9D,CAAC;GAEH,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK,iBACH,OAAO,OAAO,OAAO,CAAC,GAAG,MAAM,GAAE,OAAO,SAAS,OAAO,MAAK,CAAC;GAChE,KAAK,iBACH,OAAO,OAAO,OAAO,CAAC,GAAG,MAAM,GAAE,OAAO,SAAS,OAAO,MAAK,CAAC;GAChE,KAAK,cACH,OAAO,OAAO,OAAO,CAAC,GAAG,MAAM,GAAE,OAAO,SAAS,OAAO,MAAK,CAAC;GAChE,KAAK,aACH,OAAO,OAAO,OAAO,CAAC,GAAG,MAAM,EAAC,WAAW,OAAO,MAAK,CAAC;GAE1D,KAAK,SAAS;IACZ,IAAM,cAAc,CAAC,GAAG,KAAK,WAAW,GAClC,iBAAiB,YAAY,WAAW,EAAC,UAAS,QAAQ,OAAO,EAAE;IACzE,QAAQ,OAAO,WAAf;KACE,KAAK;MAEH,IAAI,mBAAmB,IAAI;MAC3B,YAAY,KAAK;OACf,KAAK,OAAO;OACZ,GAAG,OAAO;MACZ,CAA2B;MAC3B;KACF,KAAK;MACH,IAAI,mBAAmB,IAAI;MAC3B,YAAY,kBAAkB;OAC5B,GAAG,YAAY;OACf,GAAG,OAAO;MACZ;MACA;KACF,KAAK;MACH,IAAI,mBAAmB,IAAI;MAC3B,YAAY,OAAO,gBAAgB,CAAC;IAExC;IACA,OAAO,OAAO,OAAO,CAAC,GAAG,MAAM,EAAC,YAAW,CAAC;GAC9C;GACA,SACE,OAAO;EACX;CACF,GACA;EACE,eAAe,aAAa;EAC5B,qBAAqB,aAAa;EAClC,mBAAmB,yBAAyB,aAAa,qBAAqB,CAAC,CAAC;EAChF,eAAe,QAAQ,oBAAoB,aAAa;EACxD,eAAe,aAAa;EAC5B,YAAY,aAAa,cAAc,CAAC,CAAC,QAAQ;EACjD,iBAAiB,aAAa;EAC9B,aAAa;CACf,CACF,GAGM,CAAC,iBAAiB,sBAAsB,SAAwB,IAAI,GACpE,gBAAgB,aAAa,kBAC7B,uBAAuB,aAAa,kBAEpC,EAAC,UAAU,mBAAmB,8BAA6B,iBAC/D,cACA,aACF,GACM,EAAC,oBAAoB,uBAAuB,sBAChD,iBAAiB,YAAY;CAQ/B,AANA,gBAAgB;EACd,AAAI,YACF,uBAAuB,SAAS;GAAC,GAAG;GAAK,MAAM;EAAQ,EAAE;CAE7D,GAAG,CAAC,UAAU,qBAAqB,CAAC,GAEpC,gBAAgB;EACd,IAAM,oBAAoB,aACpB,wBAAwB,WAAW,wBACrC,mBACE,mBAAmB,cAAc,QAAQ,EAAE,wCAAwC,cAAc,oBAAoB,GACvH,GACO,MAEF,IAGH,oBAAoB,SACpB,kBAAkB,KAAA,KAAa,QAAQ,kBAI3C,mBACE,cAAc,YAAY,IAAI,EAAE,oCAAoC,YAAY,aAAa,GAC/F,GACO,KAGH,2BAA2B,gBAC3B,OAAO,cAAc,eACvB,mBAAmB,0CAA0C,GACtD,MAEF,IAGL,QAAQ;EAUZ,AATI,oBAAoB,SACtB,UAAkB,6BAA6B,iBAAiB,mBAAmB,IAAI,IAErF,oBAAoB,aACtB,UAAiB,iBAAiB,mBAAmB,QAAQ,IAE3D,oBAAoB,eAAe,SACrC,UAAiB,wBAAwB,mBAAmB,WAAW,IAErE,SACF,mBAAmB,IAAI;CAE3B,GAAG;EACD;EACA;EACA;EACA,oBAAoB;EACpB,oBAAoB;EACpB,oBAAoB;EACpB,oBAAoB;EACpB;EACA,OAAO;EACP;CACF,CAAC;CAKD,IAAM,EAAC,wBAAwB,wBAAuB,cAChD,aAAa,0BAA0B;CAW7C,IAVA,gBAAgB;EACd,IAAI,YAAY;GACd,IAAM,EAAC,UAAU,cAAa,mBAAmB,QAAQ,SAAS,EAChE,kBAAkB,oBAAoB,YACxC,CAAC;GACD,YAAY,UAAU,SAAS;EACjC;CAGF,GAAG,CAAC,CAAC,GACD,YAAY,OAAO;CAEvB,IAAM,cAAc,OAAO,kBAAkB,UAAU,OAAO,kBAAkB,WAC1E,yBAAyB,OAAO,iBAAiB,OAAO,iBAAiB,OAAO,YAChF,yBAAyB,iBAAiB,WAC7C,OAAO,GAAG,UAAU,aAAa,mBACpC;CACA,OACE,oBAAC,QAAD;EACE,SAAA;EACA,MAAA;EACA,IAAG;EACH,SAAS;EACT,OAAO;EACP,QAAO;EACE;EAET,UAAA,qBAAC,OAAD;GAAO,SAAS;GAAG,KAAK;GAAxB,UAAA;KACI,mBAAmB,6BACnB,oBAAC,MAAD;KAAM,SAAS;KAAG,MAAK;KAAW,QAAQ;KAAG,cAAc;KACzD,UAAA,qBAAC,MAAD;MAAM,KAAK;MAAG,OAAM;MAApB,UAAA,CACE,oBAAC,kBAAD;OAAkB,OAAO;OAAI,QAAQ;MAAK,CAAA,GAC1C,qBAAC,OAAD;OAAO,KAAK;OAAZ,UAAA,CACE,oBAAC,MAAD;QAAM,MAAM;QAAG,QAAO;QAAW,UAAA;OAE3B,CAAA,GACN,oBAAC,MAAD;QAAM,MAAM;QAAI,UAAA,mBAAmB;OAA+B,CAAA,CAC7D;MACH,CAAA,CAAA;;IACF,CAAA;IAER,oBAAC,OAAD;KAAO,MAAM;KAAG,UAAA;IAAqB,CAAA;IACrC,oBAAC,MAAD;KACE,MAAK;KACL,QAAA;KACA,SAAS;KACT,UAAU;KACV,OAAO,EAAC,cAAc,YAAW;KAEjC,UAAA,qBAAC,MAAD;MAAM,KAAK;MAAX,UAAA,CACE,oBAAC,mBAAD,EAAmB,UAAS,MAAO,CAAA,GACnC,qBAAC,OAAD;OAAO,KAAK;OAAZ,UAAA;QACE,oBAAC,MAAD;SAAM,cAAa;SAAW,IAAG;SAAK,MAAM;SACzC,UAAA,aAAa,SAAS,SAAS,aAAa,MAAM,EAAE,CAAE,OAAO,aAAa;QACvE,CAAA;QACN,oBAAC,MAAD;SAAM,IAAG;SAAI,MAAM;SAAG,OAAA;SACnB,UAAA,aAAa,SAAS,SACnB,uBAAuB,YAAY,aAAa,MAAM,EAAE,CAAE,IAAI,EAAE,KAE1D,oBAAoB,OACf,kBAAkB,YAAY,mBAAmB,IAAI,EAAE,KAE5D,oBACK,oCAEF;QAET,CAAA;QACL,aAAa,SAAS,UACrB,qBAAC,OAAD;SAAO,KAAK;SAAZ,UAAA,CACG,qBACC,oBAAC,MAAD;UAAM,IAAG;UAAI,MAAM;UAAG,OAAA;UAAM,UAAA;SAEtB,CAAA,GAEP,oBAAoB,YAAY,CAAC,mBAChC,qBAAC,MAAD;UAAM,IAAG;UAAI,MAAM;UAAG,OAAA;UAAtB,UAAA,CAA4B,cACf,cAAc,mBAAmB,QAAQ,CAChD;SAEH,CAAA,CAAA;;OAEJ;MACH,CAAA,CAAA;;IACF,CAAA;IACL,CAAC,uBACA,qBAAC,OAAD;KAAO,KAAK;KAAG,eAAe;KAA9B,UAAA,CACE,oBAAC,WAAD;MACE,MAAM,CAAC;MACP,OAAM;MACN,aACE,qBAAAiD,UAAA,EAAA,UAAA;OAAE;OAEe;OACf,oBAAC,KAAD;QACE,MAAK;QACL,QAAO;QACP,KAAI;QACL,UAAA;OAEE,CAAA;MACH,EAAA,CAAA;MAGJ,UAAA,oBAAC,MAAD;OAAM,KAAK;OACR,UAAA,qBAAqB,KAAK,EAAC,OAAO,YAAW;QAC5C,IAAM,UAAU,GAAG,GAAG,iBAAiB;QACvC,OACE,qBAAC,MAAD;SAAkB,OAAM;SAAS,KAAK;SAAtC,UAAA,CACE,oBAAC,OAAD;UACE,SAAS,OAAO,kBAAkB;UAClC,MAAK;UACL,WAAW,MACT,SAAS;WACP,QAAQ;WACR,OAAO,EAAE,cAAc;UACzB,CAAC;UAEI;UACP,IAAI;SACL,CAAA,GACD,oBAAC,MAAD;UAAM,IAAG;UAAQ,SAAS;UACvB,UAAA;SACG,CAAA,CACF;QAhBK,GAAA,KAgBL;OAEV,CAAC;MACG,CAAA;KACG,CAAA,GAEV,CAAC,eACA,qBAAAA,UAAA,EAAA,UAAA,CACE,oBAAC,WAAD;MAAW,OAAM;MAA2B,MAAM,CAAC;MACjD,UAAA,qBAAC,OAAD;OAAO,KAAK;OAAZ,UAAA;QACE,oBAAC,gBAAD;SAAoB;SAAY;SAAiB;SAAmB;QAAW,CAAA;QAC9E,yBAAyB,KACxB,oBAAC,wBAAD;SACM;SACI;SACE;SACc;QACzB,CAAA;QAEH,oBAAC,yBAAD;SAA6B;SAAY;SAAkB;QAAW,CAAA;QACrE,CAAC,0BACA,oBAAC,kBAAD;SACE,QAAQ,OAAO;SACL;SACV,aAAa,aAAa;QAC3B,CAAA;OAEE;;KACE,CAAA,GACX,oBAAC,kBAAD;MACU;MACE;MACI;MACM;MACU;MACJ;MAC1B,oBAAoB;KACrB,CAAA,CACD,EAAA,CAAA,CAEC;;IAGT,oBAAC,KAAD;KAAK,WAAW;KACd,UAAA,oBAAC,QAAD;MACE,UACG,CAAC,eAAe,CAAC,0BAClB,oBAAoB,QACpB,qBACC,qBAAqB,CAAC;MAEzB,MAAM;MACN,MAAK;MACL,MAAK;MACL,eAAe;OACb,IAAI,CAAC,iBAAiB;QACpB,IAAM,EAAC,UAAU,cAAa,mBAAmB,QAAQ,SAAS,EAChE,kBAAkB,oBAAoB,YACxC,CAAC;QACD,YAAY,UAAU,SAAS;OACjC;MACF;KACD,CAAA;IACE,CAAA;GACA;;CACD,CAAA;AAEZ;AAEA,SAAS,0BACP,QACA,SACmD;CACnD,IAAM,6BAAgF,CAAC;CAiBvF,OAhBI,OAAO,iBACT,2BAA2B,KAAK,EAAC,QAAQ,SAAQ,CAAC,GAEhD,OAAO,iBACT,2BAA2B,KAAK,EAAC,QAAQ,SAAQ,CAAC,GAEhD,OAAO,eACL,QAAQ,cACV,2BAA2B,KAAK;EAC9B,QAAQ;EACR,sBAAsB,QAAQ,eAAe,KAAA;CAC/C,CAAC,IAED,QAAQ,MAAM,sDAAsD,IAGjE;AACT;AAEA,SAAS,mBACP,QACA,SACA,SAIA;CACA,IAAM,sBAAsB,OAAO,YAChC,OAA+B,oBAAoB,CAAC,CACpD,KAA0D,WAAW;EACpE,MAAM,MAAM;EACZ,eAAe,MAAM;CACvB,EAAE,GAEE,SAAoD,CACxD;EACE,MAAM;EACN,qBAAqB,oBAAoB,SAAS,IAAI,sBAAsB,KAAA;CAC9E,GACA,GAAG,OAAO,YAAY,OAAwB,iBAAiB,CAAC,CAAC,QAC9D,KAAK,WACA,MAAM,iBAAiB,MAAM,QAAQ,MAAM,QAC7C,IAAI,KAAK;EACP,KAAK,MAAM,KAAK;EAChB,MAAM;EACN,WAAW,MAAM,SAAS,cAAc,cAAc,KAAA;EACtD,eAAe,MAAM;EACrB,MAAM,MAAM;EACZ,iBAAiB,MAAM,SAAS;CAClC,CAAC,GAEI,MAET,CAAC,CACH,CACF;CAEA,IAAI,OAAO,WAAW,UAAU;EAE9B,IAAM,kBAAkB,6BAA6B;GADX,GAAG,OAAO;GAAW,SAAS;EACnB,GAAiB;GACpE,kBAAkB,SAAS,oBAAoB,KAAA;GAC/C,OAAO;EACT,CAAC;EACD,AAAI,mBACF,OAAO,KAAK;GACV,KAAK,OAAO,UAAU;GACtB,kBAAkB;EACpB,CAAC;CAEL;CAEA,OAAO;EACL,UAAU;GACR,OAAO;GACP,mBACE,OAAO,kBAAkB,SAAS,IAC9B,OAAO,kBAAkB,KAAK,gBAAgB,EAAC,WAAU,EAAE,IAC3D,KAAA;GACN,4BAA4B,0BAA0B,QAAQ,OAAO;GACrE,qBAAqB,OAAO;GAC5B,eAAe,OAAO;GACtB,iBAAiB,OAAO;EAC1B;EACA,WAAW,OAAO,WAAW,WAAW;GAAC,GAAG,OAAO;GAAW,SAAS;EAAI,IAAI,KAAA;CACjF;AACF;AAEA,SAAS,iBAAA,IAgBN;gBAhBuB,EACxB,QACA,UACA,cACA,oBACA,8BACA,0BACA,uBAPwB1B;CAiBxB,IAAI,oBAAoB,gBAAgB,IAAO,OAAO;CAG5CC,IAAAA;qDAAC,KAAA,CAAA;CAGLC,IAAAA;;EACE;EAAiF;EACjF,oBAAC,KAAD;GACE,MAAK;GACL,QAAO;GACP,KAAI;GAEJ,UAAA;EACC,CAAA;CACH,EAAA,CAAA;CAKWC,IAAAA;CAAOC,AAAAA,EAAAA,OAAAA,OAAAA,yBAAP,KAAA,OAAO,aAAa,EAAC,SAAS,GAAK,GAA5BA,EAAAA,KAAAA,OAAAA;CACRC,IAAAA;CACR,AAAA,EAAA,OAAA,wBADQ,MAAC,cAAc;EACvB,SAAS;GAAC,QAAQ;GAAa,OAAO;EAAS,CAAC;CAClD,GADE,EAAA,KAAA;CAHJC,IAAAA;CAKsB,AAAA,EAAA,OAAA,sBAAA,EAAA,OAJTH,MAAAA,EAAAA,OACDE,MAAAA,EAAAA,OAIW,gCAAA,EAAA,QACJ,4BAPnB,KAAA,oBAAC,mBAAD;EACE,WAAWF;EACX,UAAUE;EAGU;EACpB,qBAAqB;EACrB,iBAAiB;CAClB,CAAA,GAHqB,EAAA,KAAA,oBAJTF,EAAAA,KAAAA,IACDE,EAAAA,KAAAA,IAIW,EAAA,KAAA,8BACJ,EAAA,MAAA;CAElBE,IAAAA;CAAOH,AAAAA,EAAAA,QAAAA,OAAAA,aAAAA,EAAAA,QASA,YAAA,EAAA,QARNI,gBAAAA,EAAAA,QAMsBC,sBAAAA,EAAAA,QAIG,gCAAA,EAAA,QACX,4BAZf,KAAA,OAAO,WAAW,YACjB,aAAa,SAAS,UAEtB,CAAC,OAAO,UAAU,oBAChB,oBAAC,kBAAD;EACgB;EACd,WAAW,OAAO;EAClB,kBAAkB,mBAAmB;EACrC,oBAAoB,gBAAc;GAChC,SAAS;IAAC,QAAQ;IAAa,OAAOL;GAAS,CAAC;EAClD;EACA,qBAAqB;EACrB,UAAU;CACX,CAAA,GAbGA,EAAAA,MAAAA,OAAAA,WASA,EAAA,MAAA,UARNI,EAAAA,MAAAA,cAMsBC,EAAAA,MAAAA,oBAIG,EAAA,MAAA,8BACX,EAAA,MAAA;CAtCpBC,IAAAA;CADF,OAkBMJ,EAAAA,QAAAA,MAAAA,EAAAA,QASCC,MA1BL,KAAA,oBAAC,WAAD;EACE,MAAMN;EACN,OAAM;EACN,aACEC;EAYF,UAAA,qBAAC,OAAD;GAAO,KAAK;GAAZ,UAAA,CACEI,IASCC,EAeI;;CACE,CAAA,GAzBPD,EAAAA,MAAAA,IASCC,EAAAA,MAAAA,8BA1BLG;AA4CJ;AAGA,MAAM,mBAAmB,KAAK,SAAS,iBAAA,IAcpC;gBAdqD,EACtD,cACA,WACA,mBACA,kBACA,qBACA,aANsDC,IAgB5CC,IAWPC;CAXH,AAC0BL,EAAAA,OAAAA,gBAAAA,EAAAA,OAApBM,YADI,WAAM;EACd,IAAI,SAAS,WAAW,aAAa,SAAS,QAAQ;GACpD,IAAM,OAAO,aAAa,MAAM,IAC1B,MAAM,IAAI,gBAAgB,IAAK;GAGrC,OAFA,SAAS,QAAQ,MAAM,WAEV;IACX,IAAI,gBAAgB,GAAG;GACzB;EACF;CAEF,GAAG,KAAA,CAAC,cAAc,QAAQ,GAVAN,EAAAA,KAAAA,cAApBM,EAAAA,KAAAA,0DADN,UAAUF,IAWPC,EAAwB;CAE3B,IAAM,aACJ,oBAAqB,QAA0C,mBAAmB,GAMzEE;;EACL,UAAU;EAEV,SAAS;EACT,gBAAgB;CAClB;CASW,IAAA,KAAA,aAAa,SAAS,QAChB,KAAA,mBAAmB,OAAO,gBAAgB,IAAI,QACvDC;oCAAa,KAAA,aAAA;EAAC,QAAQ;EAAS,WAAW;CAAM,IAAI,EAAC,WAAW,QAAO,GAAvE,EAAA,KAAA;CANCC,IAAAA;CAIEC,AAAAA,EAAAA,OAAAA,MAAAA,EAAAA,OACMC,MAAAA,EAAAA,OACTH,MANC,KAAA;EACL,UAAU;EAGV,OAAOE;EACP,aAAaC;EACb,GAAIH;EACJ,UAAU;CACZ,GAJSE,EAAAA,KAAAA,IACMC,EAAAA,KAAAA,IACTH,EAAAA,KAAAA;CAMGI,IAAAA;;EACL,UAAU;EACV,KAAK;EACL,MAAM;EACN,OAAO;EACP,QAAQ;EACR,WAAW;EACX,SAAS;CACX;CAVFC,IAAAA;CACO,AAAA,EAAA,QAAA,yBADP,KAAA,oBAAC,SAAD;EACE,KAAK;EACL,OAAOD;CASR,CAAA,GAVM,EAAA,MAAA;CAcS,IAAA,MAAA,qBACG,MAAA,UAJnBE;CAEY,AAAA,EAAA,QAAA,qBAAA,EAAA,QACIC,OAAAA,EAAAA,QACGC,OAAAA,EAAAA,QAHN,aADb,MAAA,oBAAC,oBAAD;EACa;EACX,UAAU;EACV,cAAcD;EACd,iBAAiBC;CAClB,CAAA,GAHW,EAAA,MAAA,mBACID,EAAAA,MAAAA,KACGC,EAAAA,MAAAA,KAHN,EAAA,MAAA;CApCjBC,IAAAA;CADF,OAaW,EAAA,QAAA,uBAAA,EAAA,QAuBLH,OAAAA,EAAAA,QAtBOL,MAAAA,EAAAA,QAUPI,MAvBJ,MAAA,oBAAC,MAAD;EACE,MAAK;EACL,QAAA;EACA,OAAON;EAQP,UAAA,qBAAC,OAAD;GACE,KAAK;GACL,OAAOE;GAFT,UAAA,CAYEI,IAYAC,GAMG;;CACD,CAAA,GA9BG,EAAA,MAAA,qBAuBLA,EAAAA,MAAAA,KAtBOL,EAAAA,MAAAA,IAUPI,EAAAA,MAAAA,gCAvBJI;AA4CJ,CAAC;AC/qBD,SAAgB,cAAoC,WAAiC;CAGnF,OAAO,OAAO,SAAS,CAAC,CAAA,WAAA;;;CAAuB,CAAA,CAAA,EAAA,EAAC,SAAS,YAAW;EAClE,IAAM,SAAS;GACb,OAAO;GACP,OAAO;EACT;EAEA,OAAO,GAAG,2BACmB,qBAAqB,MAAM,EAAE,iBAEvC,IAEf,MAAM,OAAO,OAAO,EACtB,EAAE,wFAK2B,eAAe;GACxC,MAEE,MAAM,OAAO,MAAM;GACrB;GACA,WAEE,MAAM,OAAO;EACjB,CAAC,EAAE;CAGT,CAAC;AACH;AChCA,MAAM,0BAA0B,cAAc,IAAI;AAWlD,SAAgB,WAAA,IASwC;gBAT7B,EACzB,UACA,MACA,SACA,QACA,aACA,aACA,YACA,QARyBG,IAUnB,WAAW,OAAyB,IAAI,GACgCC;qDAAC,MAAA,UAAU;EAIvF,AAHe,MAAM,OAGV,QAAQ,UAAU,MAIxB,MAAM,WAAW,MAAM,YAAY,MAAM,QAAQ,OACpD,SAAS,QAAS,MAAM;CAE5B;CAXA,IAAM,gBAAgBC,IA4BlBC;qDAAC,KAAA,oBAAAG,eAAD,EAAa,KAAK,SAAW,CAAA;CAd/BF,IAAAA;CADF,OAgBK,EAAA,OAAA,YAAA,EAAA,OALY,eAAA,EAAA,OACA,eAAA,EAAA,OACD,cAAA,EAAA,OAHJ,UAAA,EAAA,OADC,WAAA,EAAA,OANJ,OAAA,EAAA,OADC,QADR,KAAA,qBAAC,yBAAD;EACQ;EACD;EACL,SAAS;EACT,QAAQ;EACR,QAAQ;EACR,UAAU;EACV,WAAW;EACF;EACD;EACK;EACA;EACD;EAZd,UAAA,CAcED,IACC,QACsB;KADtB,EAAA,KAAA,UALY,EAAA,KAAA,aACA,EAAA,KAAA,aACD,EAAA,KAAA,YAHJ,EAAA,KAAA,QADC,EAAA,KAAA,SANJ,EAAA,KAAA,KADC,EAAA,KAAA,gCADRC;AAkBJ;AAEA,MAAME,gBAAc,OAAO,MAAM,MAAM,EAAC,MAAM,OAAM,CAAC,CAAC,CAAA,WAAA;;;6EC1DhD,cAAc,OAAO,MAAA,WAAA;;;AAAK,CAAA,CAAA,oFAS1BU,UAAQ,OAAO,MAAA,WAAA;;;AAAK,CAAA,CAAA,sBAQb,mBAAA,OAA0E;gBAA5C,QAAV,UAAqB;CAAtBT,AAAAA,EAAAA,OAAAA,uDAAC,CAAA,UAAU,QAAQ,GAAA,SAAnBA;CAC9B,IAAM,UAAU,aAAa,MAAM,KAC7B,WAAW,OAAyB,IAAI,GAE5CC;CACM,AAAA,EAAA,OAAA,wBADN,MAAC,UAAU;EACT,AAAI,YACF,SAAS,MAAM,OAAO,KAAM;CAEhC,GAHM,EAAA,KAAA;CAFR,IAAM,eAAeC,IAQiBC;qDAAM,WAAA,SAAS,SAAS,MAAM;CAApE,IAAM,oBAAoBC,IAGtBC;CACU,AAAA,EAAA,OAAA,UAAA,EAAA,OAKE,gBAAA,EAAA,OADN,WALN,KAAA,oBAAC,aAAD;EACU;EACR,KAAK;EACL,UAAU;EACV,MAAK;EACL,IAAI;EACJ,UAAU;EACV,OAAM;CACP,CAAA,GAPS,EAAA,KAAA,QAKE,EAAA,KAAA,cADN,EAAA,KAAA;CAQGC,IAAAA;sDAAC,KAAA,EAAA,OAAO,OAAM;CAJvBC,IAAAA;CAKM,AAAA,EAAA,QAAA,sBALN,KAAA,oBAAC,QAAD;EACE,SAAS;EACT,MAAK;EACL,MAAK;EACL,OAAOD;EACP,GAAI;CACL,CAAA,GADK,EAAA,MAAA;CAfRE,IAAAA;CADF,OACkB,EAAA,QAAA,WAAA,EAAA,QACdH,MAAAA,EAAAA,QASAE,MAVF,KAAA,qBAACE,SAAD;EAAO,SAAS;EAAhB,UAAA,CACEJ,IASAE,EAOK;KAjBS,EAAA,MAAA,SACdF,EAAAA,MAAAA,IASAE,EAAAA,MAAAA,8BAVFC;AAmBJ;ACzCA,SAAS,mBAAmB,QAAwB;CAClD,OAAO,OACJ,MAAM,GAAG,CAAC,CACV,KAAK,SAAS,KAAK,KAAK,CAAC,CAAC,QAAQ,MAAM,EAAE,CAAC,CAAC,CAC5C,KAAK,MAAM;AAChB;AAWA,SAAwB,kBAAkB,OAA+B;gBACjE,EAAC,gBAAgB,UAAU,UAAU,UAAU,YAAY,WAAU,OAC1CG;CAAM,AAAA,EAAA,OAAA,8BAAN,WAAM,eAAe,cAAc,GAA7B,EAAA,KAAA;CAAvC,IAAM,eAAeC,IACkBC;CAAM,AAAA,EAAA,OAAA,8BAAN,WAAM,eAAe,SAAS,GAAxB,EAAA,KAAA;CAA7C,IAAM,qBAAqBC,IACrB,EAAC,oBAAmB,iBAAiB,MAAM,MAAM,GAK7C,KAAA,WAAW,gBAAgB,WAK1BC;kCAAW,KAAA,WAAA,EAAC,aAAa,cAAa,IAAI,KAAA,GAA1C,EAAA,KAAA;CAMMC,IAAAA;;EAAC;EAAU;EAAU;CAAK;CAKnCC,IAAAA;qDAAC,KAAA,oBAAA,MAAD;EAAM,SAAQ;EACZ,UAAA,oBAAC,MAAD;GAAM,OAAA;GACJ,UAAA,oBAAC,mBAAD,CAAoB,CAAA;EAChB,CAAA;CACF,CAAA;CAGIC,IAAAA;CAAmB,AAAA,EAAA,OAAA,sBAAnB,KAAA,mBAAmB,MAAM,GAAN,EAAA,KAAA;CAR/BC,IAAAA;CAQYD,AAAAA,EAAAA,QAAAA,mBARZ,KAAA,qBAAC,MAAD;EAAM,OAAM;EAAS,SAAQ;EAAa,KAAK;EAAG,MAAM;EAAxD,UAAA,CACED,IAKA,oBAAC,MAAD;GAAM,SAAQ;GACZ,UAAA,qBAAC,MAAD;IAAM,MAAM;IAAG,OAAA;IAAf,UAAA;KACE;KAAMC;KAA2B;IAC7B;;EACF,CAAA,CACF;KAHMA,EAAAA,MAAAA;CAKVE,IAAAA;CACU,AAAA,EAAA,QAAA,UAAA,EAAA,QAKE,YANZ,KAAA,oBAAC,iBAAD;EACU;EACR,MAAK;EACL,MAAK;EACL,MAAM;EACN,MAAK;EACK;CACX,CAAA,GANS,EAAA,MAAA,QAKE,EAAA,MAAA;CAEZC,IAAAA;CAA8D,AAAA,EAAA,QAAA,6BAA9D,KAAA,oBAAC,QAAD;EAAQ,MAAK;EAAQ,MAAM;EAAY,MAAK;EAAS,SAAS;CAAe,CAAA,GAAf,EAAA,MAAA;CAE7DC,IAAAA;CAKY,AAAA,EAAA,QAAA,sBAAA,EAAA,QALZ,mBAAA,EAAA,QAIS,cAJT,MAAA,mBACC,oBAAC,QAAD;EACE,SAAS;EACT,QAAQ;EACR,MAAM,aAAa,aAAa,KAAA;EAChC,SAAS;EACT,MAAM;EACN,MAAK;EACL,OAAM;CACP,CAAA,GAJU,EAAA,MAAA,oBALZ,EAAA,MAAA,iBAIS,EAAA,MAAA;CAfZC,IAAAA;CAWGD,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAVDF,MAAAA,EAAAA,QAQAC,MATF,MAAA,qBAAC,QAAD;EAAQ,KAAK;EAAb,UAAA;GACED;GAQAC;GAECC;EAWK;KAXLA,EAAAA,MAAAA,KAVDF,EAAAA,MAAAA,IAQAC,EAAAA,MAAAA;CA7BJG,IAAAA;CAoBED,AAAAA,EAAAA,QAAAA,OAAAA,EAAAA,QAZAJ,MARF,MAAA,qBAAC,MAAD;EACE,OAAM;EACN,SAAQ;EACR,KAAK;EACL,WAAWH;EACX,UAAU;EACV,QAAO;EANT,UAAA,CAQEG,IAYAI,GAuBI;KAvBJA,EAAAA,MAAAA,KAZAJ,EAAAA,MAAAA;CAjBJM,IAAAA;CADF,OAUID,EAAAA,QAAAA,OAAAA,EAAAA,QAPME,MAAAA,EAAAA,QAKCX,MAPT,MAAA,oBAAC,MAAD;EACE,QAAO;EACP,MAAMW;EACN,QAAA;EACA,QAAQ;EACR,UAAU;EACV,UAAU;EACV,OAAOX;EAEPS,UAAAA;CA4CI,CAAA,GA5CJA,EAAAA,MAAAA,KAPME,EAAAA,MAAAA,IAKCX,EAAAA,MAAAA,gCAPTU;AAuDJ;ACpCA,MAAM,gBAAuB;CAC3B,cAAc;CACd,cAAc;CACd,OAAO;AACT;;;;;;AAoBA,SAAwB,SAAS,OAAc;CAC7C,IAAM,QAAQ,SAAS,GACjB,eAAe,OAAuB,IAAI,GAE1C,iBAAiB,OAAsB,CAAC,CAAC,GACzC,CAAC,WAAW,gBAAgB,SAAqC,IAAI,GAErE,qBAAqB,cAClB;EACL,IAAM,UAAU,IAAI,QAAQ;EAC5B,OAAO;GACL,YAAY,QAAQ,aAAa;GACjC,cAAc,UAA+C,QAAQ,KAAK,KAAK;EACjF;CACF,EAAA,CAAG,CACL,CAAC,CAAC,SAEI,YAAY,OAA4B,IAAI,GAC5C,sBAAsB,OAAsB,IAAI,GAChD,CAAC,OAAO,YAAY,YAEvB,MAAa,WAAgC;EAC5C,QAAQ,OAAO,QAAf;GACE,KAAK,eACH,OAAO,OAAO,OAAO,CAAC,GAAG,eAAe,EAAC,cAAc,OAAO,MAAK,CAAC;GACtE,KAAK,gBACH,OAAO,OAAO,OAAO,CAAC,GAAG,MAAM,EAAC,cAAc,EAAC,UAAU,EAAC,EAAC,CAAC;GAC9D,KAAK,gBAAgB;IAEnB,IAAM,EAAC,MAAM,QAAQ,GAAG,GAAG,YAAW;IACtC,OAAO,OAAO,OAAO,CAAC,GAAG,MAAM,EAC7B,cAAc;KACZ,GAAG,KAAK;KACR,UAAU,KAAK,aAAc;KAC7B,GAAG;IACL,EACF,CAA6C;GAC/C;GACA,KAAK,YACH,OAAO,OAAO,OAAO,CAAC,GAAG,MAAM,EAC7B,cAAc;IACZ,GAAG,KAAK;IACR,UAAU,OAAO;GACnB,EACF,CAA6C;GAC/C,KAAK;GACL,KAAK,YAKH,OAHA,UAAU,SAAS,YAAY,GAC/B,UAAU,UAAU,MACpB,oBAAoB,UAAU,MACvB;GACT,KAAK,SAAS;IAIZ,AAFA,UAAU,SAAS,YAAY,GAC/B,UAAU,UAAU,MACpB,oBAAoB,UAAU;IAE9B,IAAI,QAAQ,OAAO;IAOnB,OANI,cAAc,OAAO,KAAK,KAAK,kBAAkB,OAAO,UAAU,KAAK,MACzE,QAAQ,gBAAI,MACV,qHACF,IAGK,OAAO,OAAO,CAAC,GAAG,eAAe,EAAQ,MAAK,CAAC;GACxD;GACA,SACE,OAAO;EACX;CACF,GACA;EACE,cAAc;EACd,cAAc;EACd,OAAO;CACT,CACF;CAIA,gBAAgB;EACd,IAAM,gBAAgB;GAOpB,IALI,UAAU,WAAW,CAAC,UAAU,QAAQ,UAC1C,UAAU,QAAQ,YAAY,GAI5B,oBAAoB,WAAW,MAAM,OAAO,QAAQ,oBAAoB,SAAS;IACnF,IAAM,QAAQ,oBAAoB;IAGlC,AAFA,oBAAoB,UAAU,MAE9B,MAAM,OAAO,OAAO,KAAK,CAAC,CAAC,OAAO,QAAQ;KACxC,QAAQ,KAAK,+CAA+C,GAAG;IACjE,CAAC;GACH;EACF,GAEM,2BAA2B;GAC/B,QAAQ;EACV;EAKA,OAHA,OAAO,iBAAiB,gBAAgB,kBAAkB,GAC1D,OAAO,iBAAiB,YAAY,kBAAkB,SAEzC;GAGX,AAFA,OAAO,oBAAoB,gBAAgB,kBAAkB,GAC7D,OAAO,oBAAoB,YAAY,kBAAkB,GACzD,QAAQ;EACV;CACF,GAAG,CAAC,MAAM,QAAQ,MAAM,OAAO,GAAG,CAAC;;;;;;;;;;;CAgBnC,IAAM,eACJ,UACA,cACG;EACH,IAAM,EAAC,iBAAgB;EACvB,IAAI,CAAC,gBAAgB,UAAU,SAAS;EACxC,SAAS,EAAC,QAAQ,eAAc,CAAC;EACjC,IAAI;EACJ,QAAQ,aAAa,MAArB;GACE,KAAK;IACH,mBAAmB,UAAU;KAC3B,QAAQ,MAAM;KACd,KAAK,aAAa;KAClB;KACA;IACF,CAAC;IACD;GACF,KAAK,QACH,mBAAmB,WAAW;IAC5B,QAAQ,MAAM;IACd,MAAM,aAAa,MAAM;IACzB;IACA;GACF,CAAC,CAAC,CAAC,KACD,UACE,mBAAmB,WAAW,KAC5B,UAAU;IACR,AAEE,oBAAoB,aADpB,MAAW,OAAO,OAAO,oBAAoB,OAAO,GACtB;GAElC,CAAC,CACH,CACF,CACF;EAEJ;EACA,UAAU,UAAU,iBAAiB,UAAU;GAC7C,OAAO,UAAU;IACf,QAAQ,MAAM,MAAd;KACE,KAAK;MAGH,AADA,oBAAoB,UAAU,MAAM,MACpC,SAAS;OAAC,QAAQ;OAAgB,GAAG;MAAK,CAAC;MAC3C;KACF,KAAK;KACL,KAAK;MACH,SAAS;OAAC,QAAQ;OAAgB,GAAG;MAAK,CAAC;MAC3C;KACF,KAAK;MACH,SAAS;OAAC,QAAQ;OAAY,SAAS,MAAM;MAAO,CAAC;MACrD;KACF,KAAK,WAGH,AAFA,SAAS;MAAC,QAAQ;MAAY,SAAS;KAAG,CAAC,GAC3C,oBAAoB,UAAU,MAC9B,MAAM,SACJ,WAAW,KAAK,CACd,aAAa,EAAC,OAAO,CAAC,EAAC,CAAC,GACxB,IAAI;MAAC,OAAO;MAAa,OAAO;MAAM,MAAM,MAAM,MAAM;KAAG,GAAG,CAAC,OAAO,CAAC,CACzE,CAAC,CACH;IAMJ;GACF;GACA,gBAAgB,SAAS,EAAC,QAAQ,WAAU,CAAC;GAC7C,QAAQ,UAAU,SAAS;IAAC,QAAQ;IAAS;IAAO;GAAQ,CAAC;EAC/D,CAAC;CACH,GAEM,mBAAmB,kBAAkB;EACzC,MAAM,KAAK;GACT,QAAQ;GACR,OAAO,sCAAsC,MAAM,OAAO,mBAAmB,KAAK,IAAI;EACxF,CAAC;CACH,GAAG,CAAC,MAAM,OAAO,mBAAmB,KAAK,CAAC,GAOpC,iBAAiB,UACH,MAAM,KAAK,KAAK,CAAC,CAAC,MAAM,SACjC,CAAC,MAAM,OAAO,mBAAmB,MAAM,iBAAiB;EAE7D,IAAM,UAAU,IAAI,aAAa,QAAQ,KAAK,IAAI,EAAE;EACpD,OAAO,IAAI,OAAO,OAAO,CAAC,CAAC,KAAK,KAAK,IAAI;CAC3C,CAAC,CAGI,GAQH,gBAAgB,UAA6B;EACjD,AAAI,cAAc,KAAK,KACvB,SAAS;GACP,QAAQ;GACR,OAAO;IAAC,MAAM;IAAQ;GAAK;EAC7B,CAAC;CACH,GAGM,eAA8D,UAAU;EAI5E,IAHe,MAAM,OAGV,QAAQ,UAAU,GAC3B;EAIF,AADA,MAAM,eAAe,GACrB,MAAM,gBAAgB;EAGtB,IAAM,OADJ,MAAM,iBAAkB,OAAmD,cAAA,EAClD,QAAQ,MAAM,CAAC,EAAE,KAAK;EACjD,AAAK,WAAW,GAAG,IAInB,SAAS;GAAC,QAAQ;GAAe,OAAO;IAAC,MAAM;IAAY;GAAG;EAAC,CAAC,IAH9D,MAAM,KAAK;GAAC,QAAQ;GAAS,OAAO;EAAkC,CAAC;CAI3E,GAGM,cAAsD,UAAU;EAGpE,AAFA,MAAM,eAAe,GACrB,MAAM,gBAAgB,GAClB,cAAc,aAChB,iBAAiB,GACjB,aAAa,IAAI,MAGnB,aAAa,IAAI,GACjB,oBAAyB,MAAM,YAAY,YAAa,CAAC,CAAC,MAAM,UAAU;GACxE,SAAS;IACP,QAAQ;IACR,OAAO;KAAC,MAAM;KAAQ;IAAK;GAC7B,CAAC;EACH,CAAC;CACH,GAIM,kBAA0D,UAAU;EAExE,AADA,MAAM,eAAe,GACrB,MAAM,gBAAgB;CACxB,GAEM,mBAA2D,UAAU;EAEzE,AADA,MAAM,gBAAgB,GACtB,eAAe,QAAQ,KAAK,MAAM,MAAM;EACxC,IAAM,OAAO,MAAM,aAAa,QAAQ,EAAE,EAAE,MAItC,cAHY,MAAM,OAAO,mBAGA,MAAM,iBAAiB;GAEpD,IAAM,UAAU,IAAI,aAAa,QAAQ,KAAK,IAAI,EAAE;GACpD,OAAO,IAAI,OAAO,OAAO,CAAC,CAAC,KAAK,IAAK;EACvC,CAAC;EAED,aAAa,cAAc,UAAU,SAAS;CAChD,GAEM,mBAA2D,UAAU;EACzE,MAAM,gBAAgB;EACtB,IAAM,MAAM,eAAe,QAAQ,QAAQ,MAAM,MAAM;EAIvD,AAHI,MAAM,MACR,eAAe,QAAQ,OAAO,KAAK,CAAC,GAElC,eAAe,QAAQ,WAAW,KACpC,aAAa,IAAI;CAErB;CAKA,IAAI,MAAM,UAAU,MAAM;EACxB,IAAM,QAAQ,MAAM;EACpB,OACE,qBAAC,MAAD;GAAM,KAAK;GAAG,WAAU;GAAS,SAAQ;GAAS,OAAM;GAAxD,UAAA;IACE,oBAAC,MAAD;KAAM,MAAM;KAAG,OAAA;KACb,UAAA,oBAAC,kBAAD,CAAmB,CAAA;IACf,CAAA;IACN,oBAAC,MAAD,EAAA,UAAM,uBAA0B,CAAA;IAC/B,iBAAiB,SAAS,MAAM,WAC/B,oBAAC,MAAD;KAAM,MAAM;KAAG,OAAA;KAAM,QAAO;KAAW,OAAO,EAAC,WAAW,SAAQ;KAC/D,UAAA,MAAM;IACH,CAAA;IAER,oBAAC,QAAD;KAAQ,MAAK;KAAsB,eAAe,SAAS,EAAC,QAAQ,QAAO,CAAC;IAAI,CAAA;GAC5E;;CAEV;CAGA,IAAI,MAAM,iBAAiB,MAAM;EAC/B,IAAM,EAAC,iBAAgB;EACvB,OACE,oBAAC,gBAAD;GAEE,UAAU,mBAAmB;GAC7B,UAAU,aAAa;GACvB,UAAU,aAAa,MAAM,QAAQ,aAAa;EACnD,CAAA;CAEL;CAGA,IAAI,MAAM,iBAAiB,MACzB,OACE,oBAAC,qBAAD;EACE,cAAc,MAAM;EACpB,cAAc,MAAM;EACpB,SAAS,MAAM;EACF;EACb,eAAe,SAAS,EAAC,QAAQ,QAAO,CAAC;CAC1C,CAAA;CAKL,IAAI;CACJ,AAAI,cAAW,OAAO,cAAc,UAAU,aAAa;CAE3D,IAAM,mBAAmB,MAAM,QAAQ,mBAAmB,SACtD,MAAM,OAAO,kBAAkB,KAAK,GAAG,IACvC;CAEJ,OACE,qBAAAG,UAAA,EAAA,UAAA,CACE,oBAAC,YAAD;EACQ;EACN,QAAQ;EACR,YAAY;EACZ,aAAa;EACb,aAAa;EACb,SAAS;EACT,KAAK;EAEJ,UAAA,MAAM,QACL,oBAAC,qBAAD;GACE,aAAa,MAAM;GACnB,gBAAgB,MAAM;GAEtB,UAAA,oBAAC,QAAD;IACE,UAAU,MAAM;IAChB,OAAO,MAAM;IACb,UAAU,MAAM;IAChB,QAAQ,MAAM;IACd,SACE,oBAACC,2BAAD;KACE,QAAQ;KACR,OAAO,MAAM;KACb,aAAa,MAAM;KACnB,gBAAgB,MAAM;KACtB,UAAU,MAAM;KAChB,UAAU;KACV,UAAU,MAAM;KAChB,QAAQ,MAAM;IACf,CAAA;GAEJ,CAAA;EACkB,CAAA,IAErB,oBAAC,mBAAD;GACE,QAAQ;GACR,UAAU,cAAc;GACxB,UAAU;GACV,UAAU,CAAC,CAAC,MAAM;GAClB,gBAAgB,MAAM;GACtB,YAAY,MAAM;GAClB,QAAQ,MAAM;EACf,CAAA;CAEO,CAAA,GACX,MAAM,gBAAgB,kBACrB,oBAAC,cAAD;EACE,QAAQ,MAAM;EACd,OAAO,MAAM;EACb,UAAU,MAAM;EAChB,gBAAgB,MAAM;CACvB,CAAA,CAEH,EAAA,CAAA;AAEN;ACheA,MAAM,SAAS,UAAsB;gBAC7B,SAASS,YAAU,GACnB,uBAAuB,yBAAyB,GAChD,sBAAsB,uBAAuB,MAAM,OAAO,KAAK,GAC/D,OAAO,cAAc,MAAM,WAAW,KAAA,IAAY,qBAAqB,SAAS,KAAA,CAAS,GACzF,CAAC,aAAa,kBAAkB,eAAe,GAC/C,EAAC,oBAAmB,iBAAiB,MAAM,MAAM,GAEjD,QAAQ,qBAAqB,SAAS,oBAAoB,SAAS,KAAK;CAM9E,IAAI,OAEF,MAAM;CAER,IAAM,YAAY,qBAAqB,aAAa,oBAAoB,WAK9CR;qDAAC,KAAA,oBAAA,eAAD,CAAgB,CAAA;CAApCC,IAAAA;CAKiDC,AAAAA,EAAAA,OAAAA,uBAAAA,EAAAA,OAO/B,UAAA,EAAA,OAGK,eAAA,EAAA,OAMa,mBAAA,EAAA,OApBjC,aAAA,EAAA,OAKsDC,SAAAA,EAAAA,OAD7BC,qBAAAA,SAAAA,EAAAA,OACK,kBANjC,KAAA,oBAAC,UAAD;EAAU,UAAUJ;EACjB,UAAA,YACC,oBAAC,eAAD,CAAgB,CAAA,IAEhB,qBAAAS,UAAA,EAAA,UAAA,CACG,qBAAqB,MAAM,cAAc,CAAC,oBAAoB,QAC7D,oBAAC,SAAD;GAAyB;GAAgB,QAAQ,MAAM;EAAS,CAAA,IAEhE,oBAAC,UAAD;GACE,GAAI;GACJ,QAAQ,MAAM;GACd,UAAU,MAAM;GACR;GACR,SAAS,qBAAqB,MAAM;GACpC,OAAO,oBAAoB;GACd;GACG;GAChB,YAAY,qBAAqB,MAAM;EACxC,CAAA,GAGF,gBAAgB,aAAa,mBAC5B,oBAAC,oBAAD;GACkB;GAChB,SAAS,qBAAqB,MAAM;EACrC,CAAA,CAEH,EAAA,CAAA;CAEI,CAAA,GAxBuCP,EAAAA,KAAAA,qBAO/B,EAAA,KAAA,QAGK,EAAA,KAAA,aAMa,EAAA,KAAA,iBApBjC,EAAA,KAAA,WAKsDC,EAAAA,KAAAA,OAD7BC,EAAAA,KAAAA,qBAAAA,OACK,EAAA,KAAA;CARrCC,IAAAA;CADF,OAEyCC,EAAAA,QAAAA,MAAAA,cAAAA,EAAAA,QACnCL,MAFJ,KAAA,oBAAC,MAAD,EAAA,UACE,oBAACS,2BAAD;EAAmB,YAAY,MAAM;EACnCT,UAAAA;CA8BiB,CAAA,EACf,CAAA,GAhCiCK,EAAAA,MAAAA,MAAAA,YACnCL,EAAAA,MAAAA,8BAFJI;AAmCJ;AAEA,IAAA,gBAAe,KAAK,KAAK;ACxEzB,SAAgB,wBAAwB,QAAsB;CAC5D,OAAO;EACL,YAAY,EACV,QAAQ,UACN,oBAAC,oBAAD;GAAoB,YAAY,OAAO;GACrC,UAAA,oBAACM,eAAD;IAAO,QAAQ;KAAC,GAAG;KAAQ,GAAG,MAAM,WAAW;IAAO;IAAG,GAAI;GAAQ,CAAA;EACnD,CAAA,EAExB;EACA,SAAS;GACP,QAAQ;IACN,UAAU;IACV,YAAY;IACZ,QAAQ;IACR,SAAS;IACT,WAAW;IACX,MAAM;GACR;GACA,UAAU,UAAuC;IAC/C,IAAM,EAAC,UAAU,YAAY,WAAU;IACvC,OAAO;KACL,OAAO,YAAY,cAAc;KACjC,UAAU,SAAS,WAAW,WAAW;KACzC,OAAO,MAAM,aAAa,oBAAC,gBAAD;MAAuB;MAAO,OAAO;KAAK,CAAA,IAAI;IAC1E;GACF;EACF;CACF;AACF;ACjCA,MAAa,iBAAiB;CAC5B,MAAM;CACN,MAAM;CACN,OAAO;CACP,QAAQ,CACN;EACE,OAAO;EACP,MAAM;EACN,MAAM;EACN,MAAM;EACN,IAAI,CAAC,EAAC,MAAM,iBAAgB,CAAC;CAC/B,CACF;AACF,GA4La,cAAc;CACzB;EA1LA,MAAM;EACN,MAAM;EACN,QAAQ;GACN;IAAC,MAAM;IAAU,MAAM;GAAI;GAC3B;IAAC,MAAM;IAAU,MAAM;GAAM;GAC7B;IAAC,MAAM;IAAU,MAAM;GAAW;GAClC;IAAC,MAAM;IAAU,MAAM;GAAgB;GACvC;IAAC,MAAM;IAAU,MAAM;GAAU;GACjC;IAAC,MAAM;IAAU,MAAM;GAAY;GACnC;IAAC,MAAM;IAAU,MAAM;GAAe;GACtC;IAAC,MAAM;IAAU,MAAM;GAAM;GAC7B;IAAC,MAAM;IAAU,MAAM;GAAQ;GAC/B;IAAC,MAAM;IAAU,MAAM;GAAa;GACpC;IAAC,MAAM;IAAU,MAAM;GAAW;EACpC;CA4KA;CACA;EAzKA,MAAM;EACN,MAAM;EACN,QAAQ,CACN;GAAC,MAAM;GAAU,MAAM;EAAI,GAC3B;GAAC,MAAM;GAAU,MAAM;EAAQ,CACjC;CAoKA;CACA;EAjKA,MAAM;EACN,MAAM;EACN,QAAQ;GACN;IAAC,MAAM;IAAU,MAAM;GAAM;GAC7B;IAAC,MAAM;IAAU,MAAM;GAAK;GAC5B;IAAC,MAAM;IAAU,MAAM;GAAQ;GAC/B;IAAC,MAAM;IAAU,MAAM;GAAO;GAC9B;IAAC,MAAM;IAAU,MAAM;GAAS;GAChC;IAAC,MAAM;IAAU,MAAM;GAAU;GACjC;IAAC,MAAM;IAAU,MAAM;GAAM;GAC7B;IAAC,MAAM;IAAU,MAAM;GAAQ;GAC/B;IAAC,MAAM;IAAU,MAAM;GAAiB;GACxC;IAAC,MAAM;IAAU,MAAM;GAAY;GACnC;IAAC,MAAM;IAAU,MAAM;GAAI;GAC3B;IAAC,MAAM;IAAU,MAAM;GAAa;EACtC;CAkJA;CACA;EA/IA,MAAM;EACN,MAAM;EACN,QAAQ,CACN;GAAC,MAAM;GAAU,MAAM;EAAQ,GAC/B;GACE,MAAM;GACN,MAAM;GACN,IAAI,CAAC,EAAC,MAAM,0BAAyB,CAAC;EACxC,CACF;CAsIA;CACA;EAnIA,MAAM;EACN,MAAM;EACN,QAAQ,CACN;GAAC,MAAM;GAAU,MAAM;EAAQ,GAC/B;GAAC,MAAM;GAAU,MAAM;EAAK,CAC9B;CA8HA;CACA;EA3HA,MAAM;EACN,OAAO;EACP,MAAM;EACN,QAAQ;GACN;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;IACN,IAAI,CAAC,EAAC,MAAM,YAAW,CAAC;GAC1B;GACA;IACE,MAAM;IACN,MAAM;IACN,IAAI,CAAC,EAAC,MAAM,iBAAgB,CAAC;GAC/B;GACA;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;GACR;EACF;CAyCA;CACA;EAtCA,MAAM;EACN,MAAM;EACN,OAAO;EACP,QAAQ;GACN;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;GACR;GACA;IACE,MAAM;IACN,MAAM;GACR;EACF;CAUA;AACF,GCvMa,gBAA8B;CACzC,mBAAmB,CAAC;CAEpB,aAAa;CACb,eAAe;CACf,qBAAqB;CACrB,iBAAiB;CACjB,eAAe;CACf,eAAe;CACf,YAAY;CACZ,MAAM;CACN,8BAA8B,CAAC;CAC/B,mBAAmB,CAAC,WAAW,SAAS;AAC1C;;;;AAKA,SAAS,oBAAoB,QAE3B;CAYA,OAVI,OAAO,qBAAqB,OAAO,kBAAkB,SAAS,IACzD,EAAC,mBAAmB,OAAO,kBAAiB,IAKjD,OAAO,gBAAgB,aAClB,EAAC,mBAAmB,CAAC,SAAS,EAAC,IAGjC,EAAC,mBAAmB,CAAC,EAAC;AAC/B;AAEA,MAAa,WAAW,cAA4C,eAAe;CAEjF,IAAI,OAAO,cAAe,YAAY,mBAAmB,YAAY;EAEnE,IAAM,2BAA2B,WAAW;EAC5C,AAAK,WAAW,kBACV,6BAA6B,eAC/B,WAAW,gBAAgB,UAEzB,6BAA6B,YAC/B,WAAW,gBAAgB;CAGjC;CACA,IAAM,SAAuB;EAC3B,GAAG;EACH,GAAG;EACH,GAAG,oBAAoB,cAAc,CAAC,CAAC;CACzC;CAKA,OAJI,OAAO,eAAe,KAAA,MAExB,OAAO,aAAa,oBAAoB,OAAO,UAAU,IAEpD;EACL,MAAM;EACN,QAAQ,EACN,OAAO,CACL,GAAG,aACH;GACE,GAAG;GACH,GAAG,wBAAwB,MAAM;EACnC,CACF,EACF;EACA,OAAO,OAAO,SAAS,KAAQ,KAAA,IAAY,CAAC,iBAAiB,MAAM,CAAC;CACtE;AACF,CAAC"}
\ No newline at end of file