{"version":3,"sources":["../src/frontend/UpupUploader.tsx","../src/assets/logos.ts","../src/shared/i18n/en_US.ts","../src/shared/i18n/utils.ts","../src/frontend/components/DefaultLoaderIcon.tsx","../src/frontend/components/ImageEditorInline.tsx","../src/frontend/context/RootContext.ts","../src/frontend/lib/file.ts","../src/shared/lib/encoder.ts","../src/frontend/lib/imageEditorHelpers.ts","../src/frontend/lib/tailwind.ts","../src/frontend/components/ImageEditorModal.tsx","../src/frontend/components/MainBox.tsx","../src/frontend/hooks/useMainBox.ts","../src/frontend/components/AdapterSelector.tsx","../src/frontend/hooks/useAdapterSelector.ts","../src/shared/types.ts","../src/frontend/components/CameraUploader.tsx","../src/frontend/hooks/useCameraUploader.ts","../src/frontend/hooks/useFetchFileByUrl.ts","../src/frontend/components/shared/AdapterViewContainer.tsx","../src/frontend/components/shared/ShouldRender.tsx","../src/frontend/components/DropboxUploader.tsx","../src/frontend/hooks/useDropbox.ts","../src/frontend/hooks/useDropboxAuth.ts","../src/frontend/lib/storageHelper.ts","../src/frontend/hooks/useDropboxUploader.ts","../src/frontend/components/shared/DriveBrowser.tsx","../src/frontend/lib/googleDriveUtils.ts","../src/frontend/components/shared/DriveBrowserHeader.tsx","../src/frontend/components/shared/DriveBrowserItem.tsx","../src/frontend/components/shared/DriveBrowserIcon.tsx","../src/frontend/components/shared/MyAnimatePresence.tsx","../src/frontend/components/GoogleDriveUploader.tsx","../src/frontend/hooks/useGoogleDrive.ts","../src/frontend/hooks/useLoadGAPI.ts","../src/frontend/hooks/useGoogleDriveUploader.ts","../src/frontend/components/shared/DriveAuthFallback.tsx","../src/frontend/components/Icons.tsx","../src/frontend/components/OneDriveUploader.tsx","../src/frontend/hooks/useOneDrive.ts","../src/frontend/hooks/useOneDriveAuth.ts","../src/frontend/hooks/usePCAInstance.ts","../src/frontend/hooks/useOneDriveUploader.ts","../src/frontend/components/UrlUploader.tsx","../src/frontend/lib/constants.ts","../src/frontend/components/AdapterView.tsx","../src/frontend/components/FileList.tsx","../src/frontend/components/FileItem.tsx","../src/frontend/components/FilePreview.tsx","../src/frontend/components/FilePreviewThumbnail.tsx","../src/frontend/components/FileIcon.tsx","../src/frontend/components/shared/ProgressBar.tsx","../src/frontend/components/FilePreviewPortal.tsx","../src/frontend/components/shared/MainBoxHeader.tsx","../src/frontend/hooks/useRootProvider.ts","../src/shared/lib/checkFileType.ts","../src/frontend/lib/resumable/multipartSessionStore.ts","../src/frontend/lib/storage/provider.ts","../src/frontend/hooks/useUpload.ts"],"sourcesContent":["'use client'\n\nimport React, { forwardRef, useImperativeHandle } from 'react'\nimport { TbLoader } from 'react-icons/tb'\nimport { devinoDark, devinoLight, logoDark, logoLight } from '../assets/logos'\nimport { t } from '../shared/i18n'\nimport { FileWithParams, UpupUploaderProps } from '../shared/types'\nimport DefaultLoaderIcon from './components/DefaultLoaderIcon'\nimport ImageEditorInline from './components/ImageEditorInline'\nimport ImageEditorModal from './components/ImageEditorModal'\nimport MainBox from './components/MainBox'\nimport ShouldRender from './components/shared/ShouldRender'\nimport RootContext from './context/RootContext'\nimport useRootProvider from './hooks/useRootProvider'\nimport useUpload from './hooks/useUpload'\nimport { cn } from './lib/tailwind'\n\nexport type UpupUploaderRef = {\n    useUpload(): {\n        error?: string\n        files: FileWithParams[]\n        loading: boolean\n        progress: number\n        upload(): Promise<FileWithParams[] | undefined>\n        resetState(): void\n        dynamicUpload(\n            files: File[] | FileWithParams[],\n        ): Promise<FileWithParams[] | undefined>\n        setFiles(newFiles: File[]): void\n        dynamicallyReplaceFiles(files: File[] | FileWithParams[]): void\n    }\n}\n\nexport default forwardRef<UpupUploaderRef, UpupUploaderProps>(\n    function UpupUploader(props, ref) {\n        const providerValues = useRootProvider({\n            ...props,\n            icons: {\n                ...props.icons,\n                LoaderIcon: DefaultLoaderIcon,\n            },\n        })\n        const uploadApi = useUpload({\n            upload: providerValues.upload,\n            files: providerValues.files,\n            setFiles: providerValues.setFiles,\n            dynamicUpload: providerValues.dynamicUpload,\n            resetState: providerValues.resetState,\n            dynamicallyReplaceFiles: providerValues.dynamicallyReplaceFiles,\n        })\n\n        useImperativeHandle(ref, () => ({\n            useUpload: () => uploadApi,\n        }))\n\n        return (\n            <RootContext.Provider value={providerValues}>\n                <div className=\"upup-scope upup-h-full upup-w-full\">\n                    <div\n                        className={cn('upup-w-full', {\n                            'upup-h-[480px] upup-max-w-[600px]':\n                                !providerValues.props.mini,\n                            'upup-h-auto upup-max-w-[280px]':\n                                providerValues.props.mini,\n                        })}\n                        style={\n                            providerValues.props.mini\n                                ? { aspectRatio: '1 / 1' }\n                                : undefined\n                        }\n                    >\n                        <section\n                            aria-labelledby=\"drop-instructions\"\n                            className={cn(\n                                `upup-shadow-wrapper upup-relative ${\n                                    providerValues.props.dark\n                                        ? 'upup-bg-[#232323]'\n                                        : 'upup-bg-white'\n                                } upup-flex upup-h-full upup-w-full upup-select-none upup-flex-col upup-gap-3 upup-overflow-hidden upup-rounded-2xl upup-px-5 upup-py-4`,\n                                {\n                                    [providerValues.props.classNames\n                                        .containerFull!]:\n                                        providerValues.props.classNames\n                                            .containerFull &&\n                                        !providerValues.props.mini,\n\n                                    [providerValues.props.classNames\n                                        .containerMini!]:\n                                        providerValues.props.classNames\n                                            .containerMini &&\n                                        providerValues.props.mini,\n                                },\n                            )}\n                        >\n                            <ShouldRender\n                                if={providerValues.props.isProcessing}\n                            >\n                                <TbLoader\n                                    className={cn(\n                                        'upup-absolute upup-right-5 upup-animate-spin upup-text-xs upup-text-xs upup-leading-5 upup-text-[#0E2ADD] md:upup-text-xl',\n                                        {\n                                            'upup-text-[#59D1F9] dark:upup-text-[#59D1F9]':\n                                                providerValues.props.dark,\n                                        },\n                                    )}\n                                />\n                            </ShouldRender>\n                            <ShouldRender if={providerValues.props.limit > 1}>\n                                <p\n                                    id=\"drop-instructions\"\n                                    className={cn(\n                                        'upup-text-xs upup-leading-5 upup-text-[#6D6D6D] md:upup-text-sm',\n                                        {\n                                            'upup-text-gray-300 dark:upup-text-gray-300':\n                                                providerValues.props.dark,\n                                        },\n                                    )}\n                                >\n                                    {t(\n                                        providerValues.translations\n                                            .addDocumentsHere,\n                                        {\n                                            limit: providerValues.props.limit,\n                                        },\n                                    )}\n                                </p>\n                            </ShouldRender>\n                            <MainBox />\n\n                            {/* Inline image editor — overlays the uploader content */}\n                            {providerValues.editingFile &&\n                                providerValues.props.imageEditor.display ===\n                                    'inline' && (\n                                    <ImageEditorInline\n                                        file={providerValues.editingFile}\n                                        onClose={\n                                            providerValues.closeImageEditor\n                                        }\n                                        onSave={providerValues.saveImageEdit}\n                                    />\n                                )}\n\n                            <ShouldRender if={!providerValues.props.mini}>\n                                <div\n                                    className={cn(\n                                        'upup-flex upup-w-full upup-flex-col upup-items-center upup-justify-between upup-gap-1 md:upup-flex-row',\n                                    )}\n                                >\n                                    <a\n                                        href={'https://useupup.com/'}\n                                        target={'_blank'}\n                                        rel=\"noopener noreferrer\"\n                                        className=\"upup-flex upup-items-center upup-gap-[5px]\"\n                                    >\n                                        <ShouldRender\n                                            if={providerValues.props.dark}\n                                        >\n                                            <img\n                                                src={logoDark}\n                                                width={61}\n                                                height={13}\n                                                alt=\"logo-dark\"\n                                            />\n                                        </ShouldRender>\n                                        <ShouldRender\n                                            if={!providerValues.props.dark}\n                                        >\n                                            <img\n                                                src={logoLight}\n                                                width={61}\n                                                height={13}\n                                                alt=\"logo-light\"\n                                            />\n                                        </ShouldRender>\n                                    </a>\n                                    <a\n                                        href={'https://devino.ca/'}\n                                        target={'_blank'}\n                                        rel=\"noopener noreferrer\"\n                                        className=\"upup-flex upup-flex-row upup-items-center upup-justify-end upup-gap-1\"\n                                    >\n                                        <span\n                                            className={cn(\n                                                'upup-mr-0.5 upup-text-xs upup-leading-5 upup-text-[#6D6D6D] md:upup-text-sm',\n                                                {\n                                                    'upup-text-gray-300 dark:upup-text-gray-300':\n                                                        providerValues.props\n                                                            .dark,\n                                                },\n                                            )}\n                                        >\n                                            {\n                                                providerValues.translations\n                                                    .builtBy\n                                            }{' '}\n                                        </span>\n                                        <ShouldRender\n                                            if={providerValues.props.dark}\n                                        >\n                                            <img\n                                                src={devinoDark}\n                                                width={61}\n                                                height={13}\n                                                alt=\"logo-dark\"\n                                            />\n                                        </ShouldRender>\n                                        <ShouldRender\n                                            if={!providerValues.props.dark}\n                                        >\n                                            <img\n                                                src={devinoLight}\n                                                width={61}\n                                                height={13}\n                                                alt=\"logo-light\"\n                                            />\n                                        </ShouldRender>\n                                    </a>\n                                </div>\n                            </ShouldRender>\n                        </section>\n                    </div>\n                </div>\n                {providerValues.editingFile &&\n                    providerValues.props.imageEditor.display === 'modal' && (\n                        <ImageEditorModal\n                            file={providerValues.editingFile}\n                            onClose={providerValues.closeImageEditor}\n                            onSave={providerValues.saveImageEdit}\n                        />\n                    )}\n            </RootContext.Provider>\n        )\n    },\n)\n","export const devinoDark =\n    'data:image/png;base64,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'\nexport const devinoLight =\n    'data:image/png;base64,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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgP+w/w+fcfClL07rlQAAAA5lWElmTU0AKgAAAAgAAAAAAAAA0lOTAAAAAElFTkSuQmCC'\nexport const logoDark =\n    'data:image/png;base64,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'\nexport const logoLight =\n    'data:image/png;base64,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'\n","import type { Translations } from './types'\n\nexport const en_US: Translations = {\n    // ── General ───────────────────────────────────────────────\n    cancel: 'Cancel',\n    done: 'Done',\n    loading: 'Loading...',\n\n    // ── Adapter names ─────────────────────────────────────────\n    myDevice: 'My Device',\n    googleDrive: 'Google Drive',\n    oneDrive: 'OneDrive',\n    dropbox: 'Dropbox',\n    link: 'Link',\n    camera: 'Camera',\n\n    // ── Drop-zone / AdapterSelector ───────────────────────────\n    dragFileOr: 'Drag your file or',\n    dragFilesOr: 'Drag your files or',\n    browseFiles: 'browse files',\n    or: 'or',\n    selectAFolder: 'select a folder',\n    maxFileSizeAllowed_one: 'Max {{size}} {{unit}} file is allowed',\n    maxFileSizeAllowed_other: 'Max {{size}} {{unit}} files are allowed',\n\n    // ── UpupUploader (root) ───────────────────────────────────\n    addDocumentsHere:\n        'Add your documents here, you can upload up to {{limit}} files max',\n    builtBy: 'Built by',\n\n    // ── MainBoxHeader ─────────────────────────────────────────\n    removeAllFiles: 'Remove all files',\n    addingMoreFiles: 'Adding more files',\n    filesSelected_one: '{{count}} file selected',\n    filesSelected_other: '{{count}} files selected',\n    addMore: 'Add More',\n\n    // ── FileList ──────────────────────────────────────────────\n    uploadFiles_one: 'Upload {{count}} file',\n    uploadFiles_other: 'Upload {{count}} files',\n\n    // ── FilePreview ───────────────────────────────────────────\n    removeFile: 'Remove file',\n    clickToPreview: 'Click to preview',\n    zeroBytes: '0 Byte',\n    bytes: 'Bytes',\n    kb: 'KB',\n    mb: 'MB',\n    gb: 'GB',\n    tb: 'TB',\n\n    // ── FilePreviewPortal / Thumbnail ─────────────────────────\n    previewError: 'Error: {{message}}',\n\n    // ── DriveBrowser ──────────────────────────────────────────\n    noAcceptedFilesFound: 'No accepted files found',\n    selectThisFolder: 'Select this folder',\n    addFiles_one: 'Add {{count}} file',\n    addFiles_other: 'Add {{count}} files',\n\n    // ── DriveBrowserHeader ────────────────────────────────────\n    logOut: 'Log out',\n    search: 'Search',\n\n    // ── UrlUploader ───────────────────────────────────────────\n    enterFileUrl: 'Enter file url',\n    fetch: 'Fetch',\n\n    // ── CameraUploader ────────────────────────────────────────\n    capture: 'Capture',\n    switchToCamera: 'switch to {{side}}',\n    addImage: 'Add Image',\n\n    // ── Camera sides ──────────────────────────────────────────\n    front: 'front',\n    back: 'back',\n\n    // ── Powered by ────────────────────────────────────────────\n    poweredBy: 'Powered by',\n\n    // ── Errors & Warnings ───────────────────────────────────\n    multipleFilesNotAllowed: 'Multiple file uploads are not allowed',\n    failedToGetUploadUrl: 'Failed to get upload URL',\n    statusError: 'Status: {{status}} ({{statusText}}). Details: {{details}}',\n    networkErrorDuringUpload:\n        'Network error during upload - Status: {{status}} ({{statusText}})',\n    missingRequiredConfiguration: 'Missing required configuration: {{missing}}',\n    invalidProvider:\n        'Invalid provider: {{provider}}. Valid options: {{validOptions}}',\n    invalidTokenEndpoint:\n        'Invalid tokenEndpoint URL: {{tokenEndpoint}} {{error}}',\n    maxFileSizeMustBeGreater: 'maxFileSize must be greater than 0',\n    invalidAcceptFormat:\n        'Invalid accept format: {{accept}}. Use MIME types, */*, * or extensions (like .fbx)',\n\n    unauthorizedAccess: 'Unauthorized access to Provider',\n    presignedUrlInvalid: 'Presigned URL has expired or is invalid',\n    temporaryCredentialsInvalid: 'Temporary credentials are no longer valid',\n    corsMisconfigured: 'CORS configuration prevents file upload',\n    fileTooLarge: 'File exceeds maximum size limit',\n    invalidFileType: 'File type is not allowed',\n    storageQuotaExceeded: 'Storage quota has been exceeded',\n    signedUrlGenerationFailed: 'Failed to generate signed upload URL',\n    uploadFailedWithCode: 'Upload failed with error code: {{code}}',\n    uploadFailed: 'Upload failed: {{message}}',\n\n    // Dropbox-specific\n    dropboxSessionExpired:\n        'Your Dropbox session has expired. Please re-authenticate to continue.',\n    dropboxMissingPermissions:\n        'Your Dropbox app is missing required permissions. Please add the following scopes in the Dropbox Developer Console: files.metadata.read, account_info.read',\n    failedToRefreshExpiredToken: 'Failed to refresh expired token',\n\n    // Upup UI messages\n    allowedLimitSurpassed: 'Allowed limit has been surpassed!',\n    fileUnsupportedType: '{{name}} has an unsupported type!',\n    fileTooLargeName: '{{name}} is larger than {{size}} {{unit}}!',\n    filePreviouslySelected: '{{name}} has previously been selected',\n    fileWithUrlPreviouslySelected:\n        'A file with this url: {{url}} has previously been selected',\n    errorCompressingFile: 'Error compressing {{name}}',\n\n    // Integration / Auth errors\n    clientIdRequired: 'Client ID is required...',\n    popupBlocked: 'Popup blocked',\n    dropboxClientIdMissing: 'Dropbox clientId missing',\n    dropboxAuthFailed: 'Dropbox authentication failed',\n    genericErrorDetails: 'Error: {{details}}',\n    errorProcessingFiles: 'Error processing files: {{message}}',\n    errorSelectingFolder: 'Error selecting folder: {{message}}',\n    graphClientNotInitialized: 'Graph client not initialized',\n    dropboxNoAccessToken: 'No access token provided for Dropbox download',\n\n    // MSAL / OneDrive messages\n    silentTokenAcquisitionFailed:\n        'Silent token acquisition failed: {{details}}',\n    msalInitializationFailed: 'MSAL initialization failed: {{details}}',\n    silentTokenAcquisitionProceeding:\n        'Silent token acquisition failed, proceeding with interactive login{{details}}',\n    signInFailed: 'Sign-in failed: {{message}}',\n    handleSignInFailed: 'Handle sign-in failed: {{message}}',\n    signOutFailed: 'Sign-out failed: {{message}}',\n}\n","import type { Translations } from './types'\n\n/**\n * Interpolate `{{key}}` placeholders in a translation string.\n *\n * @example\n * t('Upload {{count}} files', { count: 3 })\n * // → \"Upload 3 files\"\n */\nexport function t(\n    template: string,\n    values?: Record<string, string | number>,\n): string {\n    if (!values) return template\n    return template.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key: string) =>\n        String(values[key] ?? `{{${key}}}`),\n    )\n}\n\n/**\n * Pick the correct plural form for a translation key.\n *\n * Given a base key (e.g. `\"uploadFiles\"`) and a count, this returns\n * the `_one` variant when count === 1 and `_other` otherwise.\n *\n * @example\n * plural(translations, 'uploadFiles', 3)\n * // → translations.uploadFiles_other  (\"Upload {{count}} files\")\n */\nexport function plural(\n    translations: Translations,\n    baseKey: string,\n    count: number,\n): string {\n    const suffix = count === 1 ? '_one' : '_other'\n    const key = `${baseKey}${suffix}` as keyof Translations\n    return (\n        translations[key] ?? translations[baseKey as keyof Translations] ?? ''\n    )\n}\n\n/**\n * Deep-merge a partial translations override onto a base locale.\n * Only top-level keys are merged (the object is flat by design).\n */\nexport function mergeTranslations(\n    base: Translations,\n    overrides?: Partial<Translations>,\n): Translations {\n    if (!overrides) return base\n    return { ...base, ...overrides }\n}\n","import React from 'react'\nimport { TbLoader } from 'react-icons/tb'\n\nexport default function DefaultLoaderIcon() {\n    return (\n        <TbLoader className=\"upup-animate-spin upup-text-3xl upup-text-[#6D6D6D]\" />\n    )\n}\n","import React, {\n    ComponentType,\n    memo,\n    useCallback,\n    useEffect,\n    useMemo,\n    useRef,\n    useState,\n} from 'react'\nimport { FileWithParams } from '../../shared/types'\nimport { useRootContext } from '../context/RootContext'\nimport {\n    getFilerobotTheme,\n    getImageEditorCssOverrides,\n} from '../lib/imageEditorHelpers'\nimport { cn } from '../lib/tailwind'\n\ntype Props = {\n    file: FileWithParams\n    onClose: () => void\n    onSave: (editedImageData: string, mimeType?: string) => void\n}\n\n/**\n * Filerobot's onBeforeSave / onSave callback signature.\n */\ntype FilerobotImageState = {\n    imageBase64?: string\n    fullName?: string\n    mimeType?: string\n    width?: number\n    height?: number\n}\n\ntype FilerobotDesignState = Record<string, unknown>\n\ntype FilerobotEditorProps = {\n    source: string\n    savingPixelRatio?: number\n    previewPixelRatio?: number\n    onSave?: (\n        imageData: FilerobotImageState,\n        designState: FilerobotDesignState,\n    ) => void\n    onClose?: () => void\n    onBeforeSave?: (imageData: FilerobotImageState) => boolean | void\n    annotationsCommon?: Record<string, unknown>\n    Rotate?: Record<string, unknown>\n    Crop?: Record<string, unknown>\n    tabsIds?: unknown[]\n    defaultTabId?: unknown\n    defaultToolId?: unknown\n    [key: string]: unknown\n}\n\n/**\n * Inline image editor that overlays on top of the uploader container,\n * giving an \"edit in place\" experience similar to Uppy.\n *\n * Unlike ImageEditorModal, this does NOT use a portal or fixed positioning.\n * It renders as an absolutely positioned overlay inside the uploader's\n * <section>, covering the file list and other UI underneath.\n */\nexport default memo(function ImageEditorInline(props: Props) {\n    const { file, onClose, onSave } = props\n    const {\n        props: { dark, imageEditor: editorConfig },\n    } = useRootContext()\n\n    const containerRef = useRef<HTMLDivElement>(null)\n\n    // Lazy-loaded editor component + TABS/TOOLS constants\n    const [EditorComponent, setEditorComponent] =\n        useState<ComponentType<FilerobotEditorProps> | null>(null)\n    const [editorConstants, setEditorConstants] = useState<{\n        TABS: Record<string, unknown>\n        TOOLS: Record<string, unknown>\n    } | null>(null)\n    const [loadError, setLoadError] = useState<string | null>(null)\n\n    // StyleSheetManager from styled-components to filter custom props\n    const [StyleSheetMgr, setStyleSheetMgr] = useState<ComponentType<{\n        shouldForwardProp?: (prop: string) => boolean\n        children: React.ReactNode\n    }> | null>(null)\n\n    // Dynamically import react-filerobot-image-editor (browser only)\n    useEffect(() => {\n        if (typeof window === 'undefined') return\n\n        let cancelled = false\n        ;(async () => {\n            try {\n                const [mod, scMod] = await Promise.all([\n                    import('react-filerobot-image-editor'),\n                    import('styled-components').catch(() => null),\n                ])\n                if (cancelled) return\n                setEditorComponent(\n                    () => mod.default as ComponentType<FilerobotEditorProps>,\n                )\n                setEditorConstants({\n                    TABS: (mod as Record<string, unknown>).TABS as Record<\n                        string,\n                        unknown\n                    >,\n                    TOOLS: (mod as Record<string, unknown>).TOOLS as Record<\n                        string,\n                        unknown\n                    >,\n                })\n                if (scMod?.StyleSheetManager) {\n                    setStyleSheetMgr(\n                        () =>\n                            scMod.StyleSheetManager as ComponentType<{\n                                shouldForwardProp?: (prop: string) => boolean\n                                children: React.ReactNode\n                            }>,\n                    )\n                }\n            } catch {\n                if (cancelled) return\n                setLoadError(\n                    'Image editor failed to load. Make sure \"react-filerobot-image-editor\" is installed.',\n                )\n            }\n        })()\n\n        return () => {\n            cancelled = true\n        }\n    }, [])\n\n    // Close on ESC\n    const handleKeyDown = useCallback(\n        (e: React.KeyboardEvent) => {\n            if (e.key === 'Escape') {\n                e.stopPropagation()\n                onClose()\n            }\n        },\n        [onClose],\n    )\n\n    // Filerobot onSave handler\n    const handleEditorSave = useCallback(\n        (imageData: FilerobotImageState) => {\n            if (!imageData.imageBase64) return\n            const dataURL = imageData.imageBase64.startsWith('data:')\n                ? imageData.imageBase64\n                : `data:${imageData.mimeType || file.type};base64,${\n                      imageData.imageBase64\n                  }`\n            onSave(dataURL, imageData.mimeType)\n        },\n        [file.type, onSave],\n    )\n\n    // Filter styled-components custom props to avoid React 19 warnings\n    const shouldForwardProp = useCallback(\n        (prop: string) => !FILEROBOT_CUSTOM_PROPS.has(prop),\n        [],\n    )\n\n    // Build Filerobot tabs from config\n    const resolvedTabs = editorConstants?.TABS\n        ? editorConfig.tabs?.map(\n              tab =>\n                  (editorConstants.TABS as Record<string, unknown>)[\n                      tab.toUpperCase()\n                  ] ?? tab,\n          )\n        : undefined\n\n    const filerobotTheme = useMemo(() => getFilerobotTheme(dark), [dark])\n    const editorCssOverrides = useMemo(\n        () => getImageEditorCssOverrides(dark),\n        [dark],\n    )\n\n    return (\n        <div\n            ref={containerRef}\n            role=\"region\"\n            aria-label={`Editing image: ${file.name}`}\n            tabIndex={-1}\n            className={cn(\n                'upup-absolute upup-inset-0 upup-z-[9999] upup-flex upup-flex-col upup-overflow-hidden',\n                dark ? 'upup-bg-[#232323]' : 'upup-bg-white',\n            )}\n            onKeyDown={handleKeyDown}\n            data-upup-theme={dark ? 'dark' : 'light'}\n        >\n            {/* Theme fallback overrides for hardcoded library values */}\n            {editorCssOverrides && (\n                <style\n                    dangerouslySetInnerHTML={{ __html: editorCssOverrides }}\n                />\n            )}\n\n            {/* Header — Cancel / Title / (Save is handled by Filerobot) */}\n            <div\n                className={cn(\n                    'upup-flex upup-items-center upup-justify-between upup-border-b upup-px-4 upup-py-2',\n                    dark\n                        ? 'upup-border-gray-700 upup-bg-[#232323]'\n                        : 'upup-border-gray-200 upup-bg-white',\n                )}\n            >\n                <button\n                    type=\"button\"\n                    className={cn(\n                        'upup-text-sm upup-font-semibold upup-transition-colors',\n                        dark\n                            ? 'upup-text-[#30C5F7] hover:upup-text-[#6DD8FB]'\n                            : 'upup-text-blue-600 hover:upup-text-blue-800',\n                    )}\n                    onClick={onClose}\n                >\n                    Cancel\n                </button>\n                <span\n                    className={cn(\n                        'upup-text-sm upup-font-semibold',\n                        dark ? 'upup-text-gray-100' : 'upup-text-gray-900',\n                    )}\n                >\n                    Editing {file.name}\n                </span>\n                {/* Save is handled by Filerobot's built-in save button */}\n                <span className=\"upup-w-14\" />\n            </div>\n\n            {/* Editor body */}\n            <div className=\"upup-relative upup-flex-1 upup-overflow-hidden\">\n                {loadError && (\n                    <div className=\"upup-flex upup-h-full upup-items-center upup-justify-center upup-p-8\">\n                        <p\n                            className={cn(\n                                'upup-text-center upup-text-sm',\n                                dark\n                                    ? 'upup-text-red-400'\n                                    : 'upup-text-red-600',\n                            )}\n                        >\n                            {loadError}\n                        </p>\n                    </div>\n                )}\n\n                {!EditorComponent && !loadError && (\n                    <div className=\"upup-flex upup-h-full upup-items-center upup-justify-center\">\n                        <div\n                            className={cn(\n                                'upup-h-8 upup-w-8 upup-animate-spin upup-rounded-full upup-border-2 upup-border-t-transparent',\n                                dark\n                                    ? 'upup-border-gray-500'\n                                    : 'upup-border-gray-300',\n                            )}\n                        />\n                    </div>\n                )}\n\n                {EditorComponent && !loadError && (\n                    <EditorWrapper\n                        StyleSheetMgr={StyleSheetMgr}\n                        shouldForwardProp={shouldForwardProp}\n                    >\n                        <EditorComponent\n                            source={file.url}\n                            onSave={handleEditorSave}\n                            onClose={onClose}\n                            savingPixelRatio={4}\n                            previewPixelRatio={4}\n                            theme={filerobotTheme}\n                            defaultTabId={\n                                editorConstants?.TABS\n                                    ? (\n                                          editorConstants.TABS as Record<\n                                              string,\n                                              unknown\n                                          >\n                                      ).ADJUST\n                                    : undefined\n                            }\n                            tabsIds={resolvedTabs}\n                            onBeforeSave={() => false}\n                        />\n                    </EditorWrapper>\n                )}\n            </div>\n        </div>\n    )\n})\n\n/**\n * Custom props that filerobot-image-editor's styled-components leak to the DOM.\n */\nconst FILEROBOT_CUSTOM_PROPS = new Set([\n    'active',\n    'noMargin',\n    'showBackButton',\n    'isPhoneScreen',\n    'showTabsDrawer',\n    'hasChildren',\n    'isAccordion',\n])\n\n/**\n * Wraps children with styled-components' StyleSheetManager (when available)\n * to prevent custom props from leaking to the DOM in React 19+.\n */\nfunction EditorWrapper({\n    children,\n    StyleSheetMgr,\n    shouldForwardProp,\n}: {\n    children: React.ReactNode\n    StyleSheetMgr: ComponentType<{\n        shouldForwardProp?: (prop: string) => boolean\n        children: React.ReactNode\n    }> | null\n    shouldForwardProp: (prop: string) => boolean\n}) {\n    if (StyleSheetMgr) {\n        return (\n            <StyleSheetMgr shouldForwardProp={shouldForwardProp}>\n                {children}\n            </StyleSheetMgr>\n        )\n    }\n    return <>{children}</>\n}\n","import {\n    createContext,\n    Dispatch,\n    RefObject,\n    SetStateAction,\n    useContext,\n} from 'react'\nimport {\n    DropboxConfigs,\n    FileWithParams,\n    GoogleDriveConfigs,\n    OneDriveConfigs,\n    ResolvedImageEditorOptions,\n    Translations,\n    UploadAdapter,\n    UpupUploaderProps,\n    UpupUploaderPropsIcons,\n} from '../../shared/types'\nimport { FilesProgressMap } from '../hooks/useRootProvider'\n\nexport enum UploadStatus {\n    PENDING = 'PENDING',\n    ONGOING = 'ONGOING',\n    PAUSED = 'PAUSED',\n    SUCCESSFUL = 'SUCCESSFUL',\n    FAILED = 'FAILED',\n}\n\ntype ContextUpload = {\n    uploadStatus: UploadStatus\n    uploadError?: string\n    setUploadStatus: Dispatch<SetStateAction<UploadStatus>>\n    totalProgress: number\n    filesProgressMap: FilesProgressMap\n    proceedUpload: () => Promise<FileWithParams[] | undefined>\n    /** Current upload speed in bytes/sec (rolling average) */\n    uploadSpeed: number\n    /** Estimated seconds remaining */\n    uploadEta: number\n    /** Total bytes uploaded so far across all files */\n    uploadedBytes: number\n    /** Total bytes to upload across all files */\n    totalBytes: number\n}\n\ntype ContextProps = Required<\n    Pick<\n        UpupUploaderProps,\n        | 'uploadAdapters'\n        | 'accept'\n        | 'limit'\n        | 'isProcessing'\n        | 'allowPreview'\n        | 'mini'\n        | 'onFileClick'\n        | 'onIntegrationClick'\n        | 'onFilesDragOver'\n        | 'onFilesDragLeave'\n        | 'onFilesDrop'\n        | 'onError'\n        | 'dark'\n        | 'classNames'\n        | 'icons'\n        | 'showSelectFolderButton'\n    >\n> &\n    Pick<UpupUploaderProps, 'maxFileSize' | 'maxRetries' | 'resumable'> & {\n        multiple: boolean\n        icons: Required<UpupUploaderPropsIcons>\n        imageEditor: ResolvedImageEditorOptions\n    }\n\nexport interface IRootContext {\n    inputRef: RefObject<HTMLInputElement | null>\n    activeAdapter?: UploadAdapter\n    setActiveAdapter: Dispatch<SetStateAction<UploadAdapter | undefined>>\n\n    translations: Translations\n\n    files: Map<string, FileWithParams>\n    setFiles: (newFiles: File[]) => void\n    dynamicallyReplaceFiles: (files: File[] | FileWithParams[]) => void\n    resetState: () => void\n    dynamicUpload: (\n        files: File[] | FileWithParams[],\n    ) => Promise<FileWithParams[] | undefined>\n    isAddingMore: boolean\n    setIsAddingMore: Dispatch<SetStateAction<boolean>>\n\n    handleFileRemove: (fileId: string) => void\n    handleDone: () => void\n    handleCancel: () => void\n    handlePause: () => void\n    handleResume: () => void\n\n    editingFile: FileWithParams | null\n    openImageEditor: (file: FileWithParams) => void\n    closeImageEditor: () => void\n    saveImageEdit: (editedImageData: string, mimeType?: string) => void\n    replaceFile: (fileId: string, newFile: FileWithParams) => void\n\n    oneDriveConfigs?: OneDriveConfigs\n    googleDriveConfigs?: GoogleDriveConfigs\n    dropboxConfigs?: DropboxConfigs\n    upload: ContextUpload\n    props: ContextProps\n}\n\nconst RootContext = createContext<IRootContext>({\n    props: {},\n    files: new Map(),\n} as IRootContext)\n\nexport function useRootContext() {\n    const contextValue = useContext(RootContext)\n    return contextValue\n}\n\nexport default RootContext\n","import pako from 'pako'\nimport { b64EncodeUnicode } from '../../shared/lib/encoder'\nimport { FileWithParams, UpupUploaderProps } from '../../shared/types'\n\n/**\n * @param bytes assign keyword depend on size\n */\nexport const bytesToSize = (bytes: number) => {\n    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']\n    if (bytes === 0) return '0 Byte'\n    const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)).toString())\n    return Math.round(bytes / Math.pow(1024, i)) + ' ' + sizes[i]\n}\n\n/**\n * @param size\n * @param unit\n */\nexport const sizeToBytes = (\n    size: number,\n    unit: 'B' | 'KB' | 'MB' | 'GB' | 'TB' | 'PB' | 'EB' | 'ZB' | 'YB' = 'B',\n) => {\n    const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']\n    const i = sizes.indexOf(unit)\n    return size * Math.pow(1024, i)\n}\n\n/**\n * @param file\n * @param maxFileSize\n */\nexport function checkFileSize(\n    file: File,\n    maxFileSize: UpupUploaderProps['maxFileSize'],\n) {\n    const maxBytes = sizeToBytes(maxFileSize!.size, maxFileSize!.unit)\n    if (file.size <= maxBytes) return true\n    return false\n}\n\nexport const fileAppendParams = (file: File) => {\n    const rel =\n        (file as any).relativePath ||\n        (file as any).webkitRelativePath ||\n        file.name\n    Object.assign(file, {\n        id: (file as any).id || b64EncodeUnicode(rel),\n        url: (file as any).url || URL.createObjectURL(file),\n    })\n\n    return file as FileWithParams\n}\n\n/**\n * Revokes a blob URL to free memory. Safe to call on any file URL.\n * @param file - FileWithParams object containing the URL to revoke\n */\nexport const revokeFileUrl = (file: FileWithParams) => {\n    if (file.url?.startsWith('blob:')) {\n        URL.revokeObjectURL(file.url)\n    }\n}\n\nexport async function compressFile(oldFile: FileWithParams) {\n    const buffer = await oldFile.arrayBuffer()\n\n    const compressed = new File([pako.gzip(buffer)], oldFile.name + '.gz', {\n        type: 'application/octet-stream',\n        lastModified: oldFile.lastModified,\n    })\n    const newFileWithParams = fileAppendParams(compressed)\n    newFileWithParams.id = oldFile.id\n    newFileWithParams.thumbnail = oldFile.thumbnail\n    newFileWithParams.fileHash = oldFile.fileHash\n    newFileWithParams.key = oldFile.key\n\n    // Revoke old blob URL to prevent memory leak\n    revokeFileUrl(oldFile)\n\n    return newFileWithParams\n}\n\nexport function searchDriveFiles<\n    T extends {\n        name: string\n    },\n>(\n    files: T[],\n    searchTerm: string,\n    options: {\n        caseSensitive?: boolean\n        exactMatch?: boolean\n        maxResults?: number\n    } = {},\n): T[] {\n    const {\n        caseSensitive = false,\n        exactMatch = false,\n        maxResults = 100,\n    } = options\n\n    if (!searchTerm) return files?.slice(0, maxResults)\n\n    let searchString = searchTerm\n    let fileNames: string[]\n\n    if (!caseSensitive) {\n        searchString = searchTerm.toLowerCase()\n        fileNames = files.map(file => file.name.toLowerCase())\n    } else {\n        fileNames = files.map(file => file.name)\n    }\n\n    return files\n        .filter((_file, index) => {\n            // Check if file name matches search term\n            return exactMatch\n                ? fileNames[index] === searchString\n                : fileNames[index].includes(searchString)\n        })\n        .slice(0, maxResults)\n}\n\nexport function fileGetIsImage(fileType: string) {\n    return fileType.startsWith('image/')\n}\n\n/**\n * Maximum file size (in bytes) for which text-based preview is allowed.\n * Files exceeding this threshold will show a static icon instead of rendering content,\n * preventing the browser from freezing on large text files (e.g. 3MB+ JSON).\n */\nexport const PREVIEW_MAX_TEXT_SIZE = 512 * 1024 // 512 KB\n\n/**\n * Maximum number of characters to render in the preview portal for text files.\n * Content beyond this limit is truncated with an indicator.\n */\nexport const PREVIEW_TEXT_TRUNCATE_LENGTH = 100_000 // ~100 KB of text\n\n/**\n * Determines whether a file is a text-based file that could be previewed as text.\n */\nexport function fileGetIsText(fileType: string, fileName: string): boolean {\n    if (!fileType) return false\n    if (fileType.startsWith('text/')) return true\n    const lower = fileName.toLowerCase()\n    return (\n        lower.endsWith('.txt') ||\n        lower.endsWith('.md') ||\n        lower.endsWith('.json') ||\n        lower.endsWith('.csv') ||\n        lower.endsWith('.log') ||\n        lower.endsWith('.js') ||\n        lower.endsWith('.ts') ||\n        lower.endsWith('.css') ||\n        lower.endsWith('.html')\n    )\n}\n\n/**\n * Returns true if a text file is small enough to safely preview inline.\n */\nexport function fileCanPreviewText(\n    fileType: string,\n    fileName: string,\n    fileSize: number | undefined,\n): boolean {\n    if (!fileGetIsText(fileType, fileName)) return false\n    if (fileSize === undefined) return true // unknown size, allow preview\n    return fileSize <= PREVIEW_MAX_TEXT_SIZE\n}\n\nexport function fileGetExtension(fileType: string, fileName: string) {\n    if (!fileType) {\n        return fileName.split('.').pop()?.toLowerCase() || ''\n    }\n    const typeSplit = fileType.split('/')\n    const nameSplit = fileName.split('.')\n    const lastNamePart = nameSplit[nameSplit.length - 1]?.toLowerCase() || ''\n    if (!typeSplit[1]) {\n        return lastNamePart\n    }\n    if (typeSplit[1].includes('.')) {\n        return lastNamePart\n    }\n    return typeSplit[1].toLowerCase()\n}\n\nexport function fileIs3D(ext: string) {\n    const threeDExtensions = [\n        '3ds',\n        '3dm',\n        'blend',\n        'dxf',\n        'dwg',\n        'c4d',\n        'ma',\n        'mb',\n        'ply',\n        'stl',\n        'fbx',\n        'obj',\n        'dae',\n        'gltf',\n        'glb',\n        'm3',\n    ]\n    return threeDExtensions.includes(ext.toLowerCase())\n}\n","export function b64EncodeUnicode(str: string): string {\n    return btoa(\n        encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (_, p1) =>\n            String.fromCharCode(parseInt(p1, 16)),\n        ),\n    )\n}\n","import { FileWithParams, ImageEditorOptions } from '../../shared/types'\nimport { revokeFileUrl } from './file'\n\ntype FilerobotTheme = {\n    palette: Record<string, string>\n    typography: {\n        fontFamily: string\n    }\n}\n\n/**\n * Convert a data-URL (base64 or plain) string to a Blob.\n * Works with any MIME type encoded as `data:<mime>;base64,<data>`.\n */\nexport function dataURLtoBlob(dataURL: string): Blob {\n    const [header, base64Data] = dataURL.split(',')\n    const mime = header.match(/:(.*?);/)?.[1] ?? 'application/octet-stream'\n    const binary = atob(base64Data)\n    const bytes = new Uint8Array(binary.length)\n    for (let i = 0; i < binary.length; i++) {\n        bytes[i] = binary.charCodeAt(i)\n    }\n    return new Blob([bytes], { type: mime })\n}\n\n/**\n * Create a new FileWithParams from a Blob, preserving the identity (`id`)\n * of the original file. A fresh blob URL is created for the new file.\n *\n * @param blob      The edited image blob.\n * @param original  The original FileWithParams being replaced.\n * @param output    Optional output settings (mimeType, quality, fileName).\n * @returns A new FileWithParams with the same `id` but updated content.\n */\nexport function blobToFileWithParams(\n    blob: Blob,\n    original: FileWithParams,\n    output?: ImageEditorOptions['output'],\n): FileWithParams {\n    const fileName = output?.fileName\n        ? output.fileName(original)\n        : original.name\n\n    const file = new File([blob], fileName, {\n        type: blob.type || original.type,\n        lastModified: Date.now(),\n    })\n\n    // Preserve file identity so the upload pipeline sees the same entry.\n    const fileWithParams = file as FileWithParams\n    fileWithParams.id = original.id\n    fileWithParams.url = URL.createObjectURL(file)\n    fileWithParams.key = original.key\n    fileWithParams.fileHash = original.fileHash\n    fileWithParams.thumbnail = original.thumbnail\n\n    return fileWithParams\n}\n\n/**\n * Replace a file in a Map<string, FileWithParams>, revoking the old blob URL\n * to prevent memory leaks.\n *\n * @param map     The current files map (not mutated — a new Map is returned).\n * @param fileId  The id of the file to replace.\n * @param newFile The replacement FileWithParams.\n * @returns A new Map with the replaced entry.\n */\nexport function revokeAndReplace(\n    map: Map<string, FileWithParams>,\n    fileId: string,\n    newFile: FileWithParams,\n): Map<string, FileWithParams> {\n    const oldFile = map.get(fileId)\n    if (oldFile) {\n        revokeFileUrl(oldFile)\n    }\n\n    const next = new Map(map)\n\n    next.set(fileId, newFile)\n    return next\n}\n\n/**\n * Shared Filerobot theme used by both inline and modal editors.\n * Includes extra palette tokens because some editor buttons fall back to\n * incomplete defaults when light-mode tokens are omitted.\n */\nexport function getFilerobotTheme(dark: boolean): FilerobotTheme {\n    return dark\n        ? {\n              palette: {\n                  'bg-secondary': '#1a1a1a',\n                  'bg-primary': '#232323',\n                  'bg-primary-active': '#2d2d2d',\n                  'bg-stateless': '#2d2d2d',\n                  'bg-hover': '#3a3a3a',\n                  'bg-active': '#3a3a3a',\n                  'accent-primary': '#30C5F7',\n                  'accent-primary-hover': '#6DD8FB',\n                  'accent-primary-active': '#6DD8FB',\n                  accent_1_2_opacity: 'rgba(48, 197, 247, 0.12)',\n                  'accent-stateless': '#30C5F7',\n                  'icon-primary': '#ffffff',\n                  'icons-primary': '#ffffff',\n                  'icons-secondary': '#d1d5db',\n                  'icons-placeholder': '#9ca3af',\n                  'borders-secondary': '#374151',\n                  'borders-primary': '#4b5563',\n                  'borders-strong': '#6b7280',\n                  'borders-disabled': '#6b7280',\n                  'borders-button': '#4b5563',\n                  'light-shadow': 'rgba(0, 0, 0, 0.4)',\n                  warning: '#f59e0b',\n                  'txt-primary': '#ffffff',\n                  'txt-secondary': '#d1d5db',\n                  'txt-primary-invert': '#232323',\n                  'txt-secondary-invert': '#1a1a1a',\n                  'btn-primary-text': '#ffffff',\n                  'btn-secondary-text': '#d1d5db',\n                  'btn-disabled-text': '#6b7280',\n                  'link-stateless': '#d1d5db',\n              },\n              typography: {\n                  fontFamily: 'inherit',\n              },\n          }\n        : {\n              palette: {\n                  'bg-secondary': '#f9fafb',\n                  'bg-primary': '#ffffff',\n                  'bg-primary-active': '#f3f4f6',\n                  'bg-stateless': '#ffffff',\n                  'bg-hover': '#eff6ff',\n                  'bg-active': '#dbeafe',\n                  'accent-primary': '#2563eb',\n                  'accent-primary-hover': '#1d4ed8',\n                  'accent-primary-active': '#1e40af',\n                  accent_1_2_opacity: 'rgba(37, 99, 235, 0.12)',\n                  'accent-stateless': '#2563eb',\n                  'icon-primary': '#111827',\n                  'icons-primary': '#111827',\n                  'icons-secondary': '#4b5563',\n                  'icons-placeholder': '#9ca3af',\n                  'borders-secondary': '#e5e7eb',\n                  'borders-primary': '#d1d5db',\n                  'borders-strong': '#9ca3af',\n                  'borders-disabled': '#d1d5db',\n                  'borders-button': '#2563eb',\n                  'light-shadow': 'rgba(15, 23, 42, 0.12)',\n                  warning: '#d97706',\n                  'txt-primary': '#111827',\n                  'txt-secondary': '#4b5563',\n                  'txt-primary-invert': '#ffffff',\n                  'txt-secondary-invert': '#f9fafb',\n                  'btn-primary-text': '#ffffff',\n                  'btn-secondary-text': '#1d4ed8',\n                  'btn-disabled-text': '#93c5fd',\n                  'link-stateless': '#2563eb',\n              },\n              typography: {\n                  fontFamily: 'inherit',\n              },\n          }\n}\n\n/**\n * CSS fallbacks for hardcoded editor/library values and button states that do\n * not consistently respect the provided theme palette.\n */\nexport function getImageEditorCssOverrides(dark: boolean): string {\n    return dark\n        ? `\n        /* Input background & border overrides (hardcoded in @scaleflex/ui) */\n        [data-upup-theme='dark'] .SfxInput-Base {\n            background-color: #2d2d2d !important;\n            border-color: #4b5563 !important;\n        }\n        [data-upup-theme='dark'] .SfxInput-Base:focus-within {\n            background-color: #353535 !important;\n            border-color: #6b7280 !important;\n        }\n        [data-upup-theme='dark'] .SfxInput-Base:hover {\n            background-color: #353535 !important;\n        }\n        /* Carousel gradient arrow overrides (hardcoded white in FIE) */\n        [data-upup-theme='dark'] .FIE_carousel-prev-button {\n            background: linear-gradient(\n                90deg,\n                #232323 1.56%,\n                rgba(35, 35, 35, 0.89) 52.4%,\n                rgba(35, 35, 35, 0.53) 76.04%,\n                rgba(35, 35, 35, 0) 100%\n            ) !important;\n        }\n        [data-upup-theme='dark'] .FIE_carousel-next-button {\n            background: linear-gradient(\n                270deg,\n                #232323 1.56%,\n                rgba(35, 35, 35, 0.89) 52.4%,\n                rgba(35, 35, 35, 0.53) 76.04%,\n                rgba(35, 35, 35, 0) 100%\n            ) !important;\n        }\n        [data-upup-theme='dark'] .FIE_topbar-save-button,\n        [data-upup-theme='dark'] .FIE_watermark-add-button {\n            background-color: #30c5f7 !important;\n            color: #ffffff !important;\n            border: none !important;\n        }\n        [data-upup-theme='dark'] .FIE_topbar-save-button .SfxButton-Label,\n        [data-upup-theme='dark'] .FIE_watermark-add-button .SfxButton-Label {\n            color: #ffffff !important;\n            opacity: 1 !important;\n        }\n        [data-upup-theme='dark'] .FIE_topbar-save-button:hover,\n        [data-upup-theme='dark'] .FIE_topbar-save-button:focus-visible,\n        [data-upup-theme='dark'] .FIE_watermark-add-button:hover,\n        [data-upup-theme='dark'] .FIE_watermark-add-button:focus-visible {\n            background-color: #6dd8fb !important;\n        }\n        [data-upup-theme='dark'] .FIE_topbar-save-button:active,\n        [data-upup-theme='dark'] .FIE_watermark-add-button:active {\n            background-color: #27b1df !important;\n        }\n        [data-upup-theme='dark'] .FIE_topbar-save-button:disabled,\n        [data-upup-theme='dark'] .FIE_watermark-add-button:disabled {\n            color: #9ca3af !important;\n            background-color: rgba(48, 197, 247, 0.12) !important;\n            border: 1px solid #4b5563 !important;\n        }\n        [data-upup-theme='dark'] .FIE_topbar-save-button:disabled .SfxButton-Label,\n        [data-upup-theme='dark'] .FIE_watermark-add-button:disabled .SfxButton-Label {\n            color: #9ca3af !important;\n            opacity: 1 !important;\n        }\n        `\n        : `\n        [data-upup-theme='light'] .FIE_topbar-save-button,\n        [data-upup-theme='light'] .FIE_watermark-add-button {\n            background-color: #2563eb !important;\n            color: #ffffff !important;\n            border: 1px solid #2563eb !important;\n        }\n        [data-upup-theme='light'] .FIE_topbar-save-button .SfxButton-Label,\n        [data-upup-theme='light'] .FIE_watermark-add-button .SfxButton-Label {\n            color: #ffffff !important;\n            opacity: 1 !important;\n        }\n        [data-upup-theme='light'] .FIE_topbar-save-button:hover,\n        [data-upup-theme='light'] .FIE_topbar-save-button:focus-visible,\n        [data-upup-theme='light'] .FIE_watermark-add-button:hover,\n        [data-upup-theme='light'] .FIE_watermark-add-button:focus-visible {\n            background-color: #1d4ed8 !important;\n            border-color: #1d4ed8 !important;\n        }\n        [data-upup-theme='light'] .FIE_topbar-save-button:active,\n        [data-upup-theme='light'] .FIE_watermark-add-button:active {\n            background-color: #1e40af !important;\n            border-color: #1e40af !important;\n        }\n        [data-upup-theme='light'] .FIE_topbar-save-button:disabled,\n        [data-upup-theme='light'] .FIE_watermark-add-button:disabled {\n            color: #93c5fd !important;\n            background-color: rgba(37, 99, 235, 0.12) !important;\n            border: 1px solid #bfdbfe !important;\n        }\n        [data-upup-theme='light'] .FIE_topbar-save-button:disabled .SfxButton-Label,\n        [data-upup-theme='light'] .FIE_watermark-add-button:disabled .SfxButton-Label {\n            color: #93c5fd !important;\n            opacity: 1 !important;\n        }\n        `\n}\n","import { ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n    return twMerge(clsx(inputs))\n}\n","import React, {\n    ComponentType,\n    memo,\n    useCallback,\n    useEffect,\n    useMemo,\n    useRef,\n    useState,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { FileWithParams } from '../../shared/types'\nimport { useRootContext } from '../context/RootContext'\nimport {\n    getFilerobotTheme,\n    getImageEditorCssOverrides,\n} from '../lib/imageEditorHelpers'\nimport { cn } from '../lib/tailwind'\n\ntype Props = {\n    file: FileWithParams\n    onClose: () => void\n    onSave: (editedImageData: string, mimeType?: string) => void\n}\n\n/**\n * Filerobot's onBeforeSave / onSave callback signature.\n * We only use the imageData.imageBase64 field.\n */\ntype FilerobotImageState = {\n    imageBase64?: string\n    fullName?: string\n    mimeType?: string\n    width?: number\n    height?: number\n}\n\ntype FilerobotDesignState = Record<string, unknown>\n\n/**\n * The props shape of the default-exported <FilerobotImageEditor> component.\n * We only type the subset we use to keep this lightweight.\n */\ntype FilerobotEditorProps = {\n    source: string\n    savingPixelRatio?: number\n    previewPixelRatio?: number\n    onSave?: (\n        imageData: FilerobotImageState,\n        designState: FilerobotDesignState,\n    ) => void\n    onClose?: () => void\n    onBeforeSave?: (imageData: FilerobotImageState) => boolean | void\n    annotationsCommon?: Record<string, unknown>\n    Rotate?: Record<string, unknown>\n    Crop?: Record<string, unknown>\n    tabsIds?: unknown[]\n    defaultTabId?: unknown\n    defaultToolId?: unknown\n    [key: string]: unknown\n}\n\n/**\n * Accessible modal shell for the image editor.\n * Lazy-loads `react-filerobot-image-editor` at runtime so the dependency\n * is never bundled into the core entry point.\n *\n * - Focus trap: keeps focus inside the modal while open.\n * - ESC closes.\n * - Restores focus to the triggering element on close.\n * - aria-label / role=\"dialog\".\n */\nexport default memo(function ImageEditorModal(props: Props) {\n    const { file, onClose, onSave } = props\n    const {\n        props: { dark, imageEditor: editorConfig },\n    } = useRootContext()\n\n    const overlayRef = useRef<HTMLDivElement>(null)\n    const previousFocusRef = useRef<Element | null>(null)\n\n    // Lazy-loaded editor component + TABS/TOOLS constants\n    const [EditorComponent, setEditorComponent] =\n        useState<ComponentType<FilerobotEditorProps> | null>(null)\n    const [editorConstants, setEditorConstants] = useState<{\n        TABS: Record<string, unknown>\n        TOOLS: Record<string, unknown>\n    } | null>(null)\n    const [loadError, setLoadError] = useState<string | null>(null)\n\n    // StyleSheetManager from styled-components to filter custom props\n    // that filerobot passes to DOM elements (fixes React 19 warnings/errors).\n    const [StyleSheetMgr, setStyleSheetMgr] = useState<ComponentType<{\n        shouldForwardProp?: (prop: string) => boolean\n        children: React.ReactNode\n    }> | null>(null)\n\n    // Dynamically import react-filerobot-image-editor (browser only)\n    useEffect(() => {\n        if (typeof window === 'undefined') return\n\n        let cancelled = false\n        ;(async () => {\n            try {\n                const [mod, scMod] = await Promise.all([\n                    import('react-filerobot-image-editor'),\n                    import('styled-components').catch(() => null),\n                ])\n                if (cancelled) return\n                setEditorComponent(\n                    () => mod.default as ComponentType<FilerobotEditorProps>,\n                )\n                setEditorConstants({\n                    TABS: (mod as Record<string, unknown>).TABS as Record<\n                        string,\n                        unknown\n                    >,\n                    TOOLS: (mod as Record<string, unknown>).TOOLS as Record<\n                        string,\n                        unknown\n                    >,\n                })\n                if (scMod?.StyleSheetManager) {\n                    setStyleSheetMgr(\n                        () =>\n                            scMod.StyleSheetManager as ComponentType<{\n                                shouldForwardProp?: (prop: string) => boolean\n                                children: React.ReactNode\n                            }>,\n                    )\n                }\n            } catch {\n                if (cancelled) return\n                setLoadError(\n                    'Image editor failed to load. Make sure \"react-filerobot-image-editor\" is installed.',\n                )\n            }\n        })()\n\n        return () => {\n            cancelled = true\n        }\n    }, [])\n\n    // Capture the element that had focus before the modal opened\n    // and restore it when the modal closes.\n    useEffect(() => {\n        previousFocusRef.current = document.activeElement\n        return () => {\n            if (previousFocusRef.current instanceof HTMLElement) {\n                previousFocusRef.current.focus()\n            }\n        }\n    }, [])\n\n    // Auto-focus the overlay so keyboard events work immediately.\n    useEffect(() => {\n        overlayRef.current?.focus()\n    }, [])\n\n    // Close on ESC\n    const handleKeyDown = useCallback(\n        (e: React.KeyboardEvent) => {\n            if (e.key === 'Escape') {\n                e.stopPropagation()\n                onClose()\n            }\n\n            // Basic focus trap: Tab cycles within the modal.\n            if (e.key === 'Tab') {\n                const focusable =\n                    overlayRef.current?.querySelectorAll<HTMLElement>(\n                        'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])',\n                    )\n                if (!focusable || focusable.length === 0) return\n                const first = focusable[0]\n                const last = focusable[focusable.length - 1]\n\n                if (e.shiftKey) {\n                    if (document.activeElement === first) {\n                        e.preventDefault()\n                        last.focus()\n                    }\n                } else {\n                    if (document.activeElement === last) {\n                        e.preventDefault()\n                        first.focus()\n                    }\n                }\n            }\n        },\n        [onClose],\n    )\n\n    // Prevent clicks on the inner content from closing the modal\n    const handleContentClick = useCallback(\n        (e: React.MouseEvent) => e.stopPropagation(),\n        [],\n    )\n\n    // Filerobot onSave handler\n    const handleEditorSave = useCallback(\n        (imageData: FilerobotImageState) => {\n            if (!imageData.imageBase64) return\n            const dataURL = imageData.imageBase64.startsWith('data:')\n                ? imageData.imageBase64\n                : `data:${imageData.mimeType || file.type};base64,${\n                      imageData.imageBase64\n                  }`\n            onSave(dataURL, imageData.mimeType)\n        },\n        [file.type, onSave],\n    )\n\n    // Props that filerobot-image-editor's styled-components pass to DOM elements.\n    // Filter them out via StyleSheetManager to avoid React 19 warnings / errors.\n    const shouldForwardProp = useCallback(\n        (prop: string) => !FILEROBOT_CUSTOM_PROPS.has(prop),\n        [],\n    )\n\n    // Build Filerobot tabs from config\n    const resolvedTabs = editorConstants?.TABS\n        ? editorConfig.tabs?.map(\n              tab =>\n                  (editorConstants.TABS as Record<string, unknown>)[\n                      tab.toUpperCase()\n                  ] ?? tab,\n          )\n        : undefined\n\n    const filerobotTheme = useMemo(() => getFilerobotTheme(dark), [dark])\n    const editorCssOverrides = useMemo(\n        () => getImageEditorCssOverrides(dark),\n        [dark],\n    )\n\n    return createPortal(\n        <div className=\"upup-scope\">\n            <div\n                ref={overlayRef}\n                role=\"dialog\"\n                aria-modal=\"true\"\n                aria-label={`Edit image: ${file.name}`}\n                tabIndex={-1}\n                className=\"upup-fixed upup-inset-0 upup-z-[2147483647] upup-flex upup-items-center upup-justify-center upup-bg-black/60 upup-outline-none\"\n                onClick={onClose}\n                onKeyDown={handleKeyDown}\n            >\n                <div\n                    className={cn(\n                        'upup-relative upup-flex upup-h-[90vh] upup-w-[90vw] upup-max-w-5xl upup-flex-col upup-overflow-hidden upup-rounded-xl upup-shadow-2xl',\n                        dark ? 'upup-bg-[#232323]' : 'upup-bg-white',\n                    )}\n                    data-upup-theme={dark ? 'dark' : 'light'}\n                    onClick={handleContentClick}\n                >\n                    {editorCssOverrides && (\n                        <style\n                            dangerouslySetInnerHTML={{\n                                __html: editorCssOverrides,\n                            }}\n                        />\n                    )}\n\n                    {/* Header */}\n                    <div\n                        className={cn(\n                            'upup-flex upup-items-center upup-justify-between upup-border-b upup-px-4 upup-py-3',\n                            dark\n                                ? 'upup-border-gray-700 upup-text-gray-200'\n                                : 'upup-border-gray-200 upup-text-gray-800',\n                        )}\n                    >\n                        <h2 className=\"upup-text-sm upup-font-medium\">\n                            Edit image — {file.name}\n                        </h2>\n                        <button\n                            type=\"button\"\n                            aria-label=\"Close editor\"\n                            className={cn(\n                                'upup-flex upup-h-7 upup-w-7 upup-items-center upup-justify-center upup-rounded-full',\n                                'upup-text-lg upup-leading-none upup-transition-colors',\n                                dark\n                                    ? 'upup-text-gray-400 hover:upup-bg-gray-700 hover:upup-text-gray-200'\n                                    : 'upup-text-gray-500 hover:upup-bg-gray-100 hover:upup-text-gray-800',\n                            )}\n                            onClick={onClose}\n                        >\n                            ×\n                        </button>\n                    </div>\n\n                    {/* Editor body */}\n                    <div className=\"upup-relative upup-flex-1 upup-overflow-hidden\">\n                        {loadError && (\n                            <div className=\"upup-flex upup-h-full upup-items-center upup-justify-center upup-p-8\">\n                                <p\n                                    className={cn(\n                                        'upup-text-center upup-text-sm',\n                                        dark\n                                            ? 'upup-text-red-400'\n                                            : 'upup-text-red-600',\n                                    )}\n                                >\n                                    {loadError}\n                                </p>\n                            </div>\n                        )}\n\n                        {!EditorComponent && !loadError && (\n                            <div className=\"upup-flex upup-h-full upup-items-center upup-justify-center\">\n                                <div\n                                    className={cn(\n                                        'upup-h-8 upup-w-8 upup-animate-spin upup-rounded-full upup-border-2 upup-border-t-transparent',\n                                        dark\n                                            ? 'upup-border-gray-500'\n                                            : 'upup-border-gray-300',\n                                    )}\n                                />\n                            </div>\n                        )}\n\n                        {EditorComponent && !loadError && (\n                            <EditorWrapper\n                                StyleSheetMgr={StyleSheetMgr}\n                                shouldForwardProp={shouldForwardProp}\n                            >\n                                <EditorComponent\n                                    source={file.url}\n                                    onSave={handleEditorSave}\n                                    onClose={onClose}\n                                    savingPixelRatio={4}\n                                    previewPixelRatio={4}\n                                    theme={filerobotTheme}\n                                    defaultTabId={\n                                        editorConstants?.TABS\n                                            ? (\n                                                  editorConstants.TABS as Record<\n                                                      string,\n                                                      unknown\n                                                  >\n                                              ).ADJUST\n                                            : undefined\n                                    }\n                                    tabsIds={resolvedTabs}\n                                    onBeforeSave={() => false}\n                                />\n                            </EditorWrapper>\n                        )}\n                    </div>\n                </div>\n            </div>\n        </div>,\n        document.body,\n    )\n})\n\n/**\n * Custom props that filerobot-image-editor's styled-components leak to the DOM.\n * Maintained as a Set so `shouldForwardProp` can block them via StyleSheetManager.\n */\nconst FILEROBOT_CUSTOM_PROPS = new Set([\n    'active',\n    'noMargin',\n    'showBackButton',\n    'isPhoneScreen',\n    'showTabsDrawer',\n    'hasChildren',\n    'isAccordion',\n])\n\n/**\n * Wraps children with styled-components' StyleSheetManager (when available)\n * to prevent custom props from leaking to the DOM in React 19+.\n * Falls back to a plain fragment if styled-components is not loaded.\n */\nfunction EditorWrapper({\n    children,\n    StyleSheetMgr,\n    shouldForwardProp,\n}: {\n    children: React.ReactNode\n    StyleSheetMgr: ComponentType<{\n        shouldForwardProp?: (prop: string) => boolean\n        children: React.ReactNode\n    }> | null\n    shouldForwardProp: (prop: string) => boolean\n}) {\n    if (StyleSheetMgr) {\n        return (\n            <StyleSheetMgr shouldForwardProp={shouldForwardProp}>\n                {children}\n            </StyleSheetMgr>\n        )\n    }\n    return <>{children}</>\n}\n","'use client'\n\nimport { motion } from 'framer-motion'\nimport React from 'react'\nimport { useRootContext } from '../context/RootContext'\nimport useMainBox from '../hooks/useMainBox'\nimport { cn } from '../lib/tailwind'\nimport AdapterSelector from './AdapterSelector'\nimport AdapterView from './AdapterView'\nimport FileList from './FileList'\nimport MyAnimatePresence from './shared/MyAnimatePresence'\nimport ShouldRender from './shared/ShouldRender'\nexport default function MainBox() {\n    const {\n        files,\n        activeAdapter,\n        isAddingMore,\n        props: { dark },\n    } = useRootContext()\n    const {\n        isDragging,\n        absoluteIsDragging,\n        absoluteHasBorder,\n        handleDragOver,\n        handleDragLeave,\n        handleDrop,\n    } = useMainBox()\n\n    return (\n        <MyAnimatePresence>\n            <motion.div\n                key=\"adapter-selector\"\n                className={cn(\n                    'upup-relative upup-flex-1 upup-overflow-hidden upup-rounded-lg',\n                    {\n                        'upup-border upup-border-[#1849D6]': absoluteHasBorder,\n                        'upup-border-[#30C5F7] dark:upup-border-[#30C5F7]':\n                            absoluteHasBorder && dark,\n                        'upup-border-dashed': !isDragging,\n                        'upup-bg-[#E7ECFC] upup-backdrop-blur-sm':\n                            absoluteIsDragging && !dark,\n                        'upup-bg-[#045671] upup-backdrop-blur-sm dark:upup-bg-[#045671]':\n                            absoluteIsDragging && dark,\n                    },\n                )}\n                initial={{ opacity: 0 }}\n                animate={{ opacity: 1 }}\n                exit={{ opacity: 0 }}\n                onDragOver={handleDragOver}\n                onDragLeave={handleDragLeave}\n                onDrop={handleDrop}\n            >\n                <ShouldRender if={!!activeAdapter}>\n                    <AdapterView />\n                </ShouldRender>\n                <ShouldRender\n                    if={!activeAdapter && (isAddingMore || !files.size)}\n                >\n                    <AdapterSelector />\n                </ShouldRender>\n                <FileList />\n            </motion.div>\n        </MyAnimatePresence>\n    )\n}\n","import { DragEventHandler, useCallback, useMemo, useState } from 'react'\nimport { UploadStatus, useRootContext } from '../context/RootContext'\n\nexport default function useMainBox() {\n    const {\n        files,\n        activeAdapter,\n        isAddingMore,\n        upload: { uploadStatus },\n        props: { onFilesDragOver, onFilesDragLeave, onFilesDrop, isProcessing },\n        setFiles,\n    } = useRootContext()\n    const [isDragging, setIsDragging] = useState(false)\n\n    const absoluteIsDragging = useMemo(\n        () => isDragging && !activeAdapter,\n        [isDragging, activeAdapter],\n    )\n\n    const absoluteHasBorder = useMemo(\n        () => (!files.size || isAddingMore || isDragging) && !activeAdapter,\n        [activeAdapter, files.size, isAddingMore, isDragging],\n    )\n\n    const disableDragAction = useMemo(\n        () => activeAdapter ?? uploadStatus === UploadStatus.ONGOING,\n        [activeAdapter, uploadStatus],\n    )\n\n    const handleDragOver: DragEventHandler<HTMLDivElement> = useCallback(\n        e => {\n            if (disableDragAction || isProcessing) return\n            e.preventDefault()\n\n            setIsDragging(true)\n            e.dataTransfer.dropEffect = 'copy'\n\n            const files = Array.from(e.dataTransfer.files)\n            onFilesDragOver(files)\n        },\n        [disableDragAction, onFilesDragOver, isProcessing],\n    )\n\n    const handleDragLeave: DragEventHandler<HTMLDivElement> = useCallback(\n        e => {\n            if (disableDragAction || isProcessing) return\n            e.preventDefault()\n\n            setIsDragging(false)\n\n            const files = Array.from(e.dataTransfer.files)\n            onFilesDragLeave(files)\n        },\n        [disableDragAction, onFilesDragLeave, isProcessing],\n    )\n\n    const handleDrop: DragEventHandler<HTMLDivElement> = useCallback(\n        async e => {\n            if (disableDragAction || isProcessing) return\n            e.preventDefault()\n\n            const dt = e.dataTransfer\n            const items = Array.from(dt.items || [])\n            let droppedFiles: File[] = []\n            // Attempt directory-aware traversal using File System Access API or webkit entries\n            const supportsEntries = (items[0] as any)?.webkitGetAsEntry\n            if (supportsEntries) {\n                const traverse = async (entry: any): Promise<File[]> => {\n                    if (entry.isFile) {\n                        return await new Promise<File[]>((resolve, reject) => {\n                            entry.file((file: File) => {\n                                try {\n                                    // Attach synthetic relativePath so UI can build a tree\n                                    const path =\n                                        entry.fullPath || `/${file.name}`\n                                    Object.defineProperty(\n                                        file,\n                                        'relativePath',\n                                        {\n                                            value: path.replace(/^\\//, ''),\n                                            configurable: true,\n                                            enumerable: false,\n                                            writable: false,\n                                        },\n                                    )\n                                } catch {\n                                    // noop\n                                }\n                                resolve([file])\n                            }, reject)\n                        })\n                    } else if (entry.isDirectory) {\n                        const reader = entry.createReader()\n                        const entries: any[] = await new Promise(\n                            (resolve, reject) => {\n                                reader.readEntries(resolve, reject)\n                            },\n                        )\n                        const all = await Promise.all(entries.map(traverse))\n                        return all.flat()\n                    }\n                    return []\n                }\n                const filesArrays = await Promise.all(\n                    items\n                        .map(it => (it as any).webkitGetAsEntry?.())\n                        .filter(Boolean)\n                        .map(traverse),\n                )\n                droppedFiles = filesArrays.flat()\n            } else if ('getAsFileSystemHandle' in (items[0] || ({} as any))) {\n                // Newer FS Access API (optional; broad browser support not guaranteed)\n                const traverseHandle = async (\n                    h: any,\n                    path = '',\n                ): Promise<File[]> => {\n                    if (h.kind === 'file') {\n                        const file = await h.getFile()\n                        try {\n                            Object.defineProperty(file, 'relativePath', {\n                                value: path + file.name,\n                                configurable: true,\n                                enumerable: false,\n                                writable: false,\n                            })\n                        } catch {\n                            // noop\n                        }\n                        return [file]\n                    } else if (h.kind === 'directory') {\n                        const out: File[] = []\n                        for await (const [name, child] of h.entries()) {\n                            out.push(\n                                ...(await traverseHandle(\n                                    child,\n                                    path + name + '/',\n                                )),\n                            )\n                        }\n                        return out\n                    }\n                    return []\n                }\n                const handles = await Promise.all(\n                    items.map(\n                        async it => await (it as any).getAsFileSystemHandle?.(),\n                    ),\n                )\n                const all = await Promise.all(\n                    handles.filter(Boolean).map((h: any) => traverseHandle(h)),\n                )\n                droppedFiles = all.flat()\n            } else {\n                // Fallback: plain files (most browsers will already include nested files when a folder is dropped in Chromium)\n                droppedFiles = Array.from(dt.files)\n            }\n\n            onFilesDrop(droppedFiles)\n            setFiles(droppedFiles)\n\n            setIsDragging(false)\n        },\n        [disableDragAction, onFilesDrop, setFiles, isProcessing],\n    )\n\n    return {\n        isDragging,\n        absoluteIsDragging,\n        absoluteHasBorder,\n        handleDragOver,\n        handleDragLeave,\n        handleDrop,\n    }\n}\n","import React, { useCallback } from 'react'\nimport { TbUpload } from 'react-icons/tb'\nimport { plural, t } from '../../shared/i18n'\nimport { useRootContext } from '../context/RootContext'\nimport useAdapterSelector from '../hooks/useAdapterSelector'\nimport { cn } from '../lib/tailwind'\nimport ShouldRender from './shared/ShouldRender'\n\nexport default function AdapterSelector() {\n    const {\n        props: {\n            mini,\n            accept,\n            multiple,\n            limit,\n            maxFileSize,\n            dark,\n            classNames,\n            showSelectFolderButton,\n        },\n        translations: tr,\n        isAddingMore,\n        setIsAddingMore,\n        inputRef,\n        setFiles,\n    } = useRootContext()\n    const { chosenAdapters, handleAdapterClick, handleInputFileChange } =\n        useAdapterSelector()\n\n    const handleBrowseFilesClick = useCallback(() => {\n        if (inputRef.current) {\n            inputRef.current.removeAttribute('webkitdirectory')\n            inputRef.current.removeAttribute('directory')\n            inputRef.current.click()\n        }\n    }, [inputRef])\n\n    const handleSelectFolderClick = useCallback(async () => {\n        const anyWindow = window as any\n        if (anyWindow.showDirectoryPicker) {\n            try {\n                const directoryHandle = await anyWindow.showDirectoryPicker()\n                const files: File[] = []\n\n                async function getFiles(dirHandle: any, path = '') {\n                    for await (const entry of dirHandle.values()) {\n                        const newPath = path\n                            ? `${path}/${entry.name}`\n                            : entry.name\n                        if (entry.kind === 'file') {\n                            const file = await entry.getFile()\n                            ;(file as any).webkitRelativePath = newPath\n                            files.push(file)\n                        } else if (entry.kind === 'directory') {\n                            await getFiles(entry, newPath)\n                        }\n                    }\n                }\n                await getFiles(directoryHandle)\n                if (files.length > 0) {\n                    setFiles(files)\n                    if (inputRef.current) {\n                        inputRef.current.value = ''\n                    }\n                }\n            } catch {\n                // User cancelled, do nothing.\n            }\n        } else {\n            // Fallback to existing behavior\n            if (inputRef.current) {\n                inputRef.current.setAttribute('webkitdirectory', 'true')\n                inputRef.current.setAttribute('directory', 'true')\n                inputRef.current.click()\n            }\n        }\n    }, [inputRef, setFiles])\n\n    return (\n        <div\n            className={cn(\n                'upup-relative upup-flex upup-h-full upup-gap-3 upup-rounded-lg',\n                {\n                    'upup-flex-col': isAddingMore,\n                    'upup-flex-col-reverse upup-items-center upup-justify-center md:upup-flex-col md:upup-gap-14':\n                        !isAddingMore,\n                },\n            )}\n        >\n            <ShouldRender if={isAddingMore}>\n                <div\n                    className={cn(\n                        'upup-shadow-bottom upup-flex upup-w-full upup-items-center upup-rounded-t-lg upup-bg-black/[0.025] upup-px-3 upup-py-2',\n                        {\n                            'upup-bg-white/5 dark:upup-bg-white/5': dark,\n                        },\n                        classNames.containerHeader,\n                    )}\n                >\n                    <button\n                        className={cn(\n                            'upup-flex upup-items-center upup-gap-1 upup-text-sm upup-font-medium upup-text-blue-600',\n                            {\n                                'upup-text-[#30C5F7] dark:upup-text-[#30C5F7]':\n                                    dark,\n                            },\n                            classNames.containerCancelButton,\n                        )}\n                        onClick={() => setIsAddingMore(false)}\n                    >\n                        <svg\n                            xmlns=\"http://www.w3.org/2000/svg\"\n                            width=\"16\"\n                            height=\"16\"\n                            viewBox=\"0 0 24 24\"\n                            fill=\"none\"\n                            stroke=\"currentColor\"\n                            strokeWidth=\"2\"\n                            strokeLinecap=\"round\"\n                            strokeLinejoin=\"round\"\n                        >\n                            <polyline points=\"15 18 9 12 15 6\" />\n                        </svg>\n                        Back\n                    </button>\n                    <span\n                        className={cn(\n                            'upup-flex-1 upup-text-center upup-text-sm upup-text-[#6D6D6D]',\n                            {\n                                'upup-text-gray-300 dark:upup-text-gray-300':\n                                    dark,\n                            },\n                        )}\n                    >\n                        Adding more files\n                    </span>\n                </div>\n            </ShouldRender>\n            <ShouldRender if={!mini}>\n                <div\n                    className={cn(\n                        'upup-flex upup-w-full upup-flex-col upup-justify-center upup-gap-1 md:upup-flex-row md:upup-flex-wrap md:upup-items-center md:upup-gap-[30px] md:upup-px-[30px]',\n                        classNames.adapterButtonList,\n                    )}\n                >\n                    {chosenAdapters.map(({ Icon, id, name }) => (\n                        <button\n                            key={id}\n                            type=\"button\"\n                            className={cn(\n                                'upup-group upup-flex upup-items-center upup-gap-[6px] upup-border-b upup-border-gray-200 upup-px-2 upup-py-1 md:upup-flex-col md:upup-justify-center md:upup-rounded-lg md:upup-border-none md:upup-p-0',\n                                {\n                                    'upup-border-[#6D6D6D] dark:upup-border-[#6D6D6D]':\n                                        dark,\n                                },\n                                classNames.adapterButton,\n                            )}\n                            onKeyDown={e => {\n                                if (e.key === 'Enter') e.preventDefault()\n                            }}\n                            onClick={() => handleAdapterClick(id)}\n                        >\n                            <Icon />\n                            <span\n                                className={cn(\n                                    'upup-text-xs upup-text-[#242634]',\n                                    {\n                                        'upup-text-gray-300 dark:upup-text-gray-300':\n                                            dark,\n                                    },\n                                    classNames.adapterButtonText,\n                                )}\n                            >\n                                {name}\n                            </span>\n                        </button>\n                    ))}\n                </div>\n            </ShouldRender>\n            <input\n                type=\"file\"\n                accept={accept}\n                className=\"upup-hidden\"\n                data-testid=\"upup-file-input\"\n                ref={inputRef}\n                multiple={multiple}\n                onChange={handleInputFileChange}\n            />\n            {mini ? (\n                <button\n                    type=\"button\"\n                    onClick={handleBrowseFilesClick}\n                    className=\"upup-flex upup-cursor-pointer upup-flex-col upup-items-center upup-justify-center upup-gap-2 upup-rounded-lg upup-p-2\"\n                >\n                    <TbUpload\n                        size={32}\n                        className={cn(\n                            'upup-h-16 upup-w-16 md:upup-h-20 md:upup-w-20',\n                            {\n                                'upup-text-[#0B0B0B]': !dark,\n                                'upup-text-white dark:upup-text-white': dark,\n                            },\n                        )}\n                    />\n                    <p\n                        className={cn('px-6 upup-text-center upup-text-xs', {\n                            'upup-text-[#6D6D6D] dark:upup-text-gray-400':\n                                !dark,\n                            'upup-text-gray-400 dark:upup-text-gray-500': dark,\n                        })}\n                    >\n                        Drag or browse to upload\n                    </p>\n                </button>\n            ) : (\n                <div className=\"upup-flex upup-flex-col upup-items-center upup-gap-1 upup-px-3 upup-text-center md:upup-gap-2 md:upup-px-[30px]\">\n                    <div className=\"upup-flex upup-flex-wrap upup-items-center upup-justify-center upup-gap-1\">\n                        <span\n                            className={cn(\n                                'upup-text-xs upup-text-[#0B0B0B] md:upup-text-sm',\n                                {\n                                    'upup-text-white dark:upup-text-white':\n                                        dark,\n                                },\n                            )}\n                        >\n                            {limit > 1 ? tr.dragFilesOr : tr.dragFileOr}\n                        </span>\n                        <button\n                            type=\"button\"\n                            className={cn(\n                                'upup-cursor-pointer upup-text-xs upup-font-semibold upup-text-[#0E2ADD] md:upup-text-sm',\n                                {\n                                    'upup-text-[#59D1F9] dark:upup-text-[#59D1F9]':\n                                        dark,\n                                },\n                            )}\n                            onClick={handleBrowseFilesClick}\n                        >\n                            {tr.browseFiles}\n                        </button>\n                        {showSelectFolderButton && (\n                            <>\n                                <span\n                                    className={cn(\n                                        'upup-text-xs upup-text-[#0B0B0B] md:upup-text-sm',\n                                        {\n                                            'upup-text-white dark:upup-text-white':\n                                                dark,\n                                        },\n                                    )}\n                                >\n                                    {' '}\n                                    {tr.or}\n                                </span>\n                                <button\n                                    type=\"button\"\n                                    className={cn(\n                                        'upup-cursor-pointer upup-text-xs upup-font-semibold upup-text-[#0E2ADD] md:upup-text-sm',\n                                        {\n                                            'upup-text-[#59D1F9] dark:upup-text-[#59D1F9]':\n                                                dark,\n                                        },\n                                    )}\n                                    onClick={handleSelectFolderClick}\n                                >\n                                    {tr.selectAFolder}\n                                </button>\n                            </>\n                        )}\n                    </div>\n                    <p\n                        className={cn(\n                            'upup-text-center upup-text-xs upup-text-[#6D6D6D] md:upup-text-sm',\n                            {\n                                'upup-text-gray-300 dark:upup-text-gray-300':\n                                    dark,\n                            },\n                        )}\n                    >\n                        {maxFileSize?.size && maxFileSize?.unit && (\n                            <>\n                                {t(plural(tr, 'maxFileSizeAllowed', limit), {\n                                    size: maxFileSize.size,\n                                    unit: maxFileSize.unit,\n                                })}\n                            </>\n                        )}\n                    </p>\n                </div>\n            )}\n        </div>\n    )\n}\n","import { ChangeEventHandler, useCallback, useMemo } from 'react'\nimport { UploadAdapter } from '../../shared/types'\nimport { useRootContext } from '../context/RootContext'\nimport { uploadAdapterObject } from '../lib/constants'\n\nexport default function useAdapterSelector() {\n    const {\n        inputRef,\n        setActiveAdapter,\n        setFiles,\n        translations,\n        props: { uploadAdapters, onIntegrationClick },\n    } = useRootContext()\n\n    const chosenAdapters = useMemo(\n        () =>\n            Object.values(uploadAdapterObject)\n                .filter(item => uploadAdapters.includes(item.id))\n                .map(item => ({\n                    ...item,\n                    name: translations[item.nameKey],\n                })),\n        [uploadAdapters, translations],\n    )\n\n    const handleAdapterClick = useCallback(\n        (adapterId: UploadAdapter) => {\n            onIntegrationClick(adapterId)\n            if (adapterId === UploadAdapter.INTERNAL) inputRef.current?.click()\n            else setActiveAdapter(adapterId)\n        },\n        [inputRef, onIntegrationClick, setActiveAdapter],\n    )\n\n    const handleInputFileChange: ChangeEventHandler<HTMLInputElement> =\n        useCallback(\n            e => {\n                setFiles(Array.from(e.currentTarget.files || []))\n                e.currentTarget.value = ''\n            },\n            [setFiles],\n        )\n\n    return {\n        chosenAdapters,\n        handleAdapterClick,\n        handleInputFileChange,\n    }\n}\n","import { FC } from 'react'\nimport type { Translations } from './i18n/types'\n\nexport type { Translations }\n\nexport enum UploadAdapter {\n    INTERNAL = 'INTERNAL',\n    GOOGLE_DRIVE = 'GOOGLE_DRIVE',\n    ONE_DRIVE = 'ONE_DRIVE',\n    DROPBOX = 'DROPBOX',\n    LINK = 'LINK',\n    CAMERA = 'CAMERA',\n    // UNSPLASH = 'UNSPLASH',\n    // BOX = 'BOX',\n}\n\nexport type GoogleDriveConfigs = {\n    google_api_key: string\n    google_app_id: string\n    google_client_id: string\n}\n\nexport type OneDriveConfigs = {\n    onedrive_client_id: string\n    redirectUri?: string\n}\n\nexport type DropboxConfigs = {\n    dropbox_client_id?: string\n    dropbox_redirect_uri?: string\n}\n\nexport enum UpupProvider {\n    AWS = 'aws',\n    Azure = 'azure',\n    BackBlaze = 'backblaze',\n    DigitalOcean = 'digitalocean',\n}\n\ntype MaxFileSizeObject = {\n    size: number\n    unit: 'B' | 'KB' | 'MB' | 'GB' | 'TB' | 'PB' | 'EB' | 'ZB' | 'YB'\n}\n\n/**\n * Configuration for the optional image editor.\n * The editor is lazy-loaded at runtime; consumers must install\n * `react-filerobot-image-editor` and its peer deps separately.\n */\nexport type ImageEditorOptions = {\n    /** Whether the editor is enabled (default false). */\n    enabled?: boolean\n    /**\n     * How the editor is displayed.\n     * - \"inline\":  overlays the editor on top of the uploader container (default)\n     * - \"modal\":   opens the editor in a full-screen modal dialog\n     */\n    display?: 'inline' | 'modal'\n    /**\n     * When to auto-open the editor after file selection.\n     * - \"never\":  never auto-open (user clicks Edit manually)\n     * - \"single\": auto-open when exactly 1 new image is added\n     * - \"always\": auto-open for every newly added image (queued sequentially)\n     */\n    autoOpen?: 'never' | 'single' | 'always'\n    /** Output settings for the edited image. */\n    output?: {\n        /** MIME type for the saved image (e.g. \"image/png\", \"image/webp\"). */\n        mimeType?: string\n        /** Quality 0–1 for lossy formats (jpeg/webp). */\n        quality?: number\n        /** Custom file name generator. Receives the original File. */\n        fileName?: (original: File) => string\n    }\n    /**\n     * Filerobot tab keys to show.\n     * @see https://github.com/nicedayfor/filerobot-image-editor#tabs\n     */\n    tabs?: (\n        | 'Adjust'\n        | 'Annotate'\n        | 'Filters'\n        | 'Finetune'\n        | 'Resize'\n        | 'Watermark'\n    )[]\n    /**\n     * Filerobot tool keys to show inside the Annotate tab.\n     * @see https://github.com/nicedayfor/filerobot-image-editor#tools\n     */\n    tools?: (\n        | 'Crop'\n        | 'Rotate'\n        | 'Flip'\n        | 'Brightness'\n        | 'Contrast'\n        | 'HSV'\n        | 'Blur'\n        | 'Text'\n        | 'Line'\n        | 'Rect'\n        | 'Ellipse'\n        | 'Polygon'\n        | 'Pen'\n        | 'Arrow'\n        | 'Image'\n    )[]\n    /** Callback fired when the editor modal opens. */\n    onOpen?: (file: FileWithParams) => void\n    /** Callback fired when the user cancels editing. */\n    onCancel?: (file: FileWithParams) => void\n    /** Callback fired after the user saves an edit. */\n    onSave?: (editedFile: FileWithParams, originalFile: FileWithParams) => void\n}\n\n/** Resolved image editor config with all defaults applied. */\nexport type ResolvedImageEditorOptions = Required<\n    Pick<ImageEditorOptions, 'enabled' | 'autoOpen' | 'display'>\n> &\n    Omit<ImageEditorOptions, 'enabled' | 'autoOpen' | 'display'>\n\nexport type UpupUploaderPropsClassNames = {\n    fileIcon?: string\n    containerMini?: string\n    containerFull?: string\n    containerHeader?: string\n    containerCancelButton?: string\n    containerAddMoreButton?: string\n\n    adapterButtonList?: string\n    adapterButton?: string\n    adapterButtonIcon?: string\n    adapterButtonText?: string\n\n    adapterViewHeader?: string\n    adapterViewCancelButton?: string\n    adapterView?: string\n    driveLoading?: string\n\n    driveHeader?: string\n    driveLogoutButton?: string\n    driveSearchContainer?: string\n    driveSearchInput?: string\n    driveBody?: string\n    driveItemContainerDefault?: string\n    driveItemContainerSelected?: string\n    driveItemContainerInner?: string\n    driveItemInnerText?: string\n    driveFooter?: string\n    driveAddFilesButton?: string\n    driveCancelFilesButton?: string\n\n    urlInput?: string\n    urlFetchButton?: string\n\n    cameraPreviewContainer?: string\n    cameraDeleteButton?: string\n    cameraCaptureButton?: string\n    cameraRotateButton?: string\n    cameraAddButton?: string\n\n    fileListContainer?: string\n    fileListContainerInnerSingle?: string\n    fileListContainerInnerMultiple?: string\n    fileListFooter?: string\n\n    filePreviewPortal?: string\n    fileItemSingle?: string\n    fileItemMultiple?: string\n    fileThumbnailSingle?: string\n    fileThumbnailMultiple?: string\n    fileInfo?: string\n    fileName?: string\n    fileSize?: string\n    filePreviewButton?: string\n    fileDeleteButton?: string\n\n    uploadButton?: string\n    uploadDoneButton?: string\n\n    progressBarContainer?: string\n    progressBar?: string\n    progressBarInner?: string\n    progressBarText?: string\n}\n\nexport type UpupUploaderPropsIcons = {\n    ContainerAddMoreIcon?: FC<{ className?: string }>\n\n    FileDeleteIcon?: FC<{ className?: string }>\n\n    CameraDeleteIcon?: FC<{ className?: string }>\n    CameraCaptureIcon?: FC<{ className?: string }>\n    CameraRotateIcon?: FC<{ className?: string }>\n\n    LoaderIcon?: FC<{ className?: string }>\n}\n\nexport type UpupUploaderProps = {\n    // Required Props\n    provider: UpupProvider\n    tokenEndpoint: string\n\n    // Optional Props\n    showSelectFolderButton?: boolean // Controls the \"select a folder\" button visibility\n    enableAutoCorsConfig?: boolean\n    uploadAdapters?: UploadAdapter[]\n    driveConfigs?: {\n        googleDrive?: GoogleDriveConfigs\n        oneDrive?: OneDriveConfigs\n        dropbox?: DropboxConfigs\n    }\n    shouldCompress?: boolean\n    accept?: string\n    limit?: number\n    allowPreview?: boolean\n    isProcessing?: boolean\n    mini?: boolean\n    maxFileSize?: MaxFileSizeObject\n    /** Optional image editor. Pass `true` for defaults or an `ImageEditorOptions` object. */\n    imageEditor?: boolean | ImageEditorOptions\n    customProps?: object\n    dark?: boolean\n    maxRetries?: number\n    resumable?: ResumableUploadOptions\n    classNames?: UpupUploaderPropsClassNames\n    icons?: UpupUploaderPropsIcons\n\n    // i18n / Localisation\n    /** A full locale pack (a `Translations` object, e.g. `ja_JP`). Defaults to `en_US`. */\n    localePack?: Translations\n    /** Per-key overrides that are deep-merged on top of the active locale. */\n    translations?: Partial<Translations>\n\n    // Event Handlers\n    onFilesSelected?: (files: FileWithParams[]) => void\n    onDoneClicked?: () => void\n    onPrepareFiles?: (files: FileWithParams[]) => Promise<FileWithParams[]>\n    onFileClick?: (file: FileWithParams) => void\n    onIntegrationClick?: (integrationType: string) => void\n    onFileUploadStart?: (file: FileWithParams) => void\n    onFileUploadComplete?: (file: FileWithParams, key: string) => void\n    onFilesUploadComplete?: (fileWithParams: FileWithParams[]) => void\n    onFileUploadProgress?: (\n        file: FileWithParams,\n        {\n            loaded,\n            total,\n            percentage,\n        }: { loaded: number; total: number; percentage: number },\n    ) => void\n    onFilesUploadProgress?: (completedFiles: number, totalFiles: number) => void\n    onFileRemove?: (file: FileWithParams) => void\n    onFilesDragOver?: (files: File[]) => void\n    onFilesDragLeave?: (files: File[]) => void\n    onFilesDrop?: (files: File[]) => void\n    onFileTypeMismatch?: (file: File, acceptedTypes: string) => void\n    // onCancelUpload?: (files: FileWithParams[]) => void\n    onError?: (errorMessage: string) => void\n    onWarn?: (warningMessage: string) => void\n}\n\nexport type PresignedUrlResponse = {\n    key: string\n    publicUrl: string\n    uploadUrl: string\n    expiresIn: number\n}\n\nexport enum UploadErrorType {\n    PERMISSION_ERROR = 'PERMISSION_ERROR',\n    EXPIRED_URL = 'EXPIRED_URL',\n\n    FILE_VALIDATION_ERROR = 'FILE_VALIDATION_ERROR',\n    PRESIGNED_URL_ERROR = 'PRESIGNED_URL_ERROR',\n\n    SIGNED_URL_ERROR = 'SIGNED_URL_ERROR',\n    CORS_CONFIG_ERROR = 'CORS_CONFIG_ERROR',\n    TEMPORARY_CREDENTIALS_ERROR = 'TEMPORARY_CREDENTIALS_ERROR',\n\n    UNKNOWN_UPLOAD_ERROR = 'UNKNOWN_UPLOAD_ERROR',\n}\n\nexport class UploadError extends Error {\n    private readonly DEFAULT_ERROR_STATUS_CODE = 500\n\n    constructor(\n        message: string,\n        public type = UploadErrorType.UNKNOWN_UPLOAD_ERROR,\n        public retryable = false,\n        public status?: number,\n    ) {\n        super(message)\n        this.name = 'UploadError'\n        this.status = status ?? this.DEFAULT_ERROR_STATUS_CODE\n    }\n}\n\nexport type FileWithParams = File & {\n    id: string\n    url: string\n    key?: string\n    fileHash?: string | undefined\n    thumbnail?: {\n        file: File\n        key?: string\n    }\n}\n\nexport type FileWithProgress = FileWithParams & { progress: number }\n\n/**\n * Options for resumable uploads.\n * Currently supports 'multipart' mode for S3-compatible providers.\n * 'tus' mode is reserved for future implementation.\n */\nexport type ResumableUploadOptions =\n    | {\n          mode: 'multipart'\n          /** Part size in bytes. Minimum 5 MiB, clamped automatically. */\n          chunkSizeBytes?: number\n          /** Persist upload sessions in localStorage for cross-refresh resume. Default: true */\n          persist?: boolean\n      }\n    | {\n          mode: 'tus'\n          /** Tus server endpoint (not implemented yet) */\n          endpoint: string\n      }\n\n/**\n * Response from tokenEndpoint for multipart:init action\n */\nexport type MultipartInitResponse = {\n    key: string\n    uploadId: string\n    partSize: number\n    expiresIn: number\n}\n\n/**\n * Response from tokenEndpoint for multipart:signPart action\n */\nexport type MultipartSignPartResponse = {\n    uploadUrl: string\n    expiresIn: number\n}\n\n/**\n * A single uploaded part reference\n */\nexport type MultipartPart = {\n    partNumber: number\n    eTag: string\n}\n\n/**\n * Response from tokenEndpoint for multipart:listParts action\n */\nexport type MultipartListPartsResponse = {\n    parts: MultipartPart[]\n}\n\n/**\n * Response from tokenEndpoint for multipart:complete action\n */\nexport type MultipartCompleteResponse = {\n    key: string\n    publicUrl: string\n}\n\n/**\n * Response from tokenEndpoint for multipart:abort action\n */\nexport type MultipartAbortResponse = {\n    ok: true\n}\n","import React from 'react'\nimport Webcam from 'react-webcam'\nimport { t } from '../../shared/i18n'\nimport useCameraUploader from '../hooks/useCameraUploader'\nimport { cn } from '../lib/tailwind'\nimport AdapterViewContainer from './shared/AdapterViewContainer'\nimport ShouldRender from './shared/ShouldRender'\n\nexport default function CameraUploader() {\n    const {\n        capture,\n        handleFetchImage,\n        clearUrl,\n        handleCameraSwitch,\n        newCameraSide,\n        url,\n        webcamRef,\n        facingMode,\n        translations: tr,\n        props: {\n            dark,\n            classNames,\n            icons: { CameraCaptureIcon, CameraDeleteIcon, CameraRotateIcon },\n        },\n    } = useCameraUploader()\n\n    return (\n        <AdapterViewContainer>\n            <div className=\"upup-flex upup-h-full upup-w-full upup-flex-col upup-justify-center upup-overflow-auto upup-px-3 upup-py-2\">\n                <div className=\"upup-flex-1 upup-pt-10\">\n                    <ShouldRender if={!!url}>\n                        <div\n                            className={cn(\n                                'upup-relative upup-aspect-video upup-bg-black/[0.025] upup-bg-contain upup-bg-center upup-bg-no-repeat upup-shadow-xl',\n                                {\n                                    'upup-bg-white/5 dark:upup-bg-white/5':\n                                        dark,\n                                },\n                                classNames.cameraPreviewContainer,\n                            )}\n                            style={{ backgroundImage: `url(${url})` }}\n                        >\n                            <button\n                                onClick={clearUrl}\n                                className={cn(\n                                    'upup-absolute upup--right-2 upup--top-2 upup-z-10 upup-rounded-full upup-bg-[#272727] upup-p-1 upup-text-xl upup-text-[#f5f5f5]',\n                                    classNames.cameraDeleteButton,\n                                )}\n                                type=\"button\"\n                            >\n                                <CameraDeleteIcon />\n                            </button>\n                        </div>\n                    </ShouldRender>\n\n                    <ShouldRender if={!url}>\n                        <Webcam\n                            audio={false}\n                            ref={webcamRef}\n                            screenshotFormat=\"image/jpeg\"\n                            videoConstraints={{ facingMode }}\n                            className=\"upup-aspect-video upup-rounded-xl\"\n                        />\n                    </ShouldRender>\n                </div>\n                <div className=\"upup-flex upup-gap-4\">\n                    <ShouldRender if={!url}>\n                        <button\n                            className={cn(\n                                'upup-mt-2 upup-flex upup-w-1/3 upup-flex-col upup-items-center  upup-justify-center upup-rounded-md  upup-bg-blue-600 upup-p-2 upup-text-white upup-transition-all upup-duration-300',\n                                {\n                                    'upup-bg-[#59D1F9] dark:upup-bg-[#59D1F9]':\n                                        dark,\n                                },\n                                classNames.cameraCaptureButton,\n                            )}\n                            onClick={capture}\n                            type=\"button\"\n                        >\n                            <span>\n                                <CameraCaptureIcon />\n                            </span>\n                            <span>{tr.capture}</span>\n                        </button>\n                        <button\n                            className={cn(\n                                'upup-mt-2 upup-flex upup-w-1/3 upup-flex-col upup-items-center upup-rounded-md upup-bg-gray-500 upup-p-2 upup-text-white upup-transition-all upup-duration-300 hover:upup-bg-gray-600',\n                                classNames.cameraRotateButton,\n                            )}\n                            onClick={handleCameraSwitch}\n                            type=\"button\"\n                        >\n                            <span>\n                                <CameraRotateIcon />\n                            </span>\n                            <span>\n                                {t(tr.switchToCamera, {\n                                    side:\n                                        newCameraSide === 'front'\n                                            ? tr.front\n                                            : tr.back,\n                                })}\n                            </span>\n                        </button>\n                    </ShouldRender>\n                    <ShouldRender if={!!url}>\n                        <button\n                            className={cn(\n                                'upup-mt-2 upup-w-full upup-rounded-md upup-bg-blue-600 upup-p-2 upup-text-white upup-transition-all upup-duration-300',\n                                {\n                                    'upup-bg-[#59D1F9] dark:upup-bg-[#59D1F9]':\n                                        dark,\n                                },\n                                classNames.cameraAddButton,\n                            )}\n                            onClick={handleFetchImage}\n                            type=\"button\"\n                        >\n                            {tr.addImage}\n                        </button>\n                    </ShouldRender>\n                </div>\n            </div>\n        </AdapterViewContainer>\n    )\n}\n","import { MouseEventHandler, useRef, useState } from 'react'\nimport Webcam from 'react-webcam'\nimport { useRootContext } from '../context/RootContext'\nimport useFetchFileByUrl from './useFetchFileByUrl'\n\nexport enum FacingMode {\n    Environment = 'environment',\n    User = 'user',\n}\n\nexport default function useCameraUploader() {\n    const { setFiles, setActiveAdapter, translations, props } = useRootContext()\n    const { fetchImage } = useFetchFileByUrl()\n    const webcamRef = useRef<Webcam>(null)\n    const [url, setUrl] = useState('')\n    const [facingMode, setFacingMode] = useState<FacingMode>(\n        FacingMode.Environment,\n    )\n    const newCameraSide =\n        facingMode === FacingMode.Environment ? 'front' : 'back'\n    const clearUrl = () => setUrl('')\n\n    const capture = async () => {\n        const url = webcamRef.current?.getScreenshot()\n        if (!url) return\n\n        setUrl(url)\n    }\n\n    const handleFetchImage: MouseEventHandler<HTMLButtonElement> = async () => {\n        const file = await fetchImage(url)\n        if (file) {\n            setFiles([file])\n            setUrl('')\n            setActiveAdapter(undefined)\n        }\n    }\n\n    const handleCameraSwitch = () =>\n        setFacingMode(prevState =>\n            prevState === FacingMode.Environment\n                ? FacingMode.User\n                : FacingMode.Environment,\n        )\n\n    return {\n        url,\n        webcamRef,\n        facingMode,\n        capture,\n        handleFetchImage,\n        clearUrl,\n        handleCameraSwitch,\n        newCameraSide,\n        translations,\n        props,\n    }\n}\n","import { useCallback, useState } from 'react'\nimport { v4 as uuid } from 'uuid'\nimport { useRootContext } from '../context/RootContext'\n\nexport default function useFetchFileByUrl() {\n    const {\n        props: { onError },\n    } = useRootContext()\n    const [loading, setLoading] = useState(false)\n\n    const fetchImage = useCallback(\n        async (url: string) => {\n            if (loading) return\n\n            try {\n                setLoading(true)\n                const response = await fetch(url)\n                const blob = await response.blob()\n                const extension = blob.type.split('/')[1]\n\n                const file = new File([blob], `${uuid()}.${extension}`, {\n                    type: blob.type,\n                })\n\n                return file\n            } catch (error) {\n                onError((error as Error).message)\n                return\n            } finally {\n                setLoading(false)\n            }\n        },\n        [loading, onError],\n    )\n\n    return { loading, fetchImage }\n}\n","import React, { PropsWithChildren } from 'react'\nimport { useRootContext } from '../../context/RootContext'\nimport { cn } from '../../lib/tailwind'\n\nexport default function AdapterViewContainer({\n    children,\n    isLoading = false,\n}: PropsWithChildren<{ isLoading?: boolean }>) {\n    const {\n        props: { dark, classNames },\n    } = useRootContext()\n\n    return (\n        <div\n            className={cn(\n                'upup-flex upup-items-center upup-justify-center upup-overflow-hidden upup-bg-black/[0.075]',\n                {\n                    'upup-bg-white/10 upup-text-[#FAFAFA] dark:upup-bg-white/10 dark:upup-text-[#FAFAFA]':\n                        isLoading && dark,\n                    [classNames.adapterView!]:\n                        !isLoading && classNames.adapterView,\n                    [classNames.driveLoading!]:\n                        isLoading && classNames.driveLoading,\n                },\n            )}\n        >\n            {children}\n        </div>\n    )\n}\n","import React, { PropsWithChildren } from 'react'\nimport { useRootContext } from '../../context/RootContext'\n\nexport default function ShouldRender({\n    children,\n    if: condition,\n    isLoading = false,\n}: PropsWithChildren<{ if: boolean; isLoading?: boolean }>) {\n    const {\n        props: {\n            icons: { LoaderIcon },\n        },\n    } = useRootContext()\n\n    if (isLoading) return <LoaderIcon />\n    if (!condition) return null\n\n    return <>{children}</>\n}\n","import React, { useEffect } from 'react'\nimport { useDropbox } from '../hooks/useDropbox'\nimport useDropboxUploader from '../hooks/useDropboxUploader'\nimport DriveBrowser from './shared/DriveBrowser'\n\nexport default function DropboxUploader() {\n    const {\n        user,\n        dropboxFiles: driveFiles,\n        logout,\n        token,\n        isAuthenticated,\n        authenticate,\n        isLoading,\n    } = useDropbox()\n\n    const handleSignOut = async () => {\n        logout()\n        return Promise.resolve()\n    }\n\n    useEffect(() => {\n        if (!isAuthenticated && !token && !isLoading) {\n            authenticate()\n        }\n    }, [isAuthenticated, token, isLoading, authenticate])\n\n    const props = useDropboxUploader(token)\n\n    return (\n        <DriveBrowser\n            driveFiles={driveFiles as any}\n            user={user}\n            handleSignOut={handleSignOut}\n            {...(props as any)}\n        />\n    )\n}\n","import { DropboxFile, DropboxRoot, DropboxUser } from 'dropbox'\nimport { useCallback, useEffect, useState } from 'react'\nimport { useRootContext } from '../context/RootContext'\nimport { useDropboxAuth } from './useDropboxAuth'\n\nconst formatFileItem = (entry: any): DropboxFile => ({\n    id: entry.id,\n    name: entry.name,\n    path_display: entry.path_display,\n    isFolder: entry['.tag'] === 'folder',\n    size: entry.size,\n    thumbnailLink: null,\n})\n\nexport function useDropbox() {\n    const {\n        props: { onError },\n        dropboxConfigs,\n        translations,\n    } = useRootContext()\n\n    const {\n        isAuthenticated,\n        token,\n        refreshToken,\n        isLoading,\n        authenticate,\n        logout,\n        refreshAccessToken,\n    } = useDropboxAuth(dropboxConfigs)\n\n    const [user, setUser] = useState<DropboxUser>()\n    const [dropboxFiles, setDropboxFiles] = useState<DropboxRoot>()\n\n    // Check if user needs to re-authenticate to get refresh token\n    const needsReauth = isAuthenticated && token && !refreshToken\n\n    /**\n     * Utility function to make authenticated requests to Dropbox API with automatic token refresh\n     */\n    const fetchDropbox = useCallback(\n        async (\n            url: string,\n            method = 'POST',\n            body: object | null = {},\n            isRetry = false,\n        ) => {\n            try {\n                const headers: Record<string, string> = {\n                    Authorization: `Bearer ${token}`,\n                }\n\n                const requestOptions: RequestInit = {\n                    method,\n                    headers,\n                }\n\n                if (body !== null) {\n                    headers['Content-Type'] = 'application/json'\n                    requestOptions.body = JSON.stringify(body)\n                }\n\n                const response = await fetch(url, requestOptions)\n\n                if (!response.ok) {\n                    const errorText = await response.text()\n                    let errorMessage = `Dropbox API error (${response.status})`\n\n                    try {\n                        const errorJson = JSON.parse(errorText)\n                        errorMessage = errorJson.error_summary || errorMessage\n\n                        // Handle expired token by attempting refresh\n                        if (\n                            response.status === 401 &&\n                            errorMessage.includes('expired_access_token') &&\n                            refreshToken &&\n                            !isRetry\n                        ) {\n                            const newAccessToken =\n                                await refreshAccessToken(refreshToken)\n\n                            if (newAccessToken) {\n                                return fetchDropbox(url, method, body, true)\n                            } else {\n                                throw new Error(\n                                    translations.failedToRefreshExpiredToken,\n                                )\n                            }\n                        }\n\n                        // If token is expired but no refresh token available, prompt re-auth\n                        if (\n                            response.status === 401 &&\n                            errorMessage.includes('expired_access_token') &&\n                            !refreshToken\n                        ) {\n                            onError(translations.dropboxSessionExpired)\n                            logout()\n                            throw new Error(\n                                'Token expired - re-authentication required',\n                            )\n                        }\n\n                        if (errorMessage.includes('missing_scope')) {\n                            errorMessage =\n                                translations.dropboxMissingPermissions\n                        }\n                    } catch {\n                        // If we can't parse the error, but it's a 401, still try to refresh\n                        if (\n                            response.status === 401 &&\n                            refreshToken &&\n                            !isRetry\n                        ) {\n                            const newAccessToken =\n                                await refreshAccessToken(refreshToken)\n\n                            if (newAccessToken) {\n                                return fetchDropbox(url, method, body, true)\n                            }\n                        } else if (response.status === 401 && !refreshToken) {\n                            onError(translations.dropboxSessionExpired)\n                            logout()\n                            throw new Error(\n                                'Token expired - re-authentication required',\n                            )\n                        }\n\n                        errorMessage = errorText\n                            ? `${errorMessage}: ${errorText}`\n                            : errorMessage\n                    }\n\n                    throw new Error(errorMessage)\n                }\n\n                return response\n            } catch (error) {\n                console.error('Dropbox API error:', error)\n                throw error\n            }\n        },\n        [token, refreshToken, refreshAccessToken, onError, logout],\n    )\n\n    /**\n     * Get the user's information from Dropbox\n     */\n    const getUserInfo = useCallback(async () => {\n        try {\n            const response = await fetchDropbox(\n                'https://api.dropboxapi.com/2/users/get_current_account',\n                'POST',\n                null,\n            )\n            const data = await response.json()\n            setUser({\n                name: data.name.display_name,\n                email: data.email,\n            })\n        } catch (error) {\n            onError(`Failed to fetch user info: ${(error as Error).message}`)\n        }\n    }, [fetchDropbox, onError])\n\n    /**\n     * Get the list of files from Dropbox root\n     */\n    const fetchRootContents = useCallback(async () => {\n        try {\n            const response = await fetchDropbox(\n                'https://api.dropboxapi.com/2/files/list_folder',\n                'POST',\n                {\n                    path: '',\n                    recursive: false,\n                    include_media_info: true,\n                    include_deleted: false,\n                    include_has_explicit_shared_members: false,\n                },\n            )\n\n            const data = await response.json()\n            const files = data.entries.map(formatFileItem)\n\n            setDropboxFiles({\n                id: 'root',\n                name: 'Dropbox',\n                isFolder: true,\n                children: files,\n            })\n        } catch (error) {\n            onError(`Failed to fetch file list: ${(error as Error).message}`)\n        }\n    }, [fetchDropbox, onError])\n\n    /**\n     * Initialize user data and files when authentication is complete\n     */\n    useEffect(() => {\n        if (token && isAuthenticated && !isLoading) {\n            ;(async () => {\n                try {\n                    await getUserInfo()\n                    await fetchRootContents()\n                } catch (error) {\n                    console.error('Error initializing Dropbox data:', error)\n                }\n            })()\n        }\n    }, [token, isAuthenticated, isLoading, getUserInfo, fetchRootContents])\n\n    return {\n        user,\n        dropboxFiles,\n        logout,\n        authenticate,\n        token,\n        isAuthenticated,\n        isLoading,\n        needsReauth,\n    }\n}\n","// @ts-expect-error typings incomplete\nimport { Dropbox, DropboxUser } from 'dropbox'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { useRootContext } from '../context/RootContext'\nimport { createSecureStorage } from '../lib/storageHelper'\n\nconst TOKEN_KEY = 'dropbox_access_token'\nconst REFRESH_KEY = 'dropbox_refresh_token'\nconst USER_KEY = 'dropbox_user'\n\nconst WIN_NAME = 'DropboxAuthPopup'\n\ninterface DropboxConfigs {\n    dropbox_client_id?: string\n    dropbox_redirect_uri?: string\n}\n\nconst secure = createSecureStorage()\n\nconst addBusyOverlay = (w: Window) => {\n    if (w.document.getElementById('__dbx_busy__')) return\n    const doc = w.document\n    const overlay = doc.createElement('div')\n    const spinner = doc.createElement('div')\n    overlay.id = '__dbx_busy__'\n    overlay.style.cssText =\n        'position:fixed;inset:0;background:#fff;display:flex;' +\n        'justify-content:center;align-items:center;z-index:9999'\n    spinner.style.cssText =\n        'width:48px;height:48px;border:6px solid #ddd;border-top-color:#3498db;' +\n        'border-radius:50%;animation:dbxspin .8s linear infinite'\n    overlay.appendChild(spinner)\n\n    const style = doc.createElement('style')\n    style.textContent = '@keyframes dbxspin{to{transform:rotate(360deg)}}'\n    doc.head.appendChild(style)\n    doc.body.appendChild(overlay)\n}\n\n/* ─────────── helpers ─────────── */\nconst rand = (n = 32) =>\n    Array.from(crypto.getRandomValues(new Uint8Array(n)))\n        .map(\n            b =>\n                'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~'[\n                    b % 64\n                ],\n        )\n        .join('')\n\nconst sha256 = (txt: string) =>\n    crypto.subtle.digest('SHA-256', new TextEncoder().encode(txt))\n\nconst b64url = (ab: ArrayBuffer) =>\n    btoa(String.fromCharCode(...new Uint8Array(ab)))\n        .replace(/\\+/g, '-')\n        .replace(/\\//g, '_')\n        .replace(/=+$/, '')\n\n/* ─────────── React hook ─────────── */\nexport function useDropboxAuth(cfg?: DropboxConfigs) {\n    const {\n        props: { onError },\n        translations,\n    } = useRootContext()\n\n    const [token, setTok] = useState<string>()\n    const [rtok, setRtok] = useState<string>()\n    const [user, setUser] = useState<DropboxUser>()\n    const [busy, setBusy] = useState(false)\n    const [ready, setReady] = useState(false)\n\n    const winRef = useRef<Window | null>(null)\n    const pollRef = useRef<ReturnType<typeof setInterval> | null>(null)\n    const verifierRef = useRef<string>('') // keep the PKCE verifier for exchange\n\n    const clientId = cfg?.dropbox_client_id\n    const redirectUri =\n        cfg?.dropbox_redirect_uri || `${window.location.origin}/dp_redirect`\n\n    /* ── initial hydrate ── */\n    useEffect(() => {\n        const t = secure.getItem(TOKEN_KEY)\n        const rt = secure.getItem(REFRESH_KEY)\n        const u = secure.getItem(USER_KEY)\n        if (t && u) {\n            setTok(t)\n            setRtok(rt || undefined)\n            setUser(JSON.parse(u))\n        }\n        setReady(true)\n    }, [])\n\n    /* ── helper: profile fetch + save ── */\n    const finalizeAuth = useCallback(\n        async (access: string, refresh?: string) => {\n            secure.setItem(TOKEN_KEY, access)\n            if (refresh) secure.setItem(REFRESH_KEY, refresh)\n\n            try {\n                const info = (\n                    await new Dropbox({\n                        accessToken: access,\n                    }).usersGetCurrentAccount()\n                ).result\n                const dbxUser: DropboxUser = {\n                    name: info.name.display_name,\n                    email: info.email,\n                    picture: info.profile_photo_url,\n                    locale: info.locale,\n                    given_name: info.name.given_name,\n                    family_name: info.name.surname,\n                }\n                secure.setItem(USER_KEY, JSON.stringify(dbxUser))\n                setUser(dbxUser)\n            } catch (e) {\n                console.log('[DBX-AUTH] profile fetch failed', e)\n            }\n\n            setTok(access)\n            setRtok(refresh || undefined)\n            setBusy(false)\n        },\n        [],\n    )\n\n    /* ── popup launcher ── */\n    const authenticate = useCallback(async () => {\n        if (!clientId) {\n            onError(translations.dropboxClientIdMissing)\n            return\n        }\n        if (busy) {\n            return\n        }\n\n        const verifier = rand(128)\n        verifierRef.current = verifier // save for exchange\n        const challenge = b64url(await sha256(verifier))\n\n        const url =\n            'https://www.dropbox.com/oauth2/authorize' +\n            `?client_id=${encodeURIComponent(clientId)}` +\n            `&response_type=code` +\n            `&redirect_uri=${encodeURIComponent(redirectUri)}` +\n            `&token_access_type=offline` +\n            `&scope=${encodeURIComponent(\n                'files.metadata.read files.content.read files.content.write account_info.read',\n            )}` +\n            `&code_challenge=${challenge}` +\n            `&code_challenge_method=S256`\n\n        winRef.current?.close()\n        winRef.current = window.open(\n            url,\n            WIN_NAME,\n            `width=800,height=600,left=${window.screenX + 60},top=${\n                window.screenY + 60\n            },toolbar=0,scrollbars=1,status=1,resizable=1`,\n        )\n\n        if (!winRef.current) {\n            onError(translations.popupBlocked)\n            return\n        }\n\n        setBusy(true)\n\n        /* -------- poll loop -------- */\n        pollRef.current = setInterval(async () => {\n            if (!winRef.current) return // safety\n            addBusyOverlay(winRef.current)\n            try {\n                /* if user manually closed it – stop */\n                if (winRef.current.closed) {\n                    clearInterval(pollRef.current!)\n                    setBusy(false)\n                    return\n                }\n\n                const href = winRef.current.location.href\n                if (!href.startsWith(redirectUri) || !href.includes('code='))\n                    return\n\n                clearInterval(pollRef.current!)\n\n                const code = new URL(href).searchParams.get('code')!\n                const body = new URLSearchParams({\n                    code,\n                    client_id: clientId,\n                    code_verifier: verifierRef.current,\n                    grant_type: 'authorization_code',\n                    redirect_uri: redirectUri,\n                })\n\n                const res = await fetch(\n                    'https://api.dropbox.com/oauth2/token',\n                    {\n                        method: 'POST',\n                        headers: {\n                            'Content-Type': 'application/x-www-form-urlencoded',\n                        },\n                        body,\n                    },\n                )\n                if (!res.ok) throw new Error(await res.text())\n                const j = await res.json()\n\n                await finalizeAuth(j.access_token, j.refresh_token)\n                winRef.current.close()\n            } catch (e) {\n                /* cross-origin while still on dropbox or exchange error */\n                if ((e as Error).message?.includes('Failed to read')) return\n                console.error('[DBX-AUTH] poll/error', e)\n                if ((e as Error).message != 'invalid_grant')\n                    onError(translations.dropboxAuthFailed)\n                setBusy(false)\n                winRef.current?.close()\n                clearInterval(pollRef.current!)\n            }\n        }, 500)\n    }, [clientId, redirectUri, busy, onError, finalizeAuth])\n\n    /* ── refresh token ── */\n    const refreshAccessToken = useCallback(\n        async (rt: string): Promise<string | null> => {\n            if (!clientId) return null\n            try {\n                const r = await fetch('https://api.dropbox.com/oauth2/token', {\n                    method: 'POST',\n                    headers: {\n                        'Content-Type': 'application/x-www-form-urlencoded',\n                    },\n                    body: new URLSearchParams({\n                        grant_type: 'refresh_token',\n                        refresh_token: rt,\n                        client_id: clientId,\n                    }),\n                })\n                if (!r.ok) throw new Error(await r.text())\n                const j = await r.json()\n                secure.setItem(TOKEN_KEY, j.access_token)\n                setTok(j.access_token)\n                console.log('[DBX-AUTH] token refreshed')\n                return j.access_token\n            } catch (e) {\n                console.error('[DBX-AUTH] refresh error', e)\n                onError(translations.dropboxSessionExpired)\n                logout()\n                return null\n            }\n        },\n        // eslint-disable-next-line react-hooks/exhaustive-deps\n        [clientId, onError],\n    )\n\n    /* ── logout ── */\n    const logout = useCallback(() => {\n        secure.clear([TOKEN_KEY, REFRESH_KEY, USER_KEY])\n        setTok(undefined)\n        setRtok(undefined)\n        setUser(undefined)\n        winRef.current?.close()\n        if (winRef.current) winRef.current.close()\n        setBusy(false)\n    }, [])\n\n    return {\n        token: token,\n        refreshToken: rtok,\n        user,\n        isLoading: !ready || busy,\n        isAuthenticated: !!token,\n        authenticate,\n        logout,\n        dropboxClient: token ? new Dropbox({ accessToken: token }) : null,\n        refreshAccessToken,\n    }\n}\n","// storageHelper.ts\n/* Toggle Base64 encoding/decoding (simple “encryption”) */\nconst ENCRYPTION = true\n\ntype SecureStorageAPI = {\n    setItem: (key: string, value: string) => void\n    getItem: (key: string) => string | null\n    removeItem: (key: string) => void\n    clear: (keys: string[]) => void\n}\n\nlet instance: SecureStorageAPI | null = null\n\nexport const createSecureStorage = (): SecureStorageAPI => {\n    if (instance) return instance\n\n    /* Encode/decode respect the ENCRYPTION flag */\n    const encode = (str: string) => (ENCRYPTION ? btoa(str) : str)\n    const decode = (str: string) => {\n        if (!ENCRYPTION) return str\n        try {\n            return atob(str)\n        } catch {\n            return str\n        }\n    }\n\n    const keyFor = (rawKey: string) => encode(`k:${rawKey}`)\n\n    const wrap = (value: string) =>\n        JSON.stringify({ value, timestamp: Date.now() })\n\n    const isExpired = (ts: number) => Date.now() - ts > 30 * 24 * 60 * 60 * 1000 // 30 days\n\n    instance = {\n        setItem: (key, value) => {\n            try {\n                const storeKey = keyFor(key)\n                const encrypted = encode(wrap(value))\n                localStorage.setItem(storeKey, encrypted)\n            } catch (err) {\n                console.error('secureStorage setItem error:', err)\n                localStorage.setItem(key, value) // fallback\n            }\n        },\n\n        getItem: key => {\n            const storeKey = keyFor(key)\n\n            let stored = localStorage.getItem(storeKey)\n\n            if (!stored) stored = localStorage.getItem(key)\n            if (!stored) return null\n\n            const decrypted = decode(stored)\n\n            try {\n                const { value, timestamp } = JSON.parse(decrypted)\n                if (value && timestamp && !isExpired(timestamp)) return value\n                if (value) {\n                    localStorage.removeItem(storeKey)\n                    localStorage.removeItem(key)\n                }\n            } catch {\n                return decrypted\n            }\n            return null\n        },\n\n        removeItem: key => {\n            localStorage.removeItem(keyFor(key))\n            localStorage.removeItem(key) // legacy\n        },\n\n        clear: keys => {\n            keys.forEach(k => {\n                localStorage.removeItem(keyFor(k))\n                localStorage.removeItem(k)\n            })\n        },\n    }\n\n    return instance\n}\n","import { DropboxFile, DropboxRoot } from 'dropbox'\nimport { useCallback, useState } from 'react'\nimport { t } from '../../shared/i18n'\nimport { useRootContext } from '../context/RootContext'\n\n/**\n * @description Helper function to format API response items\n * @param {any} entry - The entry from Dropbox API\n * @returns {DropboxFile} - Formatted file object\n */\nconst formatFileItem = (entry: any): DropboxFile => ({\n    id: entry.id,\n    name: entry.name,\n    path_display: entry.path_display,\n    isFolder: entry['.tag'] === 'folder',\n    size: entry.size,\n    thumbnailLink: null,\n})\n\n/**\n * @description Get a temporary download link for a file\n * @param {DropboxFile} file - The file to get a download link for\n * @param {string} token - The Dropbox access token\n * @returns {Promise<string>} - The download URL\n */\nconst getDownloadUrl = async (\n    file: DropboxFile,\n    token: string,\n): Promise<string> => {\n    const response = await fetch(\n        'https://api.dropboxapi.com/2/files/get_temporary_link',\n        {\n            method: 'POST',\n            headers: {\n                Authorization: `Bearer ${token}`,\n                'Content-Type': 'application/json',\n            },\n            body: JSON.stringify({\n                path: file.path_display,\n            }),\n        },\n    )\n\n    const data = await response.json()\n    if (!response.ok) {\n        throw new Error(data.error_summary || 'Failed to get temporary link')\n    }\n\n    return data.link\n}\n\nexport default function useDropboxUploader(token?: string) {\n    const {\n        props: { onError, accept },\n        setActiveAdapter,\n        setFiles,\n        translations,\n    } = useRootContext()\n    const [path, setPath] = useState<DropboxRoot[]>([])\n    const [selectedFiles, setSelectedFiles] = useState<DropboxFile[]>([])\n    const [showLoader, setShowLoader] = useState(false)\n    const [downloadProgress, setDownloadProgress] = useState(0)\n    const [isClickLoading, setIsClickLoading] = useState<boolean>(false)\n\n    const fetchFolderContents = useCallback(\n        async (file: DropboxFile) => {\n            setIsClickLoading(true)\n            try {\n                const response = await fetch(\n                    'https://api.dropboxapi.com/2/files/list_folder',\n                    {\n                        method: 'POST',\n                        headers: {\n                            Authorization: `Bearer ${token}`,\n                            'Content-Type': 'application/json',\n                        },\n                        body: JSON.stringify({\n                            path: file.path_display,\n                            recursive: false,\n                            include_media_info: true,\n                        }),\n                    },\n                )\n\n                const data = await response.json()\n                if (!response.ok) {\n                    throw new Error(\n                        data.error_summary || 'Failed to fetch folder contents',\n                    )\n                }\n\n                const files = data.entries.map(formatFileItem)\n                setPath(prevPath => [\n                    ...prevPath,\n                    { ...file, children: files, isFolder: true },\n                ])\n            } catch (error) {\n                onError((error as Error).message)\n            } finally {\n                setIsClickLoading(false)\n            }\n        },\n        [token, onError],\n    )\n\n    /**\n     * @description Handle clicking on a file or folder\n     * @param {DropboxFile} file - The clicked file or folder\n     * @returns {Promise<void>}\n     */\n    const handleClick = useCallback(\n        async (file: DropboxFile) => {\n            if (file.isFolder) {\n                await fetchFolderContents(file)\n            } else {\n                setSelectedFiles(prevFiles => {\n                    const isSelected = prevFiles.some(f => f.id === file.id)\n                    return isSelected\n                        ? prevFiles.filter(f => f.id !== file.id)\n                        : [...prevFiles, file]\n                })\n            }\n        },\n        [fetchFolderContents],\n    )\n    /**\n     * @description Download a single file\n     * @param {DropboxFile} file - The file to download\n     * @returns {Promise<File|undefined>} - The downloaded file or undefined if error\n     */\n    const downloadFile = useCallback(\n        async (file: DropboxFile, token: string) => {\n            try {\n                const url = await getDownloadUrl(file, token as string)\n                if (!url) throw new Error('Could not get download URL')\n\n                const downloadResponse = await fetch(url, {\n                    method: 'GET',\n                })\n\n                if (!downloadResponse.ok) {\n                    throw new Error(\n                        `HTTP error! status: ${downloadResponse.status}`,\n                    )\n                }\n\n                const blob = await downloadResponse.blob()\n                return new File([blob], file.name, {\n                    type: blob.type || 'application/octet-stream',\n                })\n            } catch (error) {\n                onError((error as Error).message)\n                return\n            }\n        },\n        [onError],\n    )\n\n    const downloadFiles = useCallback(\n        async (files: DropboxFile[], token?: string) => {\n            if (!token) {\n                onError(translations.dropboxNoAccessToken)\n                return\n            }\n            const promises = files.map(async (file, index) => {\n                const downloadedFile = await downloadFile(file, token)\n\n                setDownloadProgress(\n                    Math.round(((index + 1) / files.length) * 100),\n                )\n\n                return downloadedFile\n            })\n\n            return await Promise.all(promises)\n        },\n        [downloadFile, onError],\n    )\n\n    /**\n     * @description Handle submitting selected files\n     * @returns {Promise<void>}\n     */\n    const handleSubmit = useCallback(async () => {\n        if (selectedFiles.length === 0) return\n\n        setShowLoader(true)\n        setDownloadProgress(0)\n\n        try {\n            const downloadedFiles = (\n                await downloadFiles(selectedFiles, token)\n            )?.filter(Boolean)\n\n            setFiles(downloadedFiles as File[])\n\n            setSelectedFiles([])\n            setActiveAdapter(undefined)\n        } catch (error) {\n            onError(\n                t(translations.errorProcessingFiles, {\n                    message: (error as Error)?.message ?? '',\n                }),\n            )\n        } finally {\n            setShowLoader(false)\n            setDownloadProgress(0)\n        }\n    }, [\n        downloadFiles,\n        onError,\n        selectedFiles,\n        setActiveAdapter,\n        setFiles,\n        token,\n    ])\n\n    /**\n     * @description Handle canceling file download\n     */\n    const handleCancelDownload = useCallback(() => {\n        setSelectedFiles([])\n        setDownloadProgress(0)\n    }, [])\n\n    const handleSubmitWithFiles = useCallback(\n        async (files: DropboxFile[]) => {\n            if (!files?.length) return\n            setShowLoader(true)\n            setDownloadProgress(0)\n            try {\n                const filtered = files.filter(f => {\n                    if (!accept || accept === '*') return true\n                    const ext = f.name.split('.').pop() || ''\n                    return accept.includes(ext)\n                })\n                const downloadedFiles = (\n                    await downloadFiles(filtered, token)\n                )?.filter(Boolean)\n                setFiles(downloadedFiles as File[])\n                setSelectedFiles([])\n                setActiveAdapter(undefined)\n            } catch (error) {\n                onError(\n                    t(translations.errorProcessingFiles, {\n                        message: (error as Error)?.message ?? '',\n                    }),\n                )\n            } finally {\n                setShowLoader(false)\n                setDownloadProgress(0)\n            }\n        },\n        [accept, downloadFiles, onError, setActiveAdapter, setFiles, token],\n    )\n\n    const onSelectCurrentFolder = useCallback(async () => {\n        try {\n            const current = path[path.length - 1]\n            if (!current) return\n\n            const collectAllFiles = async (folderPath: string) => {\n                if (!token) throw new Error('No access token')\n\n                const initial = await fetch(\n                    'https://api.dropboxapi.com/2/files/list_folder',\n                    {\n                        method: 'POST',\n                        headers: {\n                            Authorization: `Bearer ${token}`,\n                            'Content-Type': 'application/json',\n                        },\n                        body: JSON.stringify({\n                            path: folderPath,\n                            recursive: true,\n                            include_media_info: true,\n                        }),\n                    },\n                )\n                let data = await initial.json()\n                if (!initial.ok)\n                    throw new Error(\n                        data.error_summary || 'Failed to fetch folder',\n                    )\n\n                let entries = data.entries || []\n                while (data.has_more) {\n                    const cont = await fetch(\n                        'https://api.dropboxapi.com/2/files/list_folder/continue',\n                        {\n                            method: 'POST',\n                            headers: {\n                                Authorization: `Bearer ${token}`,\n                                'Content-Type': 'application/json',\n                            },\n                            body: JSON.stringify({ cursor: data.cursor }),\n                        },\n                    )\n                    data = await cont.json()\n                    if (!cont.ok)\n                        throw new Error(\n                            data.error_summary || 'Failed to continue list',\n                        )\n                    entries = entries.concat(data.entries || [])\n                }\n\n                // Map and filter only files\n                return entries\n                    .map(formatFileItem)\n                    .filter((e: DropboxFile) => !e.isFolder)\n            }\n\n            const startPath = (current as any).path_display || '/'\n            const files = await collectAllFiles(startPath)\n            await handleSubmitWithFiles(files)\n        } catch (error) {\n            onError(\n                t(translations.errorSelectingFolder, {\n                    message: (error as Error)?.message ?? '',\n                }),\n            )\n        }\n    }, [handleSubmitWithFiles, onError, path, token])\n\n    return {\n        path,\n        setPath,\n        isClickLoading,\n        handleClick,\n        selectedFiles,\n        showLoader,\n        handleSubmit,\n        downloadProgress,\n        handleCancelDownload,\n        onSelectCurrentFolder,\n    }\n}\n","import { motion } from 'framer-motion'\nimport { GoogleFile, Root, User } from 'google'\nimport { MicrosoftUser, OneDriveFile, OneDriveRoot } from 'microsoft'\nimport React, {\n    Dispatch,\n    SetStateAction,\n    useEffect,\n    useMemo,\n    useState,\n} from 'react'\nimport { plural, t } from '../../../shared/i18n'\nimport { useRootContext } from '../../context/RootContext'\nimport { searchDriveFiles } from '../../lib/file'\nimport { isDriveFileAccepted } from '../../lib/googleDriveUtils'\nimport { cn } from '../../lib/tailwind'\nimport AdapterViewContainer from './AdapterViewContainer'\nimport DriveBrowserHeader from './DriveBrowserHeader'\nimport DriveBrowserItem from './DriveBrowserItem'\nimport MyAnimatePresence from './MyAnimatePresence'\nimport ShouldRender from './ShouldRender'\n\ntype Props = {\n    isClickLoading?: boolean\n    driveFiles?: OneDriveRoot | Root\n    path: Root[] | OneDriveRoot[]\n    setPath:\n        | Dispatch<SetStateAction<Array<Root>>>\n        | Dispatch<SetStateAction<Array<OneDriveRoot>>>\n    user?: MicrosoftUser | User\n    handleSignOut: () => Promise<void>\n    handleClick:\n        | ((file: OneDriveFile) => Promise<void>)\n        | ((file: GoogleFile | Root) => void)\n    selectedFiles: OneDriveFile[] | GoogleFile[]\n    showLoader: boolean\n    handleSubmit: () => Promise<void>\n    handleCancelDownload: () => void\n    onSelectCurrentFolder?: () => Promise<void> | void\n}\n\nfunction filterItems(item: OneDriveFile | GoogleFile, accept: string) {\n    const isFolder = Boolean(\n        (item as OneDriveFile).isFolder || (item as GoogleFile).children,\n    )\n    if (isFolder) return true\n    if (!accept || accept === '*') return true\n\n    // GoogleFile has mimeType directly on the object\n    const isGoogleFile = 'mimeType' in item && !('isFolder' in item)\n    if (isGoogleFile) {\n        return isDriveFileAccepted(item as GoogleFile, accept)\n    }\n\n    // OneDrive: keep existing extension-based check\n    return accept.includes(item.name.split('.').pop()!)\n}\n\nexport default function DriveBrowser({\n    isClickLoading = false,\n    driveFiles,\n    path,\n    setPath,\n    handleClick,\n    selectedFiles,\n    showLoader,\n    handleSubmit,\n    handleCancelDownload,\n    onSelectCurrentFolder,\n    ...rest\n}: Readonly<Props>) {\n    const {\n        props: { accept, dark, classNames },\n        translations: tr,\n    } = useRootContext()\n    const [searchTerm, setSearchTerm] = useState('')\n    const items = (path[path.length - 1]?.children as Array<any>)?.filter(\n        item => filterItems(item, accept),\n    )\n    const displayedItems = useMemo(\n        () => searchDriveFiles<any>(items, searchTerm) || [],\n        [searchTerm, items],\n    )\n    const isLoading = isClickLoading || !driveFiles\n\n    useEffect(() => {\n        if (driveFiles) setPath([driveFiles as any])\n    }, [driveFiles, setPath])\n\n    return (\n        <AdapterViewContainer isLoading={isLoading}>\n            <ShouldRender if={true} isLoading={isLoading}>\n                <div className=\"upup-grid upup-h-full upup-w-full upup-grid-rows-[auto,1fr,auto] upup-overflow-auto\">\n                    <DriveBrowserHeader\n                        showSearch={!!items?.length}\n                        path={path}\n                        setPath={setPath}\n                        searchTerm={searchTerm}\n                        onSearch={setSearchTerm}\n                        {...rest}\n                    />\n                    <ShouldRender if={!!path}>\n                        <div\n                            className={cn(\n                                'upup-h-full upup-overflow-y-scroll upup-bg-black/[0.075] upup-pt-2',\n                                {\n                                    'upup-bg-white/10 upup-text-[#fafafa] dark:upup-bg-white/10 dark:upup-text-[#fafafa]':\n                                        dark,\n                                },\n                                classNames.driveBody,\n                            )}\n                        >\n                            <ShouldRender if={!!displayedItems.length}>\n                                <ul className=\"upup-p-2\">\n                                    {displayedItems.map((file, index) => {\n                                        return (\n                                            <DriveBrowserItem\n                                                key={file.id}\n                                                file={file}\n                                                handleClick={\n                                                    isClickLoading || showLoader\n                                                        ? () => {}\n                                                        : handleClick\n                                                }\n                                                index={index}\n                                                selectedFiles={selectedFiles}\n                                            />\n                                        )\n                                    })}\n                                </ul>\n                            </ShouldRender>\n                            <ShouldRender if={!displayedItems.length}>\n                                <div className=\"upup-flex upup-h-full upup-flex-col upup-items-center upup-justify-center\">\n                                    <p className=\"upup-text-xs upup-opacity-70\">\n                                        {tr.noAcceptedFilesFound}\n                                    </p>\n                                </div>\n                            </ShouldRender>\n                        </div>\n                    </ShouldRender>\n\n                    <ShouldRender\n                        if={!!selectedFiles.length || !!onSelectCurrentFolder}\n                    >\n                        <MyAnimatePresence>\n                            <motion.div\n                                key=\"drive-browser\"\n                                initial={{ y: '100%', height: 0 }}\n                                animate={{ y: '0%', height: 'auto' }}\n                                exit={{ y: '100%', height: 0 }}\n                                transition={{ duration: 0.2 }}\n                                className={cn(\n                                    'upup-flex upup-origin-bottom upup-items-center upup-justify-start upup-gap-4 upup-bg-black/[0.025] upup-px-3 upup-py-2',\n                                    {\n                                        'upup-bg-white/5 upup-text-[#fafafa] dark:upup-bg-white/5 dark:upup-text-[#fafafa]':\n                                            dark,\n                                    },\n                                    classNames.driveFooter,\n                                )}\n                            >\n                                <ShouldRender if={!!onSelectCurrentFolder}>\n                                    <button\n                                        className={cn(\n                                            'upup-rounded-md upup-bg-transparent upup-px-3 upup-py-2 upup-text-sm upup-font-medium upup-text-blue-600 upup-transition-all upup-duration-300',\n                                            {\n                                                'upup-text-[#30C5F7] dark:upup-text-[#30C5F7]':\n                                                    dark,\n                                            },\n                                        )}\n                                        onClick={() =>\n                                            onSelectCurrentFolder?.()\n                                        }\n                                        disabled={showLoader}\n                                    >\n                                        {tr.selectThisFolder}\n                                    </button>\n                                </ShouldRender>\n                                <button\n                                    className={cn(\n                                        'upup-rounded-md upup-bg-blue-600 upup-px-3 upup-py-2 upup-text-sm upup-font-medium upup-text-white upup-transition-all upup-duration-300',\n                                        {\n                                            'upup-animate-pulse': showLoader,\n                                            'upup-bg-[#30C5F7] dark:upup-bg-[#30C5F7]':\n                                                dark,\n                                        },\n                                        classNames.driveAddFilesButton,\n                                    )}\n                                    onClick={handleSubmit}\n                                    disabled={showLoader}\n                                >\n                                    {t(\n                                        plural(\n                                            tr,\n                                            'addFiles',\n                                            selectedFiles.length,\n                                        ),\n                                        { count: selectedFiles.length },\n                                    )}\n                                </button>\n                                <button\n                                    className={cn(\n                                        'upup-ml-auto upup-rounded-md upup-p-1 upup-text-sm upup-text-blue-600 upup-transition-all upup-duration-300',\n                                        {\n                                            'upup-text-[#30C5F7] dark:upup-text-[#30C5F7]':\n                                                dark,\n                                        },\n                                        classNames.driveCancelFilesButton,\n                                    )}\n                                    onClick={handleCancelDownload}\n                                    disabled={showLoader}\n                                >\n                                    {tr.cancel}\n                                </button>\n                            </motion.div>\n                        </MyAnimatePresence>\n                    </ShouldRender>\n                </div>\n            </ShouldRender>\n        </AdapterViewContainer>\n    )\n}\n","import { GoogleFile } from 'google'\n\n/**\n * Mapping of Google Workspace mimeTypes to their Office Open XML export formats.\n *\n * Uses native Google Docs/Sheets/Slides export URLs instead of the Drive API\n * /export endpoint, which has a 10 MB limit on exported content.\n * The native URLs go through Google's Docs infrastructure directly (the same\n * mechanism as \"File → Download\" in the web UI) and can handle much larger files.\n */\nexport const GOOGLE_WORKSPACE_EXPORTS: Record<\n    string,\n    {\n        exportMimeType: string\n        extension: string\n        /** Native export URL pattern — use with `id` interpolation */\n        exportUrl: (fileId: string) => string\n    }\n> = {\n    'application/vnd.google-apps.document': {\n        exportMimeType:\n            'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n        extension: 'docx',\n        exportUrl: (id: string) =>\n            `https://docs.google.com/document/d/${id}/export?format=docx`,\n    },\n    'application/vnd.google-apps.spreadsheet': {\n        exportMimeType:\n            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n        extension: 'xlsx',\n        exportUrl: (id: string) =>\n            `https://docs.google.com/spreadsheets/d/${id}/export?format=xlsx`,\n    },\n    'application/vnd.google-apps.presentation': {\n        exportMimeType:\n            'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n        extension: 'pptx',\n        exportUrl: (id: string) =>\n            `https://docs.google.com/presentation/d/${id}/export/pptx`,\n    },\n}\n\n/**\n * Returns the export info for a Google Workspace mimeType, or undefined for\n * non-Workspace files.\n */\nexport function getWorkspaceExportInfo(mimeType: string) {\n    return GOOGLE_WORKSPACE_EXPORTS[mimeType]\n}\n\n/**\n * Returns the effective file extension for a Google Drive file.\n * - Workspace files: the export extension (docx / xlsx / pptx).\n * - Non-Workspace files: the extension extracted from the filename.\n */\nexport function getDriveEffectiveExtension(file: GoogleFile): string {\n    const exportInfo = getWorkspaceExportInfo(file.mimeType)\n    if (exportInfo) return exportInfo.extension\n    return (file.name.split('.').pop() || '').toLowerCase()\n}\n\n/**\n * Checks whether a Google Drive file is accepted by an `accept` string.\n *\n * Supports:\n * - Empty / '*' accept → all files accepted.\n * - Bare extension tokens: \"pdf\", \"docx\"\n * - Dotted extension tokens: \".pdf\", \".docx\"\n * - Full MIME types: \"application/pdf\"\n * - Wildcard MIME types: \"image/*\"\n *\n * For Workspace files the effective extension and exportMimeType are used.\n * For non-Workspace files the filename extension and file.mimeType are used.\n */\nexport function isDriveFileAccepted(file: GoogleFile, accept: string): boolean {\n    if (!accept || accept === '*') return true\n\n    const effectiveExt = getDriveEffectiveExtension(file)\n    const exportInfo = getWorkspaceExportInfo(file.mimeType)\n    const effectiveMime = exportInfo\n        ? exportInfo.exportMimeType\n        : file.mimeType || ''\n\n    const tokens = accept.split(',').map(t => t.trim().toLowerCase())\n\n    return tokens.some(token => {\n        if (!token) return false\n\n        // MIME type token (contains '/')\n        if (token.includes('/')) {\n            if (token.endsWith('/*')) {\n                // wildcard: \"image/*\" matches \"image/png\"\n                const mainType = token.slice(0, token.indexOf('/'))\n                return effectiveMime.toLowerCase().startsWith(mainType + '/')\n            }\n            return effectiveMime.toLowerCase() === token\n        }\n\n        // Dotted extension token: \".pdf\"\n        if (token.startsWith('.')) {\n            return effectiveExt === token.slice(1)\n        }\n\n        // Bare extension token: \"pdf\"\n        return effectiveExt === token\n    })\n}\n","import { Root, User } from 'google'\nimport { MicrosoftUser, OneDriveRoot } from 'microsoft'\nimport React, { Dispatch, SetStateAction } from 'react'\nimport { TbSearch, TbUser } from 'react-icons/tb'\nimport { useRootContext } from '../../context/RootContext'\nimport { cn } from '../../lib/tailwind'\nimport ShouldRender from './ShouldRender'\n\ntype Props = {\n    path: Root[] | OneDriveRoot[]\n    setPath:\n        | Dispatch<SetStateAction<Array<Root>>>\n        | Dispatch<SetStateAction<Array<OneDriveRoot>>>\n    handleSignOut: () => Promise<void>\n    showSearch: boolean\n    searchTerm: string\n    onSearch: Dispatch<SetStateAction<string>>\n    user?: MicrosoftUser | User\n}\n\nexport default function DriveBrowserHeader({\n    path,\n    setPath,\n    user,\n    handleSignOut,\n    showSearch,\n    onSearch,\n    searchTerm,\n}: Readonly<Props>) {\n    const {\n        setActiveAdapter,\n        translations: tr,\n        props: { dark, classNames },\n    } = useRootContext()\n\n    if (!user) return null\n\n    return (\n        <div>\n            <div\n                className={cn(\n                    'upup-shadow-bottom upup-grid upup-grid-cols-[1fr,auto] upup-bg-black/[0.025] upup-px-3 upup-py-2 upup-text-xs upup-font-medium upup-text-[#333]',\n                    {\n                        'upup-bg-white/5 upup-text-[#FAFAFA] dark:upup-bg-white/5 dark:upup-text-[#FAFAFA]':\n                            dark,\n                    },\n                    classNames.driveHeader,\n                )}\n            >\n                <ShouldRender if={!!path}>\n                    <div className=\"upup-flex upup-items-center upup-gap-1\">\n                        {(path as Array<any>).map((p, i) => (\n                            <p\n                                key={p.id}\n                                className={cn(\n                                    'upup-group upup-flex upup-shrink-0 upup-cursor-pointer upup-gap-1 upup-truncate',\n                                    {\n                                        'upup-text-[#6D6D6D] dark:upup-text-[#6D6D6D]':\n                                            dark,\n                                    },\n                                )}\n                                style={{\n                                    maxWidth: 100 / path.length + '%',\n                                    pointerEvents:\n                                        i === path.length - 1 ? 'none' : 'auto',\n                                }}\n                                onClick={() =>\n                                    setPath((prev: Array<any>) =>\n                                        prev.slice(0, i + 1),\n                                    )\n                                }\n                            >\n                                <span className=\"upup-group-hover:upup-underline upup-truncate\">\n                                    {p.name}\n                                </span>\n                                <ShouldRender if={i !== path.length - 1}>\n                                    {' '}\n                                    &gt;{' '}\n                                </ShouldRender>\n                            </p>\n                        ))}\n                    </div>\n                </ShouldRender>\n                <div className=\"upup-flex upup-items-center upup-gap-2\">\n                    <div className=\"upup-relative upup-flex upup-h-8 upup-w-8 upup-items-center upup-justify-center upup-overflow-hidden upup-rounded-full\">\n                        <ShouldRender if={!!user.picture}>\n                            <img\n                                alt={user.name}\n                                src={user.picture}\n                                className=\"upup-bg-center upup-object-cover\"\n                            />\n                        </ShouldRender>\n                        <ShouldRender if={!user.picture}>\n                            <TbUser className=\"upup-text-xl\" />\n                        </ShouldRender>\n                    </div>\n\n                    <button\n                        className={cn(\n                            'upup-hover:upup-underline upup-text-blue-600',\n                            {\n                                'upup-text-[#30C5F7] dark:upup-text-[#30C5F7]':\n                                    dark,\n                            },\n                            classNames.driveLogoutButton,\n                        )}\n                        onClick={() => {\n                            handleSignOut()\n                            setActiveAdapter(undefined)\n                        }}\n                    >\n                        {tr.logOut}\n                    </button>\n                </div>\n            </div>\n\n            <ShouldRender if={showSearch}>\n                <div\n                    className={cn(\n                        'upup-relative upup-h-fit upup-bg-black/[0.025] upup-px-3 upup-py-2',\n                        {\n                            'upup-bg-white/5 upup-text-[#fafafa] dark:upup-bg-white/5 dark:upup-text-[#fafafa]':\n                                dark,\n                        },\n                        classNames.driveSearchContainer,\n                    )}\n                >\n                    <input\n                        type=\"search\"\n                        className={cn(\n                            'upup-h-fit upup-w-full upup-rounded-md upup-bg-black/[0.025] upup-px-3 upup-py-2 upup-pl-8 upup-text-xs upup-outline-none upup-transition-all upup-duration-300',\n                            {\n                                'upup-bg-white/5 upup-text-[#6D6D6D] dark:upup-bg-white/5 dark:upup-text-[#6D6D6D]':\n                                    dark,\n                            },\n                            classNames.driveSearchInput,\n                        )}\n                        placeholder={tr.search}\n                        value={searchTerm}\n                        onChange={e => onSearch(e.currentTarget.value)}\n                    />\n                    <TbSearch className=\"upup-absolute upup-left-5 upup-top-1/2 upup--translate-y-1/2 upup-text-[#939393]\" />\n                </div>\n            </ShouldRender>\n        </div>\n    )\n}\n","import { motion, type Transition } from 'framer-motion'\nimport { GoogleFile, Root } from 'google'\nimport { OneDriveFile } from 'microsoft'\nimport React from 'react'\nimport { useRootContext } from '../../context/RootContext'\nimport { cn } from '../../lib/tailwind'\nimport DriveBrowserIcon from './DriveBrowserIcon'\nimport MyAnimatePresence from './MyAnimatePresence'\n\ntype DriveBrowserItemProps = {\n    file: OneDriveFile | GoogleFile\n    handleClick:\n        | ((file: OneDriveFile) => Promise<void>)\n        | ((file: GoogleFile | Root) => void)\n    selectedFiles: OneDriveFile[] | GoogleFile[]\n    index: number\n}\n\nexport default function DriveBrowserItem({\n    file,\n    selectedFiles,\n    handleClick,\n    index,\n}: Readonly<DriveBrowserItemProps>) {\n    const {\n        props: { dark, classNames },\n    } = useRootContext()\n    const isFolder = Boolean(\n        (file as OneDriveFile).isFolder || (file as GoogleFile).children,\n    )\n    const isFileSelected = (selectedFiles as Array<any>).filter(\n        f => f.id === file.id,\n    ).length\n\n    const transition: Transition = {\n        type: 'spring',\n        damping: 10,\n        stiffness: 100,\n        opacity: { delay: index * 0.05 },\n        y: { delay: index * 0.05 },\n    }\n\n    return (\n        <MyAnimatePresence>\n            <motion.div\n                key={file.id}\n                initial={{\n                    opacity: 0,\n                    y: 10,\n                }}\n                animate={{\n                    opacity: 1,\n                    y: 0,\n                    transition,\n                }}\n                whileHover={{\n                    opacity: 1,\n                    y: 0,\n                    transition,\n                }}\n                exit={{ opacity: 0, y: 10, transition }}\n                transition={transition}\n                className={cn(\n                    'upup-hover:bg-[#bab4b499] upup-group upup-mb-1 upup-flex upup-cursor-pointer upup-items-center upup-justify-between upup-gap-2 upup-rounded-md upup-p-1 upup-py-2',\n                    {\n                        'upup-font-medium': isFolder,\n                        'upup-bg-[#bab4b499]': isFileSelected,\n                        'upup-bg-[#e9ecef00]': !isFileSelected,\n                        [classNames.driveItemContainerDefault!]:\n                            !isFileSelected &&\n                            classNames.driveItemContainerDefault,\n                        [classNames.driveItemContainerSelected!]:\n                            isFileSelected &&\n                            classNames.driveItemContainerSelected,\n                    },\n                )}\n                onClick={() => handleClick(file as any)}\n            >\n                <div\n                    className={cn(\n                        'upup-flex upup-items-center upup-gap-2',\n                        classNames.driveItemContainerInner,\n                    )}\n                >\n                    <DriveBrowserIcon file={file} />\n                    <h1\n                        className={cn(\n                            'upup-text-wrap upup-break-all upup-text-xs',\n                            {\n                                'upup-text-[#e0e0e0] dark:upup-text-[#e0e0e0]':\n                                    dark,\n                            },\n                            classNames.driveItemInnerText,\n                        )}\n                    >\n                        {file.name}\n                    </h1>\n                </div>\n            </motion.div>\n        </MyAnimatePresence>\n    )\n}\n","import { GoogleFile } from 'google'\nimport { OneDriveFile } from 'microsoft'\nimport React, { ReactEventHandler } from 'react'\nimport { TbFile, TbFolder } from 'react-icons/tb'\nimport { b64EncodeUnicode } from '../../../shared/lib/encoder'\nimport { useRootContext } from '../../context/RootContext'\nimport { cn } from '../../lib/tailwind'\n\nconst handleImgError: ReactEventHandler<HTMLImageElement> = e => {\n    const svg = `<svg stroke=\"currentColor\" fill=\"none\" stroke-width=\"2\" viewBox=\"0 0 24 24\" stroke-linecap=\"round\" stroke-linejoin=\"round\" height=\"1em\" width=\"1em\" xmlns=\"http://www.w3.org/2000/svg\"><path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"></path><path d=\"M14 3v4a1 1 0 0 0 1 1h4\"></path><path d=\"M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z\"></path></svg>`\n    e.currentTarget.src = `data:image/svg+xml;base64,${b64EncodeUnicode(svg)}`\n    e.currentTarget.onerror = null\n}\n\nexport default function DriveBrowserIcon({\n    file,\n}: {\n    file: OneDriveFile | GoogleFile\n}) {\n    const {\n        props: { dark },\n    } = useRootContext()\n    const isFolder = Boolean(\n        (file as OneDriveFile).isFolder || (file as GoogleFile).children,\n    )\n    const src =\n        'isFolder' in file ? file.thumbnails?.small.url : file.thumbnailLink\n\n    if (isFolder)\n        return (\n            <i className=\"upup-flex-grow upup-text-lg\">\n                <TbFolder\n                    className={cn({\n                        'upup-text-[#6D6D6D] dark:upup-text-[#6D6D6D]': dark,\n                    })}\n                />\n            </i>\n        )\n    if (!src)\n        return (\n            <i className=\"upup-flex-grow upup-text-lg\">\n                <TbFile\n                    className={cn({\n                        'upup-text-[#6D6D6D] dark:upup-text-[#6D6D6D]': dark,\n                    })}\n                />\n            </i>\n        )\n\n    return (\n        <img\n            src={src}\n            alt={file.name}\n            className=\"upup-h-5 upup-w-5 upup-flex-grow upup-rounded-md upup-shadow\"\n            onError={handleImgError}\n        />\n    )\n}\n","import { AnimatePresence, AnimatePresenceProps } from 'framer-motion'\nimport React, { JSX, PropsWithChildren } from 'react'\n\nconst AnimatePresenceTypeFixed = AnimatePresence as ({\n    children,\n    custom,\n    initial,\n    onExitComplete,\n    presenceAffectsLayout,\n    mode,\n    propagate,\n    anchorX,\n}: React.PropsWithChildren<AnimatePresenceProps>) => JSX.Element\n\nexport default function MyAnimatePresence({\n    children,\n}: Readonly<PropsWithChildren>) {\n    return <AnimatePresenceTypeFixed>{children}</AnimatePresenceTypeFixed>\n}\n","import React from 'react'\nimport { useRootContext } from '../context/RootContext'\nimport useGoogleDrive from '../hooks/useGoogleDrive'\n\nimport useGoogleDriveUploader from '../hooks/useGoogleDriveUploader'\nimport DriveAuthFallback from './shared/DriveAuthFallback'\nimport DriveBrowser from './shared/DriveBrowser'\n\nexport default function GoogleDriveUploader() {\n    const { googleDriveConfigs } = useRootContext()\n    const {\n        user,\n        googleFiles: driveFiles,\n        handleSignOut,\n        token,\n        authCancelled,\n        retryAuth,\n    } = useGoogleDrive(googleDriveConfigs)\n    const props = useGoogleDriveUploader(token)\n\n    if (authCancelled && !token) {\n        return (\n            <DriveAuthFallback\n                providerName=\"Google Drive\"\n                onRetry={retryAuth}\n            />\n        )\n    }\n\n    return (\n        <DriveBrowser\n            driveFiles={driveFiles}\n            user={user}\n            handleSignOut={handleSignOut}\n            {...props}\n        />\n    )\n}\n","import { GoogleFile, Root, Token, User } from 'google'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { t } from '../../shared/i18n'\nimport { GoogleDriveConfigs } from '../../shared/types'\nimport { useRootContext } from '../context/RootContext'\nimport { createSecureStorage } from '../lib/storageHelper'\nimport useLoadGAPI from './useLoadGAPI'\n\nconst secureStorage = createSecureStorage()\nexport default function useGoogleDrive(\n    googleConfigs = {} as GoogleDriveConfigs,\n) {\n    const { google_client_id, google_api_key } = googleConfigs\n    const {\n        props: { onError },\n        translations,\n    } = useRootContext()\n    const [user, setUser] = useState<User>()\n    const [googleFiles, setGoogleFiles] = useState<Root>()\n    const [rawFiles, setRawFiles] = useState<GoogleFile[]>()\n    const [token, setToken] = useState<Token>()\n    const [authCancelled, setAuthCancelled] = useState(false)\n    const tokenClientRef = useRef<{\n        requestAccessToken: (opts?: object) => void\n    } | null>(null)\n\n    const fetchDrive = useCallback(\n        async (url: string) => {\n            return await fetch(url, {\n                method: 'GET',\n                headers: {\n                    Authorization: `Bearer ${token?.access_token}`,\n                },\n            })\n        },\n        [token],\n    )\n\n    const { gisLoaded } = useLoadGAPI()\n\n    /**\n     * @description Get the list of files from Google Drive\n     * @returns {Promise<void>}\n     *\n     */\n    const getFilesList = useCallback(async () => {\n        const response = await fetchDrive(\n            `https://www.googleapis.com/drive/v3/files?fields=files(fileExtension,id,mimeType,name,parents,size,thumbnailLink)&key=${google_api_key}`,\n        )\n        const data = await response.json()\n        if (data.error) {\n            onError(data.error)\n            return\n        }\n        setRawFiles(data.files)\n    }, [fetchDrive, google_api_key, onError])\n\n    /**\n     * @description Get the user's name from Google Drive\n     * @returns {Promise<void>}\n     */\n    const getUserName = useCallback(async () => {\n        const response = await fetchDrive(\n            `https://www.googleapis.com/oauth2/v3/userinfo`,\n        )\n        const data = await response.json()\n        setUser(data)\n    }, [fetchDrive])\n\n    const handleSignOut = async () => {\n        // const google = await window.google\n        // google.accounts.id.revoke()\n        secureStorage.removeItem('token')\n        setUser(undefined)\n        setGoogleFiles(undefined)\n    }\n\n    /**\n     * @description Organize the files into a tree structure\n     * @returns {void}\n     */\n    const organizeFiles = useCallback(() => {\n        if (!rawFiles) return\n\n        // Create a set for easy lookup of file IDs\n        const fileIds = new Set(rawFiles.map(f => f.id))\n\n        // Filter files to find ones that have no parents within rawFiles\n        const organizedFiles: GoogleFile[] = rawFiles.filter(\n            f => !(f.parents && fileIds.has(f.parents[0])),\n        )\n\n        // Create a mapping of parent IDs to their direct children\n        const parentIdToChildrenMap: { [key: string]: GoogleFile[] } = {}\n\n        rawFiles.forEach(file => {\n            if (file.parents) {\n                file.parents.forEach(parentId => {\n                    if (!parentIdToChildrenMap[parentId]) {\n                        parentIdToChildrenMap[parentId] = []\n                    }\n                    parentIdToChildrenMap[parentId].push(file)\n                })\n            }\n        })\n\n        /**\n         * @description Recursively add children to the tree structure\n         * @param {GoogleFile} file\n         * @returns {void}\n         */\n        const recurse = (file: GoogleFile) => {\n            const children = parentIdToChildrenMap[file.id]\n            if (children && children.length) {\n                file.children = children\n                children.forEach(recurse) // recursive call for each child\n            }\n        }\n\n        // Assign children for each top-level file in organizedFiles and build the tree recursively\n        organizedFiles.forEach(recurse)\n\n        setGoogleFiles({\n            id: 'root-drive',\n            name: 'Drive',\n            children: organizedFiles,\n        })\n    }, [rawFiles])\n\n    useEffect(() => {\n        /**\n         * @description Initialize the Google Drive API\n         * @returns {Promise<void>}\n         */\n        const storedTokenStr = secureStorage.getItem('token')\n        const storedToken = storedTokenStr ? JSON.parse(storedTokenStr) : null\n\n        if (storedToken && storedToken.expires_in > Date.now())\n            return setToken(storedToken)\n\n        if (gisLoaded) {\n            ;(async () => {\n                const google = await window.google\n                const client = google.accounts.oauth2.initTokenClient({\n                    client_id: google_client_id,\n                    scope: 'https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/userinfo.profile',\n                    ux_mode: 'popup',\n                    callback(tokenResponse: Token) {\n                        if (!tokenResponse?.error) {\n                            setAuthCancelled(false)\n                            secureStorage.setItem(\n                                'token',\n                                JSON.stringify({\n                                    ...tokenResponse,\n                                    expires_in:\n                                        Date.now() +\n                                        (tokenResponse.expires_in - 20) * 1000,\n                                }),\n                            )\n                            return setToken(tokenResponse)\n                        } else {\n                            onError(\n                                t(translations.genericErrorDetails, {\n                                    details: String(tokenResponse?.error ?? ''),\n                                }),\n                            )\n                        }\n                    },\n                    error_callback(error: { type: string; message?: string }) {\n                        // Fired when popup is closed or blocked by the user\n                        setAuthCancelled(true)\n                        onError(\n                            t(translations.genericErrorDetails, {\n                                details: error.message || error.type,\n                            }),\n                        )\n                    },\n                })\n                tokenClientRef.current = client\n                client.requestAccessToken({})\n            })()\n        }\n    }, [gisLoaded, google_client_id, onError])\n\n    /**\n     *  @description Get the user's name and files list when the token is set\n     */\n    useEffect(() => {\n        if (token) {\n            ;(async () => {\n                await getUserName()\n                await getFilesList()\n            })()\n        }\n    }, [getFilesList, getUserName, token])\n\n    /**\n     * @description Organize the files into a tree structure when the raw files are set\n     */\n    useEffect(() => {\n        organizeFiles()\n    }, [organizeFiles])\n\n    /**\n     * @description Re-trigger the OAuth popup so the user can retry authentication\n     */\n    const retryAuth = useCallback(() => {\n        setAuthCancelled(false)\n        tokenClientRef.current?.requestAccessToken({})\n    }, [])\n\n    return { user, googleFiles, handleSignOut, token, authCancelled, retryAuth }\n}\n","import load from 'load-script'\nimport { useEffect, useState } from 'react'\n\n/**\n * This hook loads the Google API and the Google Identity Services API\n *\n */\nexport default function useLoadGAPI() {\n    const [gisLoaded, setGisLoaded] = useState<boolean>(false)\n\n    useEffect(() => {\n        /**\n         *  Load the Google Identity Services API\n         */\n        load('https://accounts.google.com/gsi/client', async err => {\n            if (!err) setGisLoaded(true)\n        })\n    }, [gisLoaded])\n\n    /**\n     * Return the gdriveApiLoaded and gisLoaded\n     */\n    return { gisLoaded }\n}\n","import { GoogleFile, Root, Token } from 'google'\nimport { useState } from 'react'\nimport { t } from '../../shared/i18n'\nimport { useRootContext } from '../context/RootContext'\nimport {\n    getWorkspaceExportInfo,\n    isDriveFileAccepted,\n} from '../lib/googleDriveUtils'\n\nfunction handleSelectedFilesUpdate(prevFiles: GoogleFile[], file: GoogleFile) {\n    return prevFiles.includes(file)\n        ? prevFiles.filter(f => f.id !== file.id)\n        : [...prevFiles, file]\n}\n\nexport default function useGoogleDriveUploader(token?: Token) {\n    const {\n        props: { onError, accept },\n        googleDriveConfigs,\n        setActiveAdapter,\n        setFiles,\n        translations,\n    } = useRootContext()\n    const [path, setPath] = useState<Root[]>([])\n    const [selectedFiles, setSelectedFiles] = useState<GoogleFile[]>([])\n    const [showLoader, setShowLoader] = useState(false)\n    const [downloadProgress, setDownloadProgress] = useState(0)\n\n    const handleClick = (file: GoogleFile | Root) => {\n        if ('children' in file) setPath(prevPath => [...prevPath, file as Root])\n        else\n            setSelectedFiles(prevFiles =>\n                handleSelectedFilesUpdate(prevFiles, file),\n            )\n    }\n\n    const downloadFiles = async (files: GoogleFile[]) => {\n        const promises = files.map(async (file, index) => {\n            const downloadedFile = await downloadFile(file)\n\n            if (downloadedFile)\n                (downloadedFile as unknown as GoogleFile).thumbnailLink =\n                    file.thumbnailLink\n            // Update progress\n            setDownloadProgress(Math.round(((index + 1) / files.length) * 100))\n\n            return downloadedFile\n        })\n\n        return await Promise.all(promises)\n    }\n\n    const downloadFile = async (file: GoogleFile) => {\n        try {\n            const exportInfo = getWorkspaceExportInfo(file.mimeType)\n            let url: string\n            let fileName: string\n            let fileType: string\n\n            if (exportInfo) {\n                // Google Workspace file – use native Docs/Sheets/Slides\n                // export URL (bypasses the Drive API 10 MB export limit)\n                url = exportInfo.exportUrl(file.id)\n                fileName = file.name.endsWith(`.${exportInfo.extension}`)\n                    ? file.name\n                    : `${file.name}.${exportInfo.extension}`\n                fileType = exportInfo.exportMimeType\n            } else {\n                // Regular file – download via alt=media\n                url = `https://www.googleapis.com/drive/v3/files/${file.id}?key=${googleDriveConfigs?.google_api_key}&alt=media`\n                fileName = file.name\n                fileType = file.mimeType || 'application/octet-stream'\n            }\n\n            const response = await fetch(url, {\n                headers: {\n                    Authorization: `Bearer ${token?.access_token}`,\n                },\n            })\n\n            if (!response.ok) {\n                const body = await response.text().catch(() => '')\n                throw new Error(\n                    `HTTP error! status: ${response.status}${\n                        body ? ` - ${body}` : ''\n                    }`,\n                )\n            }\n\n            const blob = await response.blob()\n            return new File([blob], fileName, { type: fileType })\n        } catch (error) {\n            onError((error as Error)?.message)\n            return\n        }\n    }\n\n    const handleSubmit = async () => {\n        if (selectedFiles.length === 0) return\n\n        setShowLoader(true)\n        setDownloadProgress(0)\n\n        try {\n            const downloadedFiles = (await downloadFiles(selectedFiles)).filter(\n                Boolean,\n            )\n\n            // Update the files state\n            setFiles(downloadedFiles as File[])\n\n            // Clear selection and return to internal view\n            setSelectedFiles([])\n            setActiveAdapter(undefined)\n        } catch (error) {\n            onError(\n                t(translations.errorProcessingFiles, {\n                    message: (error as Error)?.message ?? '',\n                }),\n            )\n        } finally {\n            setShowLoader(false)\n            setDownloadProgress(0)\n        }\n    }\n\n    const submitFiles = async (files: GoogleFile[]) => {\n        if (!files?.length) return\n        setShowLoader(true)\n        setDownloadProgress(0)\n        try {\n            const filtered = files.filter(f => isDriveFileAccepted(f, accept))\n            const downloadedFiles = (await downloadFiles(filtered)).filter(\n                Boolean,\n            )\n            setFiles(downloadedFiles as File[])\n            setSelectedFiles([])\n            setActiveAdapter(undefined)\n        } catch (error) {\n            onError(\n                t(translations.errorProcessingFiles, {\n                    message: (error as Error)?.message ?? '',\n                }),\n            )\n        } finally {\n            setShowLoader(false)\n            setDownloadProgress(0)\n        }\n    }\n\n    const handleCancelDownload = () => {\n        setSelectedFiles([])\n        setDownloadProgress(0)\n    }\n\n    const onSelectCurrentFolder = async () => {\n        try {\n            const current = path[path.length - 1]\n            if (!current) return\n\n            const files: GoogleFile[] = []\n            const walk = (node: GoogleFile | Root) => {\n                if ('children' in node && Array.isArray(node.children))\n                    node.children.forEach(child => walk(child as any))\n                else files.push(node as GoogleFile)\n            }\n            walk(current as any)\n\n            await submitFiles(files)\n        } catch (error) {\n            onError(\n                t(translations.errorSelectingFolder, {\n                    message: (error as Error)?.message ?? '',\n                }),\n            )\n        }\n    }\n\n    return {\n        path,\n        setPath,\n        handleClick,\n        selectedFiles,\n        showLoader,\n        handleSubmit,\n        downloadProgress,\n        handleCancelDownload,\n        onSelectCurrentFolder,\n    }\n}\n","import React from 'react'\nimport { useRootContext } from '../../context/RootContext'\nimport { cn } from '../../lib/tailwind'\nimport AdapterViewContainer from './AdapterViewContainer'\n\ntype Props = {\n    providerName: string\n    onRetry: () => void\n}\n\nexport default function DriveAuthFallback({\n    providerName,\n    onRetry,\n}: Readonly<Props>) {\n    const {\n        props: { dark, classNames },\n    } = useRootContext()\n\n    return (\n        <AdapterViewContainer>\n            <div className=\"upup-flex upup-h-full upup-w-full upup-flex-col upup-items-center upup-justify-center upup-gap-4 upup-p-6 upup-text-center\">\n                <p\n                    className={cn(\n                        'upup-text-sm upup-text-[#333]',\n                        {\n                            'upup-text-[#FAFAFA] dark:upup-text-[#FAFAFA]':\n                                dark,\n                        },\n                        classNames.adapterView,\n                    )}\n                >\n                    Authenticate with {providerName} to select files for upload\n                </p>\n                <button\n                    type=\"button\"\n                    className={cn(\n                        'upup-rounded-md upup-bg-blue-600 upup-px-4 upup-py-2 upup-text-sm upup-font-medium upup-text-white upup-transition-all upup-duration-300 hover:upup-bg-blue-700',\n                        {\n                            'upup-bg-[#30C5F7] hover:upup-bg-[#1eb4e6] dark:upup-bg-[#30C5F7] dark:hover:upup-bg-[#1eb4e6]':\n                                dark,\n                        },\n                    )}\n                    onClick={onRetry}\n                >\n                    Sign in with {providerName}\n                </button>\n            </div>\n        </AdapterViewContainer>\n    )\n}\n","import React from 'react'\n\nexport const MyDeviceIcon = () => (\n    <svg\n        aria-hidden=\"true\"\n        focusable=\"false\"\n        width=\"32\"\n        height=\"32\"\n        viewBox=\"0 0 32 32\"\n        className=\"upup-text-[#2275d7]\"\n    >\n        <path\n            d=\"M8.45 22.087l-1.305-6.674h17.678l-1.572 6.674H8.45zm4.975-12.412l1.083 1.765a.823.823 0 00.715.386h7.951V13.5H8.587V9.675h4.838zM26.043 13.5h-1.195v-2.598c0-.463-.336-.75-.798-.75h-8.356l-1.082-1.766A.823.823 0 0013.897 8H7.728c-.462 0-.815.256-.815.718V13.5h-.956a.97.97 0 00-.746.37.972.972 0 00-.19.81l1.724 8.565c.095.44.484.755.933.755H24c.44 0 .824-.3.929-.727l2.043-8.568a.972.972 0 00-.176-.825.967.967 0 00-.753-.38z\"\n            fill=\"currentcolor\"\n            fillRule=\"evenodd\"\n        />\n    </svg>\n)\n\nexport const BoxIcon = () => (\n    <svg\n        className=\"upup-text-[#0061d5]\"\n        aria-hidden=\"true\"\n        focusable=\"false\"\n        width=\"32\"\n        height=\"32\"\n        viewBox=\"0 0 32 32\"\n    >\n        <g fill=\"currentcolor\" fillRule=\"nonzero\">\n            <path d=\"m16.4 13.5c-1.6 0-3 0.9-3.7 2.2-0.7-1.3-2.1-2.2-3.7-2.2-1 0-1.8 0.3-2.5 0.8v-3.6c-0.1-0.3-0.5-0.7-1-0.7s-0.8 0.4-0.8 0.8v7c0 2.3 1.9 4.2 4.2 4.2 1.6 0 3-0.9 3.7-2.2 0.7 1.3 2.1 2.2 3.7 2.2 2.3 0 4.2-1.9 4.2-4.2 0.1-2.4-1.8-4.3-4.1-4.3m-7.5 6.8c-1.4 0-2.5-1.1-2.5-2.5s1.1-2.5 2.5-2.5 2.5 1.1 2.5 2.5-1.1 2.5-2.5 2.5m7.5 0c-1.4 0-2.5-1.1-2.5-2.5s1.1-2.5 2.5-2.5 2.5 1.1 2.5 2.5-1.1 2.5-2.5 2.5\" />\n            <path d=\"m27.2 20.6l-2.3-2.8 2.3-2.8c0.3-0.4 0.2-0.9-0.2-1.2s-1-0.2-1.3 0.2l-2 2.4-2-2.4c-0.3-0.4-0.9-0.4-1.3-0.2-0.4 0.3-0.5 0.8-0.2 1.2l2.3 2.8-2.3 2.8c-0.3 0.4-0.2 0.9 0.2 1.2s1 0.2 1.3-0.2l2-2.4 2 2.4c0.3 0.4 0.9 0.4 1.3 0.2 0.4-0.3 0.4-0.8 0.2-1.2\" />\n        </g>\n    </svg>\n)\n\nexport const DropBoxIcon = () => (\n    <svg\n        className=\"upup-text-[#0061fe]\"\n        aria-hidden=\"true\"\n        focusable=\"false\"\n        width=\"32\"\n        height=\"32\"\n        viewBox=\"0 0 32 32\"\n    >\n        <path\n            d=\"M10.5 7.5L5 10.955l5.5 3.454 5.5-3.454 5.5 3.454 5.5-3.454L21.5 7.5 16 10.955zM10.5 21.319L5 17.864l5.5-3.455 5.5 3.455zM16 17.864l5.5-3.455 5.5 3.455-5.5 3.455zM16 25.925l-5.5-3.455 5.5-3.454 5.5 3.454z\"\n            fill=\"currentcolor\"\n            fillRule=\"nonzero\"\n        ></path>\n    </svg>\n)\n\nexport const FacebookIcon = () => (\n    <svg\n        aria-hidden=\"true\"\n        focusable=\"false\"\n        width=\"32\"\n        height=\"32\"\n        viewBox=\"0 0 32 32\"\n    >\n        <g fill=\"none\" fillRule=\"evenodd\">\n            <path\n                d=\"M27 16c0-6.075-4.925-11-11-11S5 9.925 5 16c0 5.49 4.023 10.041 9.281 10.866V19.18h-2.793V16h2.793v-2.423c0-2.757 1.642-4.28 4.155-4.28 1.204 0 2.462.215 2.462.215v2.707h-1.387c-1.366 0-1.792.848-1.792 1.718V16h3.05l-.487 3.18h-2.563v7.686C22.977 26.041 27 21.49 27 16\"\n                fill=\"#1777F2\"\n            />\n            <path\n                d=\"M20.282 19.18L20.77 16h-3.051v-2.063c0-.87.426-1.718 1.792-1.718h1.387V9.512s-1.258-.215-2.462-.215c-2.513 0-4.155 1.523-4.155 4.28V16h-2.793v3.18h2.793v7.686a11.082 11.082 0 003.438 0V19.18h2.563\"\n                fill=\"#FFFFFE\"\n            />\n        </g>\n    </svg>\n)\n\nexport const GoogleDriveIcon = () => (\n    <svg\n        aria-hidden=\"true\"\n        focusable=\"false\"\n        width=\"32\"\n        height=\"32\"\n        viewBox=\"0 0 32 32\"\n    >\n        <g fillRule=\"nonzero\" fill=\"none\">\n            <path\n                d=\"M6.663 22.284l.97 1.62c.202.34.492.609.832.804l3.465-5.798H5c0 .378.1.755.302 1.096l1.361 2.278z\"\n                fill=\"#0066DA\"\n            />\n            <path\n                d=\"M16 12.09l-3.465-5.798c-.34.195-.63.463-.832.804l-6.4 10.718A2.15 2.15 0 005 18.91h6.93L16 12.09z\"\n                fill=\"#00AC47\"\n            />\n            <path\n                d=\"M23.535 24.708c.34-.195.63-.463.832-.804l.403-.67 1.928-3.228c.201-.34.302-.718.302-1.096h-6.93l1.474 2.802 1.991 2.996z\"\n                fill=\"#EA4335\"\n            />\n            <path\n                d=\"M16 12.09l3.465-5.798A2.274 2.274 0 0018.331 6h-4.662c-.403 0-.794.11-1.134.292L16 12.09z\"\n                fill=\"#00832D\"\n            />\n            <path\n                d=\"M20.07 18.91h-8.14l-3.465 5.798c.34.195.73.292 1.134.292h12.802c.403 0 .794-.11 1.134-.292L20.07 18.91z\"\n                fill=\"#2684FC\"\n            />\n            <path\n                d=\"M23.497 12.455l-3.2-5.359a2.252 2.252 0 00-.832-.804L16 12.09l4.07 6.82h6.917c0-.377-.1-.755-.302-1.096l-3.188-5.359z\"\n                fill=\"#FFBA00\"\n            />\n        </g>\n    </svg>\n)\n\nexport const InstagramIcon = () => (\n    <svg\n        aria-hidden=\"true\"\n        focusable=\"false\"\n        width=\"32\"\n        height=\"32\"\n        viewBox=\"0 0 32 32\"\n    >\n        <defs>\n            <path\n                d=\"M16.825 5l.483-.001.799.002c1.168.005 1.598.021 2.407.057 1.17.05 1.97.235 2.67.506.725.28 1.34.655 1.951 1.265.613.61.99 1.223 1.273 1.946.273.7.46 1.498.516 2.67l.025.552.008.205c.029.748.037 1.51.042 3.777l.001.846v.703l-.001.398a50.82 50.82 0 01-.058 2.588c-.05 1.17-.235 1.97-.506 2.67a5.394 5.394 0 01-1.265 1.951c-.61.613-1.222.99-1.946 1.273-.699.273-1.498.46-2.668.516-.243.012-.451.022-.656.03l-.204.007c-.719.026-1.512.034-3.676.038l-.847.001h-1.1a50.279 50.279 0 01-2.587-.059c-1.171-.05-1.971-.235-2.671-.506a5.394 5.394 0 01-1.951-1.265 5.385 5.385 0 01-1.272-1.946c-.274-.699-.46-1.498-.517-2.668a88.15 88.15 0 01-.03-.656l-.007-.205c-.026-.718-.034-1.512-.038-3.674v-2.129c.006-1.168.022-1.597.058-2.406.051-1.171.235-1.971.506-2.672a5.39 5.39 0 011.265-1.95 5.381 5.381 0 011.946-1.272c.699-.274 1.498-.462 2.669-.517l.656-.03.204-.007c.718-.026 1.511-.034 3.674-.038zm.678 1.981h-1.226l-.295.001c-2.307.005-3.016.013-3.777.043l-.21.009-.457.02c-1.072.052-1.654.232-2.042.383-.513.2-.879.44-1.263.825a3.413 3.413 0 00-.82 1.267c-.15.388-.33.97-.375 2.043a48.89 48.89 0 00-.056 2.482v.398 1.565c.006 2.937.018 3.285.073 4.444.05 1.073.231 1.654.382 2.043.2.512.44.878.825 1.263.386.383.753.621 1.267.82.388.15.97.328 2.043.374.207.01.388.017.563.024l.208.007a63.28 63.28 0 002.109.026h1.564c2.938-.006 3.286-.019 4.446-.073 1.071-.051 1.654-.232 2.04-.383.514-.2.88-.44 1.264-.825.384-.386.622-.753.82-1.266.15-.389.328-.971.375-2.044.039-.88.054-1.292.057-2.723v-1.15-.572c-.006-2.936-.019-3.284-.074-4.445-.05-1.071-.23-1.654-.382-2.04-.2-.515-.44-.88-.825-1.264a3.405 3.405 0 00-1.267-.82c-.388-.15-.97-.328-2.042-.375a48.987 48.987 0 00-2.535-.056zm-1.515 3.37a5.65 5.65 0 11.021 11.299 5.65 5.65 0 01-.02-11.3zm.004 1.982a3.667 3.667 0 10.015 7.334 3.667 3.667 0 00-.015-7.334zm5.865-3.536a1.32 1.32 0 11.005 2.64 1.32 1.32 0 01-.005-2.64z\"\n                id=\"a\"\n            />\n        </defs>\n        <g fill=\"none\" fillRule=\"evenodd\">\n            <mask id=\"b\" fill=\"#fff\">\n                <use href=\"#a\"></use>\n            </mask>\n            <image\n                mask=\"url(#b)\"\n                x=\"4\"\n                y=\"4\"\n                width=\"24\"\n                height=\"24\"\n                href=\"data:image/png;base64,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\"\n            />\n        </g>\n    </svg>\n)\n\nexport const OneDriveIcon = () => (\n    <svg\n        aria-hidden=\"true\"\n        focusable=\"false\"\n        width=\"32\"\n        height=\"32\"\n        viewBox=\"0 0 32 32\"\n    >\n        <g fill=\"none\" fillRule=\"nonzero\">\n            <path\n                d=\"M13.39 12.888l4.618 2.747 2.752-1.15a4.478 4.478 0 012.073-.352 6.858 6.858 0 00-5.527-5.04 6.895 6.895 0 00-6.876 2.982l.07-.002a5.5 5.5 0 012.89.815z\"\n                fill=\"#0364B8\"\n            ></path>\n            <path\n                d=\"M13.39 12.887v.001a5.5 5.5 0 00-2.89-.815l-.07.002a5.502 5.502 0 00-4.822 2.964 5.43 5.43 0 00.38 5.62l4.073-1.702 1.81-.757 4.032-1.685 2.105-.88-4.619-2.748z\"\n                fill=\"#0078D4\"\n            ></path>\n            <path\n                d=\"M22.833 14.133a4.479 4.479 0 00-2.073.352l-2.752 1.15.798.475 2.616 1.556 1.141.68 3.902 2.321a4.413 4.413 0 00-.022-4.25 4.471 4.471 0 00-3.61-2.284z\"\n                fill=\"#1490DF\"\n            ></path>\n            <path\n                d=\"M22.563 18.346l-1.141-.68-2.616-1.556-.798-.475-2.105.88L11.87 18.2l-1.81.757-4.073 1.702A5.503 5.503 0 0010.5 23h12.031a4.472 4.472 0 003.934-2.333l-3.902-2.321z\"\n                fill=\"#28A8EA\"\n            ></path>\n        </g>\n    </svg>\n)\n\nexport const UnsplashIcon = () => (\n    <svg\n        className=\"upup-text-[#111]\"\n        viewBox=\"0 0 32 32\"\n        height=\"32\"\n        width=\"32\"\n        aria-hidden=\"true\"\n    >\n        <g fill=\"currentcolor\">\n            <path d=\"M46.575 10.883v-9h12v9zm12 5h10v18h-32v-18h10v9h12z\"></path>\n            <path d=\"M13 12.5V8h6v4.5zm6 2.5h5v9H8v-9h5v4.5h6z\"></path>\n        </g>\n    </svg>\n)\n\nexport const LinkIcon = () => (\n    <svg\n        aria-hidden=\"true\"\n        focusable=\"false\"\n        width=\"32\"\n        height=\"32\"\n        viewBox=\"0 0 32 32\"\n    >\n        <path\n            d=\"M23.637 15.312l-2.474 2.464a3.582 3.582 0 01-.577.491c-.907.657-1.897.986-2.968.986a4.925 4.925 0 01-3.959-1.971c-.248-.329-.164-.902.165-1.149.33-.247.907-.164 1.155.164 1.072 1.478 3.133 1.724 4.618.656a.642.642 0 00.33-.328l2.473-2.463c1.238-1.313 1.238-3.366-.082-4.597a3.348 3.348 0 00-4.618 0l-1.402 1.395a.799.799 0 01-1.154 0 .79.79 0 010-1.15l1.402-1.394a4.843 4.843 0 016.843 0c2.062 1.805 2.144 5.007.248 6.896zm-8.081 5.664l-1.402 1.395a3.348 3.348 0 01-4.618 0c-1.319-1.23-1.319-3.365-.082-4.596l2.475-2.464.328-.328c.743-.492 1.567-.739 2.475-.657.906.165 1.648.574 2.143 1.314.248.329.825.411 1.155.165.33-.248.412-.822.165-1.15-.825-1.068-1.98-1.724-3.216-1.888-1.238-.247-2.556.082-3.628.902l-.495.493-2.474 2.464c-1.897 1.969-1.814 5.09.083 6.977.99.904 2.226 1.396 3.463 1.396s2.473-.492 3.463-1.395l1.402-1.396a.79.79 0 000-1.15c-.33-.328-.908-.41-1.237-.082z\"\n            fill=\"#FF753E\"\n            fillRule=\"nonzero\"\n        ></path>\n    </svg>\n)\n\nexport const CameraIcon = () => (\n    <svg\n        aria-hidden=\"true\"\n        focusable=\"false\"\n        width=\"32\"\n        height=\"32\"\n        viewBox=\"0 0 32 32\"\n    >\n        <path\n            d=\"M23.5 9.5c1.417 0 2.5 1.083 2.5 2.5v9.167c0 1.416-1.083 2.5-2.5 2.5h-15c-1.417 0-2.5-1.084-2.5-2.5V12c0-1.417 1.083-2.5 2.5-2.5h2.917l1.416-2.167C13 7.167 13.25 7 13.5 7h5c.25 0 .5.167.667.333L20.583 9.5H23.5zM16 11.417a4.706 4.706 0 00-4.75 4.75 4.704 4.704 0 004.75 4.75 4.703 4.703 0 004.75-4.75c0-2.663-2.09-4.75-4.75-4.75zm0 7.825c-1.744 0-3.076-1.332-3.076-3.074 0-1.745 1.333-3.077 3.076-3.077 1.744 0 3.074 1.333 3.074 3.076s-1.33 3.075-3.074 3.075z\"\n            fill=\"#02B383\"\n            fillRule=\"nonzero\"\n        ></path>\n    </svg>\n)\n\nexport const AudioIcon = () => (\n    <svg\n        className=\"upup-text-[#8030a3]\"\n        aria-hidden=\"true\"\n        focusable=\"false\"\n        width=\"32px\"\n        height=\"32px\"\n        viewBox=\"0 0 32 32\"\n    >\n        <path\n            d=\"M21.143 12.297c.473 0 .857.383.857.857v2.572c0 3.016-2.24 5.513-5.143 5.931v2.64h2.572a.857.857 0 110 1.714H12.57a.857.857 0 110-1.714h2.572v-2.64C12.24 21.24 10 18.742 10 15.726v-2.572a.857.857 0 111.714 0v2.572A4.29 4.29 0 0016 20.01a4.29 4.29 0 004.286-4.285v-2.572c0-.474.384-.857.857-.857zM16 6.5a3 3 0 013 3v6a3 3 0 01-6 0v-6a3 3 0 013-3z\"\n            fill=\"currentcolor\"\n            fillRule=\"nonzero\"\n        ></path>\n    </svg>\n)\n\nexport const ScreenCastIcon = () => (\n    <svg\n        className=\"upup-text-[#2c3e50]\"\n        aria-hidden=\"true\"\n        focusable=\"false\"\n        width=\"32\"\n        height=\"32\"\n        viewBox=\"0 0 32 32\"\n    >\n        <g fill=\"currentcolor\" fillRule=\"evenodd\">\n            <path d=\"M24.182 9H7.818C6.81 9 6 9.742 6 10.667v10c0 .916.81 1.666 1.818 1.666h4.546V24h7.272v-1.667h4.546c1 0 1.809-.75 1.809-1.666l.009-10C26 9.742 25.182 9 24.182 9zM24 21H8V11h16v10z\"></path>\n            <circle cx=\"16\" cy=\"16\" r=\"2\"></circle>\n        </g>\n    </svg>\n)\n\nexport const Close = () => (\n    <svg\n        xmlns=\"http://www.w3.org/2000/svg\"\n        width=\"22\"\n        height=\"22\"\n        viewBox=\"0 0 22 22\"\n        fill=\"none\"\n    >\n        <g id=\"close\">\n            <path\n                id=\"Vector\"\n                d=\"M16.775 5.23408C16.4175 4.87658 15.84 4.87658 15.4825 5.23408L11 9.70741L6.51753 5.22491C6.16003 4.86741 5.58253 4.86741 5.22503 5.22491C4.86753 5.58241 4.86753 6.15991 5.22503 6.51741L9.70753 10.9999L5.22503 15.4824C4.86753 15.8399 4.86753 16.4174 5.22503 16.7749C5.58253 17.1324 6.16003 17.1324 6.51753 16.7749L11 12.2924L15.4825 16.7749C15.84 17.1324 16.4175 17.1324 16.775 16.7749C17.1325 16.4174 17.1325 15.8399 16.775 15.4824L12.2925 10.9999L16.775 6.51741C17.1234 6.16908 17.1234 5.58241 16.775 5.23408Z\"\n                fill=\"#1849D6\"\n            />\n        </g>\n    </svg>\n)\n","import React from 'react'\nimport { useRootContext } from '../context/RootContext'\nimport useOneDrive from '../hooks/useOneDrive'\n\nimport useOneDriveUploader from '../hooks/useOneDriveUploader'\nimport DriveAuthFallback from './shared/DriveAuthFallback'\nimport DriveBrowser from './shared/DriveBrowser'\n\nexport default function OneDriveUploader() {\n    const { oneDriveConfigs } = useRootContext()\n    const {\n        user,\n        oneDriveFiles: driveFiles,\n        signOut: handleSignOut,\n        graphClient,\n        token,\n        authCancelled,\n        retryAuth,\n    } = useOneDrive(oneDriveConfigs?.onedrive_client_id)\n    const props = useOneDriveUploader(graphClient)\n\n    if (authCancelled && !token) {\n        return <DriveAuthFallback providerName=\"OneDrive\" onRetry={retryAuth} />\n    }\n\n    return (\n        <DriveBrowser\n            driveFiles={driveFiles}\n            user={user}\n            handleSignOut={handleSignOut}\n            {...props}\n        />\n    )\n}\n","import { InteractionType } from '@azure/msal-browser'\nimport { Client } from '@microsoft/microsoft-graph-client'\nimport { AuthCodeMSALBrowserAuthenticationProvider } from '@microsoft/microsoft-graph-client/authProviders/authCodeMsalBrowser/index.js'\nimport { MicrosoftUser, OneDriveRoot } from 'microsoft'\nimport { useEffect, useState } from 'react'\nimport { useRootContext } from '../context/RootContext'\nimport useOneDriveAuth from './useOneDriveAuth'\nimport usePCAInstance from './usePCAInstance'\n\nexport default function useOneDrive(clientId = '') {\n    const {\n        props: { onError },\n    } = useRootContext()\n    const [user, setUser] = useState<MicrosoftUser>()\n    const [oneDriveFiles, setOneDriveFiles] = useState<OneDriveRoot>()\n    const [graphClient, setGraphClient] = useState<Client>()\n    const { msalInstance } = usePCAInstance(clientId)\n    const {\n        token,\n        signOut,\n        isInitialized,\n        isAuthenticating,\n        authCancelled,\n        retryAuth,\n    } = useOneDriveAuth({\n        msalInstance,\n        setUser,\n        setOneDriveFiles,\n    })\n\n    // Initialize Graph client when we have both msalInstance and token\n    useEffect(() => {\n        const isReady = token && isInitialized && !isAuthenticating\n        if (!isReady || !msalInstance) {\n            setGraphClient(undefined)\n            return\n        }\n\n        try {\n            const accounts = msalInstance.getAllAccounts()\n            if (accounts.length === 0) throw new Error('No accounts found')\n\n            const authProvider = new AuthCodeMSALBrowserAuthenticationProvider(\n                msalInstance,\n                {\n                    account: accounts[0],\n                    scopes: [\n                        'user.read',\n                        'files.read.all',\n                        'files.readwrite.all',\n                    ],\n                    interactionType: InteractionType.Popup,\n                },\n            )\n\n            const client = Client.initWithMiddleware({\n                authProvider,\n            })\n\n            setGraphClient(client)\n        } catch (error) {\n            onError(\n                `Error initializing Graph client: ${(error as Error)?.message}`,\n            )\n            setGraphClient(undefined)\n        }\n    }, [msalInstance, token, isInitialized, isAuthenticating, onError])\n\n    // Fetch user profile and files when Graph client is ready\n    useEffect(() => {\n        if (!graphClient) return\n\n        const initialize = async () => {\n            try {\n                const profile = await graphClient.api('/me').get()\n                setUser({ name: profile.displayName, mail: profile.mail })\n\n                const filesResponse = await graphClient\n                    .api('/me/drive/root/children')\n                    .select(\n                        'id,name,folder,file,thumbnails,@microsoft.graph.downloadUrl',\n                    )\n                    .expand('thumbnails')\n                    .get()\n\n                const files = filesResponse.value.map((item: any) => ({\n                    id: item.id,\n                    name: item.name,\n                    isFolder: !!item.folder,\n                    children: item.folder ? [] : undefined,\n                    thumbnails: item.thumbnails?.[0] || null,\n                    '@microsoft.graph.downloadUrl':\n                        item['@microsoft.graph.downloadUrl'],\n                    file: item.file,\n                }))\n\n                setOneDriveFiles({\n                    id: 'root',\n                    name: 'OneDrive',\n                    isFolder: true,\n                    children: files,\n                })\n            } catch (error) {\n                onError(\n                    'Error fetching profile or file list:' +\n                        (error as Error)?.message,\n                )\n            }\n        }\n\n        initialize()\n    }, [graphClient, onError])\n\n    return {\n        user,\n        oneDriveFiles,\n        signOut,\n        graphClient,\n        token,\n        authCancelled,\n        retryAuth,\n    }\n}\n","import {\n    AuthenticationResult,\n    PopupRequest,\n    PublicClientApplication,\n} from '@azure/msal-browser'\nimport { MicrosoftToken, MicrosoftUser, OneDriveRoot } from 'microsoft'\nimport {\n    Dispatch,\n    SetStateAction,\n    useCallback,\n    useEffect,\n    useState,\n} from 'react'\nimport { t } from '../../shared/i18n'\nimport { useRootContext } from '../context/RootContext'\nimport { createSecureStorage } from '../lib/storageHelper'\n\ntype Props = {\n    msalInstance?: PublicClientApplication\n    setUser: Dispatch<SetStateAction<MicrosoftUser | undefined>>\n    setOneDriveFiles: Dispatch<SetStateAction<OneDriveRoot | undefined>>\n}\n\nconst secureStorage = createSecureStorage()\n\nexport default function useOneDriveAuth({\n    msalInstance,\n    setUser,\n    setOneDriveFiles,\n}: Props) {\n    const {\n        props: { onError },\n        translations,\n    } = useRootContext()\n    const [token, setToken] = useState<MicrosoftToken>()\n    const [isInitialized, setIsInitialized] = useState(false)\n    const [isAuthenticating, setIsAuthenticating] = useState(false)\n    const [isAuthInProgress, setIsAuthInProgress] = useState(false)\n    const [authCancelled, setAuthCancelled] = useState(false)\n\n    // Initialize MSAL\n    useEffect(() => {\n        const initialize = async () => {\n            if (!msalInstance || isInitialized) return\n\n            try {\n                await msalInstance.initialize()\n                setIsInitialized(true)\n\n                // Check for existing token after initialization\n                const accounts = msalInstance.getAllAccounts()\n                if (accounts.length > 0) {\n                    try {\n                        const silentRequest = {\n                            scopes: [\n                                'user.read',\n                                'Files.ReadWrite.All',\n                                'Files.Read.All',\n                            ],\n                            account: accounts[0],\n                        }\n                        const response =\n                            await msalInstance.acquireTokenSilent(silentRequest)\n                        if (response)\n                            setToken({\n                                secret: response.accessToken,\n                                expiresOn: response.expiresOn!.getTime(),\n                            })\n                    } catch (error) {\n                        onError(\n                            t(translations.silentTokenAcquisitionFailed, {\n                                details: (error as Error)?.message ?? '',\n                            }),\n                        ) // Silent token acquisition failed, user will need to sign in again\n                    }\n                }\n            } catch (error) {\n                onError(\n                    t(translations.msalInitializationFailed, {\n                        details: (error as Error)?.message ?? '',\n                    }),\n                )\n                setIsInitialized(false)\n            }\n        }\n\n        initialize()\n    }, [isInitialized, msalInstance, onError])\n\n    const signIn =\n        useCallback(async (): Promise<AuthenticationResult | null> => {\n            if (\n                !msalInstance ||\n                !isInitialized ||\n                isAuthenticating ||\n                isAuthInProgress\n            )\n                return null\n\n            const loginRequest: PopupRequest = {\n                scopes: ['user.read', 'Files.ReadWrite.All', 'Files.Read.All'],\n                prompt: 'select_account',\n            }\n\n            try {\n                setIsAuthInProgress(true)\n                setIsAuthenticating(true)\n\n                const accounts = msalInstance.getAllAccounts()\n                if (accounts.length > 0) {\n                    try {\n                        // Attempt silent token acquisition first\n                        return await msalInstance.acquireTokenSilent({\n                            ...loginRequest,\n                            account: accounts[0],\n                        })\n                    } catch (error) {\n                        onError(\n                            t(translations.silentTokenAcquisitionProceeding, {\n                                details: (error as Error)?.message ?? '',\n                            }),\n                        ) // Silent token acquisition failed, fall through to interactive login\n                    }\n                }\n\n                // If silent token acquisition fails, try interactive login\n                const loginResponse =\n                    await msalInstance.loginPopup(loginRequest)\n\n                if (loginResponse)\n                    return await msalInstance.acquireTokenSilent({\n                        ...loginRequest,\n                        account: loginResponse.account,\n                    })\n\n                return null\n            } catch (error) {\n                onError(\n                    t(translations.signInFailed, {\n                        message: (error as Error)?.message ?? '',\n                    }),\n                )\n                return null\n            } finally {\n                setIsAuthenticating(false)\n                setIsAuthInProgress(false)\n            }\n        }, [\n            msalInstance,\n            isInitialized,\n            isAuthenticating,\n            isAuthInProgress,\n            onError,\n        ])\n\n    const handleSignIn = useCallback(async () => {\n        if (!isInitialized || isAuthenticating || isAuthInProgress) return\n\n        try {\n            const response = await signIn()\n            if (response) {\n                const newToken: MicrosoftToken = {\n                    secret: response.accessToken,\n                    expiresOn: response.expiresOn!.getTime(),\n                }\n                setToken(newToken)\n                setAuthCancelled(false)\n                secureStorage.setItem('isAuthenticated', 'true')\n            } else {\n                // Popup was closed or sign-in returned no result\n                setAuthCancelled(true)\n            }\n        } catch (error) {\n            onError(\n                t(translations.handleSignInFailed, {\n                    message: (error as Error)?.message ?? '',\n                }),\n            )\n            setAuthCancelled(true)\n            setToken(undefined)\n            secureStorage.removeItem('isAuthenticated')\n        }\n    }, [isInitialized, isAuthenticating, isAuthInProgress, signIn, onError])\n\n    const handleSignOut = useCallback(async () => {\n        if (!msalInstance || !isInitialized || isAuthInProgress) return\n\n        try {\n            setIsAuthInProgress(true)\n            const accounts = msalInstance.getAllAccounts()\n\n            if (accounts.length > 0) {\n                // Wait for the logout to complete\n                await msalInstance.logoutPopup({\n                    account: accounts[0],\n                    postLogoutRedirectUri: window.location.origin,\n                })\n            }\n\n            // Clear all local state\n            setToken(undefined)\n            setUser(undefined)\n            setOneDriveFiles(undefined)\n\n            // Clear MSAL cache\n            msalInstance.clearCache()\n\n            // Set logout flag in session storage\n            secureStorage.setItem('recentLogout', 'true')\n\n            // Clear remaining session storage\n            secureStorage.removeItem('isAuthenticated')\n        } catch (error) {\n            onError(\n                t(translations.signOutFailed, {\n                    message: (error as Error)?.message ?? '',\n                }),\n            )\n        } finally {\n            setIsAuthInProgress(false)\n            // Clear the logout flag after a short delay\n            setTimeout(() => secureStorage.removeItem('recentLogout'), 1000) // Adjust timeout as needed\n        }\n    }, [\n        msalInstance,\n        isInitialized,\n        isAuthInProgress,\n        setUser,\n        setOneDriveFiles,\n        onError,\n    ])\n\n    // Modify the auto-login effect\n    useEffect(() => {\n        if (!isInitialized || isAuthenticating || isAuthInProgress || token)\n            return\n\n        let autoLoginTimeout: ReturnType<typeof setTimeout>\n\n        const autoLogin = async () => {\n            // Check for recent logout or existing authentication\n            const hasRecentlyLoggedOut = secureStorage.getItem('recentLogout')\n            const isAuthenticated = secureStorage.getItem('isAuthenticated')\n\n            if (hasRecentlyLoggedOut || isAuthenticated) return\n\n            const accounts = msalInstance?.getAllAccounts() || []\n            if (accounts.length === 0)\n                autoLoginTimeout = setTimeout(() => {\n                    handleSignIn()\n                }, 1000)\n        }\n\n        autoLogin()\n\n        return () => {\n            if (autoLoginTimeout) clearTimeout(autoLoginTimeout)\n        }\n    }, [\n        isInitialized,\n        isAuthenticating,\n        isAuthInProgress,\n        token,\n        handleSignIn,\n        msalInstance,\n    ])\n\n    const retryAuth = useCallback(() => {\n        setAuthCancelled(false)\n        handleSignIn()\n    }, [handleSignIn])\n\n    return {\n        token,\n        signOut: handleSignOut,\n        isInitialized,\n        isAuthenticating,\n        authCancelled,\n        retryAuth,\n    }\n}\n","import { PublicClientApplication } from '@azure/msal-browser'\nimport { useEffect, useState } from 'react'\nimport { useRootContext } from '../context/RootContext'\n\nconst usePCAInstance = (clientId: string) => {\n    const {\n        props: { onError },\n        translations,\n    } = useRootContext()\n    const [msalInstance, setMsalInstance] = useState<PublicClientApplication>()\n    const [isInitializing, setIsInitializing] = useState(true)\n\n    useEffect(() => {\n        let mounted = true\n\n        const initializeMsal = async () => {\n            if (!clientId) {\n                setIsInitializing(false)\n                onError(translations.clientIdRequired)\n                return\n            }\n\n            try {\n                const instance = new PublicClientApplication({\n                    auth: {\n                        clientId,\n                        authority: 'https://login.microsoftonline.com/common',\n                        redirectUri: window.location.origin,\n                        navigateToLoginRequestUrl: true,\n                    },\n                    cache: {\n                        cacheLocation: 'sessionStorage',\n                        storeAuthStateInCookie: true,\n                    },\n                    system: {\n                        allowRedirectInIframe: true,\n                        windowHashTimeout: 60000,\n                        iframeHashTimeout: 10000,\n                        loadFrameTimeout: 10000,\n                        asyncPopups: false,\n                    },\n                })\n\n                if (mounted) setMsalInstance(instance)\n            } catch (error) {\n                onError((error as Error).message)\n            } finally {\n                if (mounted) setIsInitializing(false)\n            }\n        }\n\n        if (!msalInstance) initializeMsal()\n\n        return () => {\n            mounted = false\n        }\n    }, [clientId, msalInstance, onError])\n\n    return {\n        msalInstance,\n        isInitializing,\n    }\n}\n\nexport default usePCAInstance\n","import { Client } from '@microsoft/microsoft-graph-client'\nimport { OneDriveFile, OneDriveRoot } from 'microsoft'\nimport { useState } from 'react'\nimport { t } from '../../shared/i18n'\nimport { useRootContext } from '../context/RootContext'\n\nconst formatFileItem = (item: any) => ({\n    id: item.id,\n    name: item.name,\n    isFolder: !!item.folder,\n    children: item.folder ? [] : undefined,\n    thumbnails: item.thumbnails?.[0] || null,\n    '@microsoft.graph.downloadUrl': item['@microsoft.graph.downloadUrl'],\n    file: item.file,\n})\n\nconst getDownloadUrl = async (file: OneDriveFile, graphClient: Client) => {\n    // First try to get direct download URL\n    const fileInfo = await graphClient\n        .api(`/me/drive/items/${file.id}`)\n        .select('@microsoft.graph.downloadUrl')\n        .get()\n\n    if (fileInfo['@microsoft.graph.downloadUrl'])\n        return fileInfo['@microsoft.graph.downloadUrl']\n\n    // Fallback to creating a sharing link\n    const permission = await graphClient\n        .api(`/me/drive/items/${file.id}/createLink`)\n        .post({\n            type: 'view',\n            scope: 'anonymous',\n        })\n\n    const shareId = permission.link.webUrl.split('/s!/')[1]\n    const sharedItem = await graphClient\n        .api(`/shares/u!${shareId}`)\n        .expand('driveItem')\n        .get()\n\n    return sharedItem.driveItem['@microsoft.graph.downloadUrl']\n}\n\nexport default function useOneDriveUploader(graphClient?: Client) {\n    const {\n        setFiles,\n        setActiveAdapter,\n        props: { onError, accept },\n        translations,\n    } = useRootContext()\n    const [isClickLoading, setIsClickLoading] = useState<boolean>()\n    const [path, setPath] = useState<OneDriveRoot[]>([])\n    const [selectedFiles, setSelectedFiles] = useState<OneDriveFile[]>([])\n    const [showLoader, setShowLoader] = useState(false)\n    const [downloadProgress, setDownloadProgress] = useState(0)\n\n    const fetchFolderContents = async (file: OneDriveFile) => {\n        setIsClickLoading(true)\n        try {\n            const response = await graphClient\n                ?.api(`/me/drive/items/${file.id}/children`)\n                .select(\n                    'id,name,folder,file,thumbnails,@microsoft.graph.downloadUrl',\n                )\n                .expand('thumbnails')\n                .get()\n\n            const files = response.value.map(formatFileItem)\n            setPath(prevPath => [...prevPath, { ...file, children: files }])\n        } catch (error) {\n            onError(\n                t(translations.errorProcessingFiles, {\n                    message: (error as Error)?.message ?? '',\n                }),\n            )\n        } finally {\n            setIsClickLoading(false)\n        }\n    }\n\n    const fetchChildren = async (folderId: string) => {\n        const response = await graphClient\n            ?.api(`/me/drive/items/${folderId}/children`)\n            .select(\n                'id,name,folder,file,thumbnails,@microsoft.graph.downloadUrl',\n            )\n            .expand('thumbnails')\n            .get()\n        return response.value.map(formatFileItem) as OneDriveFile[]\n    }\n\n    const getAllFilesRecursively = async (rootFolderId: string) => {\n        const files: OneDriveFile[] = []\n        const queue: string[] = [rootFolderId]\n        while (queue.length) {\n            const folderId = queue.shift()!\n            const children = await fetchChildren(folderId)\n            for (const child of children) {\n                if (child.isFolder) queue.push(child.id)\n                else files.push(child)\n            }\n        }\n        return files\n    }\n\n    const handleClick = async (file: OneDriveFile) => {\n        if (!graphClient) {\n            onError(translations.graphClientNotInitialized)\n            return\n        }\n\n        if (file.isFolder) await fetchFolderContents(file)\n        else\n            setSelectedFiles(prevFiles => {\n                const newFiles = prevFiles.filter(f => f.id === file.id).length\n                    ? prevFiles.filter(f => f.id !== file.id)\n                    : [...prevFiles, file]\n                return newFiles\n            })\n    }\n\n    const downloadFiles = async (files: OneDriveFile[]) => {\n        const promises = files.map(async (file, index) => {\n            const downloadedFile = await downloadFile(file)\n\n            // Add thumbnail if available\n            if (file.thumbnails?.large?.url)\n                Object.defineProperty(downloadedFile, 'thumbnailLink', {\n                    value: file.thumbnails.large.url,\n                    writable: true,\n                    enumerable: true,\n                    configurable: true,\n                })\n\n            // Update progress\n            setDownloadProgress(Math.round(((index + 1) / files.length) * 100))\n\n            return downloadedFile\n        })\n\n        return await Promise.all(promises)\n    }\n\n    const downloadFile = async (file: OneDriveFile) => {\n        try {\n            const url = await getDownloadUrl(file, graphClient!)\n            if (!url) throw new Error('Could not get download URL')\n\n            const response = await fetch(url, {\n                method: 'GET',\n            })\n            if (!response.ok)\n                throw new Error(`HTTP error! status: ${response.status}`)\n\n            const blob = await response.blob()\n            return new File([blob], file.name, {\n                type: file.file?.mimeType ?? 'application/octet-stream',\n            })\n        } catch (error) {\n            onError((error as Error).message)\n            return\n        }\n    }\n\n    const handleSubmit = async () => {\n        if (selectedFiles.length === 0) return\n\n        setShowLoader(true)\n        setDownloadProgress(0)\n\n        try {\n            const downloadedFiles = (await downloadFiles(selectedFiles)).filter(\n                Boolean,\n            )\n\n            // Update the files state\n            setFiles(downloadedFiles as File[])\n\n            // Clear selection and return to internal view\n            setSelectedFiles([])\n            setActiveAdapter(undefined)\n        } catch (error) {\n            onError(\n                t(translations.errorProcessingFiles, {\n                    message: (error as Error)?.message ?? '',\n                }),\n            )\n        } finally {\n            setShowLoader(false)\n            setDownloadProgress(0)\n        }\n    }\n\n    const submitFiles = async (files: OneDriveFile[]) => {\n        if (!files?.length) return\n        setShowLoader(true)\n        setDownloadProgress(0)\n        try {\n            const filtered = files.filter(f => {\n                if (!accept || accept === '*') return true\n                const ext = f.name.split('.').pop() || ''\n                return accept.includes(ext)\n            })\n            const downloadedFiles = (await downloadFiles(filtered)).filter(\n                Boolean,\n            )\n            setFiles(downloadedFiles as File[])\n            setSelectedFiles([])\n            setActiveAdapter(undefined)\n        } catch (error) {\n            onError(\n                t(translations.errorProcessingFiles, {\n                    message: (error as Error)?.message ?? '',\n                }),\n            )\n        } finally {\n            setShowLoader(false)\n            setDownloadProgress(0)\n        }\n    }\n    const handleCancelDownload = () => {\n        setSelectedFiles([])\n        setDownloadProgress(0)\n    }\n\n    const onSelectCurrentFolder = async () => {\n        try {\n            const current = path[path.length - 1]\n            if (!current) return\n            if (!graphClient) {\n                onError(translations.graphClientNotInitialized)\n                return\n            }\n            const files = await getAllFilesRecursively(current.id)\n            await submitFiles(files)\n        } catch (error) {\n            onError(\n                t(translations.errorSelectingFolder, {\n                    message: (error as Error)?.message ?? '',\n                }),\n            )\n        }\n    }\n\n    return {\n        path,\n        setPath,\n        isClickLoading,\n        handleClick,\n        selectedFiles,\n        showLoader,\n        handleSubmit,\n        downloadProgress,\n        handleCancelDownload,\n        onSelectCurrentFolder,\n    }\n}\n","import React, { FormEventHandler, useState } from 'react'\nimport { useRootContext } from '../context/RootContext'\nimport useFetchFileByUrl from '../hooks/useFetchFileByUrl'\nimport { cn } from '../lib/tailwind'\nimport AdapterViewContainer from './shared/AdapterViewContainer'\n\nexport default function UrlUploader() {\n    const {\n        setFiles,\n        setActiveAdapter,\n        translations: tr,\n        props: {\n            icons: { LoaderIcon },\n            dark,\n            classNames,\n        },\n    } = useRootContext()\n    const [url, setUrl] = useState('')\n    const { loading, fetchImage } = useFetchFileByUrl()\n\n    const handleFormSubmit: FormEventHandler<HTMLFormElement> = async e => {\n        e.preventDefault()\n        const file = await fetchImage(url)\n        if (file) {\n            Object.assign(file, {\n                url,\n            })\n            setFiles([file])\n            setUrl('')\n            setActiveAdapter(undefined)\n        }\n    }\n\n    return (\n        <AdapterViewContainer>\n            <form onSubmit={handleFormSubmit} className=\"upup-px-3 upup-py-2\">\n                <input\n                    type=\"url\"\n                    placeholder={tr.enterFileUrl}\n                    className={cn(\n                        'upup-w-full upup-rounded-md upup-border-2 upup-border-[#e0e0e0] upup-bg-transparent upup-px-3 upup-py-2 upup-outline-none',\n                        {\n                            'upup-border-[#6D6D6D] upup-text-[#6D6D6D] dark:upup-border-[#6D6D6D] dark:upup-text-[#6D6D6D]':\n                                dark,\n                        },\n                        classNames.urlInput,\n                    )}\n                    value={url}\n                    onChange={e => setUrl(e.currentTarget.value)}\n                />\n                <button\n                    className={cn(\n                        'upup-disabled:bg-[#e0e0e0] upup-mt-2 upup-w-full upup-rounded-md upup-bg-blue-600 upup-p-2 upup-text-white upup-transition-all upup-duration-300',\n                        {\n                            'upup-disabled:bg-[#6D6D6D] dark:upup-disabled:bg-[#6D6D6D] upup-bg-[#59D1F9] dark:upup-bg-[#59D1F9]':\n                                dark,\n                        },\n                        classNames.urlFetchButton,\n                    )}\n                    type=\"submit\"\n                    disabled={!url}\n                >\n                    {loading ? <LoaderIcon /> : tr.fetch}\n                </button>\n            </form>\n        </AdapterViewContainer>\n    )\n}\n","import type { Translations } from '../../shared/i18n/types'\nimport { UploadAdapter } from '../../shared/types'\nimport CameraUploader from '../components/CameraUploader'\nimport DropboxUploader from '../components/DropboxUploader'\nimport GoogleDriveUploader from '../components/GoogleDriveUploader'\nimport {\n    CameraIcon,\n    DropBoxIcon,\n    GoogleDriveIcon,\n    LinkIcon,\n    MyDeviceIcon,\n    OneDriveIcon,\n} from '../components/Icons'\nimport OneDriveUploader from '../components/OneDriveUploader'\nimport UrlUploader from '../components/UrlUploader'\n\n/** Translation key used for each adapter's display name */\nexport const adapterNameKeys: Record<UploadAdapter, keyof Translations> = {\n    [UploadAdapter.INTERNAL]: 'myDevice',\n    [UploadAdapter.GOOGLE_DRIVE]: 'googleDrive',\n    [UploadAdapter.ONE_DRIVE]: 'oneDrive',\n    [UploadAdapter.DROPBOX]: 'dropbox',\n    [UploadAdapter.LINK]: 'link',\n    [UploadAdapter.CAMERA]: 'camera',\n}\n\nexport const uploadAdapterObject = {\n    [UploadAdapter.INTERNAL]: {\n        id: UploadAdapter.INTERNAL,\n        nameKey: 'myDevice' as keyof Translations,\n        Icon: MyDeviceIcon,\n        Component: undefined,\n    },\n    [UploadAdapter.GOOGLE_DRIVE]: {\n        id: UploadAdapter.GOOGLE_DRIVE,\n        nameKey: 'googleDrive' as keyof Translations,\n        Icon: GoogleDriveIcon,\n        Component: GoogleDriveUploader,\n    },\n    [UploadAdapter.ONE_DRIVE]: {\n        id: UploadAdapter.ONE_DRIVE,\n        nameKey: 'oneDrive' as keyof Translations,\n        Icon: OneDriveIcon,\n        Component: OneDriveUploader,\n    },\n    [UploadAdapter.DROPBOX]: {\n        id: UploadAdapter.DROPBOX,\n        nameKey: 'dropbox' as keyof Translations,\n        Icon: DropBoxIcon,\n        Component: DropboxUploader,\n    },\n    [UploadAdapter.LINK]: {\n        id: UploadAdapter.LINK,\n        nameKey: 'link' as keyof Translations,\n        Icon: LinkIcon,\n        Component: UrlUploader,\n    },\n    [UploadAdapter.CAMERA]: {\n        id: UploadAdapter.CAMERA,\n        nameKey: 'camera' as keyof Translations,\n        Icon: CameraIcon,\n        Component: CameraUploader,\n    },\n    // {\n    //     id: UploadAdapter.UNSPLASH,\n    //     name: 'Unsplash',\n    //     Icon: UnsplashIcon,\n    // },\n    // { id: UploadAdapter.BOX, name: 'Box', Icon: BoxIcon },\n}\n","import { motion } from 'framer-motion'\nimport React from 'react'\nimport { useRootContext } from '../context/RootContext'\nimport { uploadAdapterObject } from '../lib/constants'\nimport { cn } from '../lib/tailwind'\nimport MyAnimatePresence from './shared/MyAnimatePresence'\n\nexport default function AdapterView() {\n    const {\n        activeAdapter,\n        setActiveAdapter,\n        translations: tr,\n        props: { mini, dark, classNames },\n    } = useRootContext()\n    const UploadComponent =\n        activeAdapter && uploadAdapterObject[activeAdapter].Component\n    const Icon = activeAdapter && uploadAdapterObject[activeAdapter].Icon\n\n    if (!UploadComponent || mini || !activeAdapter || !Icon) return null\n\n    return (\n        <MyAnimatePresence>\n            <motion.div\n                initial={{ y: '-100%' }}\n                animate={{ y: '0%' }}\n                exit={{ y: '-100%' }}\n                className=\"upup-grid upup-h-full upup-w-full upup-grid-rows-[auto,1fr]\"\n                key=\"adapter-view\"\n            >\n                <div\n                    className={cn(\n                        'upup-shadow-bottom upup-flex upup-items-center upup-justify-between upup-bg-black/[0.025] upup-px-3 upup-py-2 upup-text-sm upup-font-medium upup-text-[#1b5dab]',\n                        {\n                            'upup-bg-white/5 upup-text-[#FAFAFA] dark:upup-bg-white/5 dark:upup-text-[#FAFAFA]':\n                                dark,\n                        },\n                        classNames.adapterViewHeader,\n                    )}\n                >\n                    <Icon />\n                    <button\n                        className={cn(\n                            'upup-rounded-md upup-p-1 upup-text-blue-600 upup-transition-all upup-duration-300',\n                            {\n                                'upup-text-[#30C5F7] dark:upup-text-[#30C5F7]':\n                                    dark,\n                            },\n                            classNames.adapterViewCancelButton,\n                        )}\n                        onClick={() => setActiveAdapter(undefined)}\n                        type=\"button\"\n                    >\n                        {tr.cancel}\n                    </button>\n                </div>\n                <UploadComponent />\n            </motion.div>\n        </MyAnimatePresence>\n    )\n}\n","import { motion } from 'framer-motion'\nimport React, { memo } from 'react'\nimport { TbPlayerPauseFilled, TbPlayerPlayFilled } from 'react-icons/tb'\nimport { plural, t } from '../../shared/i18n'\nimport { UploadStatus, useRootContext } from '../context/RootContext'\nimport { cn } from '../lib/tailwind'\nimport FileItem from './FileItem'\nimport MainBoxHeader from './shared/MainBoxHeader'\nimport MyAnimatePresence from './shared/MyAnimatePresence'\nimport ProgressBar from './shared/ProgressBar'\nimport ShouldRender from './shared/ShouldRender'\n\nfunction formatBytes(bytes: number): string {\n    if (bytes === 0) return '0 B'\n    const k = 1024\n    const sizes = ['B', 'KB', 'MB', 'GB']\n    const i = Math.floor(Math.log(bytes) / Math.log(k))\n    return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]\n}\n\nfunction formatEta(seconds: number): string {\n    if (seconds <= 0 || !isFinite(seconds)) return ''\n    const m = Math.floor(seconds / 60)\n    const s = seconds % 60\n    if (m > 0) return `${m}m ${s}s left`\n    return `${s}s left`\n}\n\nexport default memo(function FileList() {\n    const {\n        isAddingMore,\n        activeAdapter,\n        files,\n        translations: tr,\n        upload: {\n            proceedUpload,\n            uploadStatus,\n            totalProgress,\n            uploadSpeed,\n            uploadEta,\n            uploadedBytes,\n            totalBytes,\n        },\n        props: { dark, classNames, isProcessing, maxRetries, resumable },\n        handleDone,\n        handleCancel,\n        handlePause,\n        handleResume,\n    } = useRootContext()\n\n    return (\n        <div\n            className={cn(\n                'upup-relative upup-flex upup-h-full upup-flex-col upup-rounded-lg upup-shadow',\n                {\n                    'upup-hidden': isAddingMore || activeAdapter || !files.size,\n                },\n            )}\n        >\n            <MainBoxHeader handleCancel={handleCancel} />\n\n            <MyAnimatePresence>\n                <motion.div\n                    className={cn(\n                        'upup-preview-scroll upup-flex upup-flex-1 upup-flex-col upup-overflow-y-auto upup-bg-black/[0.075] upup-p-3',\n                        { 'upup-bg-white/10 dark:upup-bg-white/10': dark },\n                        classNames.fileListContainer,\n                    )}\n                >\n                    <div\n                        className={cn(\n                            // Always-on classes\n                            ` ${\n                                isProcessing &&\n                                'upup-pointer-events-none upup-opacity-75'\n                            }  upup-flex upup-flex-col upup-gap-3 upup-font-[Arial,Helvetica,sans-serif]`,\n                            {\n                                'md:upup-grid md:upup-gap-y-6': files.size > 1,\n                                'md:upup-grid-cols-2': files.size > 1,\n                                'upup-flex-1': files.size === 1,\n                                [classNames.fileListContainerInnerMultiple!]:\n                                    classNames.fileListContainerInnerMultiple &&\n                                    files.size > 1,\n                                [classNames.fileListContainerInnerSingle!]:\n                                    classNames.fileListContainerInnerSingle &&\n                                    files.size === 1,\n                            },\n                        )}\n                    >\n                        {Array.from(files.values())\n                            .sort((a: any, b: any) => {\n                                const pa: string =\n                                    (a as any).relativePath ||\n                                    (a as any).webkitRelativePath ||\n                                    a.name\n                                const pb: string =\n                                    (b as any).relativePath ||\n                                    (b as any).webkitRelativePath ||\n                                    b.name\n                                return (\n                                    pa.localeCompare(pb) ||\n                                    a.name.localeCompare(b.name)\n                                )\n                            })\n                            .map(file => (\n                                <FileItem key={file.id} file={file} />\n                            ))}\n                    </div>\n                </motion.div>\n            </MyAnimatePresence>\n            <div\n                className={cn(\n                    'upup-shadow-top upup-flex upup-items-center upup-gap-3 upup-rounded-b-lg upup-bg-black/[0.025] upup-px-3 upup-py-2',\n                    {\n                        'upup-bg-white/5 dark:upup-bg-white/5': dark,\n                    },\n                    classNames.fileListFooter,\n                )}\n            >\n                {/* FIX: Hide upload button when status is SUCCESSFUL or FAILED */}\n                <ShouldRender\n                    if={\n                        uploadStatus !== UploadStatus.SUCCESSFUL &&\n                        uploadStatus !== UploadStatus.FAILED\n                    }\n                >\n                    <button\n                        className={cn(\n                            'upup-disabled:animate-pulse upup-ml-auto upup-rounded-full upup-bg-blue-600 upup-px-4 upup-py-2 upup-text-sm upup-font-medium upup-text-white',\n                            {\n                                'upup-bg-[#30C5F7] dark:upup-bg-[#30C5F7]':\n                                    dark,\n                            },\n                            classNames.uploadButton,\n                        )}\n                        onClick={() => {\n                            proceedUpload()\n                        }}\n                        disabled={\n                            uploadStatus === UploadStatus.ONGOING ||\n                            uploadStatus === UploadStatus.PAUSED ||\n                            isProcessing\n                        }\n                    >\n                        {t(plural(tr, 'uploadFiles', files.size), {\n                            count: files.size,\n                        })}\n                    </button>\n                </ShouldRender>\n                <ShouldRender\n                    if={uploadStatus === UploadStatus.FAILED && !maxRetries}\n                >\n                    <button\n                        className={cn(\n                            'upup-disabled:animate-pulse upup-ml-auto upup-rounded-full upup-bg-red-600 upup-px-4 upup-py-2 upup-text-sm upup-font-medium upup-text-white',\n                            {\n                                'upup-bg-red-500 dark:upup-bg-red-500': dark,\n                            },\n                            classNames.uploadButton,\n                        )}\n                        onClick={() => {\n                            proceedUpload()\n                        }}\n                    >\n                        {resumable?.mode === 'multipart'\n                            ? 'Resume Upload'\n                            : 'Retry Upload'}\n                    </button>\n                </ShouldRender>\n                <ShouldRender if={uploadStatus === UploadStatus.SUCCESSFUL}>\n                    <button\n                        className={cn(\n                            'upup-disabled:animate-pulse upup-ml-auto upup-rounded-lg upup-bg-blue-600 upup-px-3 upup-py-2 upup-text-sm upup-font-medium upup-text-white',\n                            {\n                                'upup-bg-[#30C5F7] dark:upup-bg-[#30C5F7]':\n                                    dark,\n                            },\n                            classNames.uploadDoneButton,\n                        )}\n                        onClick={handleDone}\n                    >\n                        {tr.done}\n                    </button>\n                </ShouldRender>\n                <div className=\"upup-flex upup-flex-1 upup-flex-col upup-gap-1\">\n                    <div className=\"upup-flex upup-items-center upup-gap-2\">\n                        <ShouldRender\n                            if={\n                                resumable?.mode === 'multipart' &&\n                                (uploadStatus === UploadStatus.ONGOING ||\n                                    uploadStatus === UploadStatus.PAUSED)\n                            }\n                        >\n                            <button\n                                className={cn(\n                                    'upup-flex upup-h-7 upup-w-7 upup-items-center upup-justify-center upup-rounded-full upup-bg-gray-200 upup-text-gray-700 upup-transition-colors hover:upup-bg-gray-300',\n                                    {\n                                        'upup-bg-white/10 upup-text-white hover:upup-bg-white/20':\n                                            dark,\n                                    },\n                                )}\n                                onClick={\n                                    uploadStatus === UploadStatus.PAUSED\n                                        ? handleResume\n                                        : handlePause\n                                }\n                                title={\n                                    uploadStatus === UploadStatus.PAUSED\n                                        ? 'Resume upload'\n                                        : 'Pause upload'\n                                }\n                            >\n                                {uploadStatus === UploadStatus.PAUSED ? (\n                                    <TbPlayerPlayFilled size={14} />\n                                ) : (\n                                    <TbPlayerPauseFilled size={14} />\n                                )}\n                            </button>\n                        </ShouldRender>\n                        <ProgressBar\n                            className=\"upup-flex-1\"\n                            progressBarClassName=\"upup-rounded\"\n                            progress={totalProgress}\n                            showValue\n                        />\n                    </div>\n                    <ShouldRender\n                        if={\n                            (uploadStatus === UploadStatus.ONGOING ||\n                                uploadStatus === UploadStatus.PAUSED) &&\n                            totalBytes > 0\n                        }\n                    >\n                        <div\n                            className={cn(\n                                'upup-flex upup-items-center upup-justify-between upup-text-[11px] upup-text-gray-500',\n                                {\n                                    'upup-text-gray-400': dark,\n                                },\n                            )}\n                        >\n                            <span>\n                                {formatBytes(uploadedBytes)} of{' '}\n                                {formatBytes(totalBytes)}\n                                {uploadSpeed > 0 &&\n                                    ` · ${formatBytes(uploadSpeed)}/s`}\n                            </span>\n                            <ShouldRender\n                                if={\n                                    uploadStatus === UploadStatus.ONGOING &&\n                                    uploadEta > 0\n                                }\n                            >\n                                <span>{formatEta(uploadEta)}</span>\n                            </ShouldRender>\n                            <ShouldRender\n                                if={uploadStatus === UploadStatus.PAUSED}\n                            >\n                                <span>Paused</span>\n                            </ShouldRender>\n                        </div>\n                    </ShouldRender>\n                </div>\n            </div>\n        </div>\n    )\n})\n","import React, { MouseEventHandler, memo, useCallback, useState } from 'react'\nimport { FileWithParams } from '../../shared/types'\nimport { useRootContext } from '../context/RootContext'\nimport { cn } from '../lib/tailwind'\nimport FilePreview from './FilePreview'\nimport FilePreviewPortal from './FilePreviewPortal'\n\ntype Props = {\n    file: FileWithParams\n}\n\nexport default memo(function FileItem({ file }: Props) {\n    const {\n        files,\n        props: { classNames, onFileClick },\n    } = useRootContext()\n    const [showPreviewPortal, setShowPreviewPortal] = useState(false)\n    const [canPreview, setCanPreview] = useState(false)\n\n    const handleStopPropagation: MouseEventHandler<HTMLElement> = useCallback(\n        e => {\n            e.stopPropagation()\n        },\n        [],\n    )\n    const openPreviewPortal = useCallback(() => {\n        setShowPreviewPortal(true)\n    }, [])\n\n    return (\n        <div\n            data-testid=\"upup-file-item\"\n            className={cn(\n                'upup-relative upup-flex upup-flex-1 upup-flex-col upup-items-start upup-gap-1 upup-bg-transparent',\n                {\n                    [classNames.fileItemMultiple!]:\n                        classNames.fileItemMultiple && files.size > 1,\n                    [classNames.fileItemSingle!]:\n                        classNames.fileItemSingle && files.size === 1,\n                },\n            )}\n        >\n            <FilePreview\n                fileName={file.name}\n                fileType={file.type}\n                fileId={file.id}\n                fileUrl={file.url}\n                fileSize={file.size}\n                canPreview={canPreview}\n                setCanPreview={setCanPreview}\n                onRequestPreview={openPreviewPortal}\n                onClick={() => onFileClick(file)}\n            />\n            {/* Keep preview portal mounted without showing duplicate info */}\n            {canPreview && showPreviewPortal && (\n                <FilePreviewPortal\n                    onStopPropagation={handleStopPropagation}\n                    onClick={() => setShowPreviewPortal(false)}\n                    fileType={file.type}\n                    fileUrl={file.url}\n                    fileName={file.name}\n                    fileSize={file.size}\n                />\n            )}\n        </div>\n    )\n})\n","import React, {\n    Dispatch,\n    HTMLAttributes,\n    MouseEventHandler,\n    SetStateAction,\n    memo,\n    useEffect,\n    useMemo,\n} from 'react'\n\nimport type { Translations } from '../../shared/i18n/types'\nimport { useRootContext } from '../context/RootContext'\nimport { fileCanPreviewText, fileGetIsImage, fileGetIsText } from '../lib/file'\nimport { cn } from '../lib/tailwind'\nimport FilePreviewThumbnail from './FilePreviewThumbnail'\nimport ProgressBar from './shared/ProgressBar'\nimport ShouldRender from './shared/ShouldRender'\n\ntype Props = {\n    fileName: string\n    fileType: string\n    fileId: string\n    fileUrl: string\n    fileSize?: number\n    canPreview: boolean\n    setCanPreview: Dispatch<SetStateAction<boolean>>\n    onRequestPreview?: () => void\n} & HTMLAttributes<HTMLDivElement>\n\nexport default memo(function FilePreview(props: Props) {\n    const {\n        fileType,\n        fileId,\n        fileName,\n        fileUrl,\n        fileSize,\n        canPreview,\n        setCanPreview,\n        onRequestPreview,\n        ...restProps\n    } = props\n\n    const {\n        handleFileRemove,\n        translations: tr,\n        openImageEditor,\n        upload: { filesProgressMap },\n        props: {\n            classNames,\n            icons: { FileDeleteIcon },\n            allowPreview,\n            imageEditor,\n        },\n        files,\n    } = useRootContext()\n\n    const isImage = useMemo(() => fileGetIsImage(fileType), [fileType])\n    const isText = useMemo(\n        () => fileGetIsText(fileType, fileName),\n        [fileType, fileName],\n    )\n\n    // Only allow inline text preview for files within the safe size threshold\n    const canPreviewText = useMemo(\n        () => fileCanPreviewText(fileType, fileName, fileSize),\n        [fileType, fileName, fileSize],\n    )\n\n    const progress = useMemo(\n        () =>\n            Math.floor(\n                (filesProgressMap[fileId]?.loaded /\n                    filesProgressMap[fileId]?.total) *\n                    100,\n            ),\n        [fileId, filesProgressMap],\n    )\n\n    useEffect(() => {\n        // For text files, only set canPreview if below the safe size threshold.\n        // Large text files (e.g. 3MB+ JSON) would freeze the browser if rendered\n        // via <object> tags, so they get a static icon instead.\n        if ((isImage || (isText && canPreviewText)) && !canPreview)\n            setCanPreview(true)\n    }, [isImage, isText, canPreviewText, canPreview, setCanPreview])\n\n    const onHandleFileRemove: MouseEventHandler<HTMLButtonElement> = e => {\n        e.stopPropagation()\n        handleFileRemove(fileId)\n    }\n\n    const onHandleEditImage: MouseEventHandler<HTMLButtonElement> = e => {\n        e.stopPropagation()\n        const file = files.get(fileId)\n        if (file) openImageEditor(file)\n    }\n\n    const formatFileSize = (bytes: number | undefined, tr: Translations) => {\n        if (!bytes || bytes === 0) return tr.zeroBytes\n        const k = 1024\n        const sizes = [tr.bytes, tr.kb, tr.mb, tr.gb]\n        const i = Math.floor(Math.log(bytes) / Math.log(k))\n        return Math.round((bytes / Math.pow(k, i)) * 10) / 10 + ' ' + sizes[i]\n    }\n\n    return (\n        <div className=\"upup-inline-block\" {...restProps}>\n            <div\n                className={cn(\n                    'upup-relative upup-h-[145px] upup-w-[145px] upup-overflow-hidden upup-rounded-lg upup-bg-white upup-shadow-sm',\n                    'upup-bg-contain upup-bg-center upup-bg-no-repeat',\n                    {\n                        [classNames.fileThumbnailMultiple!]:\n                            classNames.fileThumbnailMultiple && files.size > 1,\n                        [classNames.fileThumbnailSingle!]:\n                            classNames.fileThumbnailSingle && files.size === 1,\n                    },\n                )}\n                style={\n                    isImage ? { backgroundImage: `url(${fileUrl})` } : undefined\n                }\n            >\n                <ShouldRender if={!isImage}>\n                    <div className=\"upup-flex upup-h-full upup-items-center upup-justify-center upup-p-6\">\n                        <FilePreviewThumbnail\n                            canPreview={canPreview}\n                            setCanPreview={setCanPreview}\n                            fileType={fileType}\n                            fileName={fileName}\n                            fileUrl={fileUrl}\n                            fileSize={fileSize}\n                            allowPreview={allowPreview}\n                            classNames={classNames}\n                            translations={tr}\n                        />\n                    </div>\n                </ShouldRender>\n\n                {isImage && imageEditor.enabled && (\n                    <button\n                        className={cn(\n                            'upup-absolute upup-right-1.5 upup-top-8 upup-z-10',\n                            'upup-flex upup-h-5 upup-w-5 upup-items-center upup-justify-center',\n                            'upup-rounded-full upup-bg-white upup-text-blue-600 upup-shadow-sm',\n                            'hover:upup-bg-white hover:upup-text-blue-700',\n                            'upup-ring-1 upup-ring-black/5',\n                            'disabled:upup-cursor-not-allowed disabled:upup-opacity-50',\n                        )}\n                        onClick={onHandleEditImage}\n                        type=\"button\"\n                        disabled={!!progress}\n                        aria-label=\"Edit image\"\n                    >\n                        <svg\n                            xmlns=\"http://www.w3.org/2000/svg\"\n                            viewBox=\"0 0 20 20\"\n                            fill=\"currentColor\"\n                            className=\"upup-h-3 upup-w-3\"\n                            aria-hidden=\"true\"\n                        >\n                            <path d=\"M2.695 14.763l-1.262 3.154a.5.5 0 00.65.65l3.155-1.262a4 4 0 001.343-.885L17.5 5.5a2.121 2.121 0 00-3-3L3.58 13.42a4 4 0 00-.885 1.343z\" />\n                        </svg>\n                    </button>\n                )}\n\n                <button\n                    className={cn(\n                        'upup-absolute upup-right-1.5 upup-top-1.5 upup-z-10',\n                        'upup-flex upup-h-5 upup-w-5 upup-items-center upup-justify-center',\n                        'upup-rounded-full upup-bg-white upup-text-red-600 upup-shadow-sm',\n                        'hover:upup-bg-white hover:upup-text-red-700',\n                        'upup-ring-1 upup-ring-black/5',\n                        'disabled:upup-cursor-not-allowed disabled:upup-opacity-50',\n                        classNames.fileDeleteButton,\n                    )}\n                    onClick={onHandleFileRemove}\n                    type=\"button\"\n                    disabled={!!progress}\n                    aria-label={tr.removeFile}\n                >\n                    <FileDeleteIcon className=\"upup-h-3 upup-w-3\" />\n                </button>\n\n                <ProgressBar\n                    className=\"upup-absolute upup-bottom-0 upup-left-0 upup-right-0\"\n                    progressBarClassName=\"upup-rounded-t-none upup-rounded-b-md\"\n                    progress={progress}\n                />\n            </div>\n\n            <div className=\"upup-mt-1 upup-px-0.5\">\n                <div className=\"upup-truncate upup-text-[13px] upup-font-normal upup-leading-tight upup-text-white\">\n                    {fileName}\n                </div>\n                <div className=\"upup-mt-0.5 upup-text-[11px] upup-leading-tight upup-text-gray-400\">\n                    {formatFileSize(fileSize, tr)}\n                </div>\n                {allowPreview && canPreview && (\n                    <button\n                        type=\"button\"\n                        className=\"upup-mt-1 upup-text-[11px] upup-font-normal upup-leading-tight upup-text-[#4A9EFF] upup-transition-all hover:upup-text-blue-300 hover:upup-underline\"\n                        onClick={onRequestPreview}\n                    >\n                        {tr.clickToPreview}\n                    </button>\n                )}\n            </div>\n        </div>\n    )\n})\n","import React, { Dispatch, SetStateAction, memo, useMemo } from 'react'\nimport type { Translations } from '../../shared/i18n/types'\nimport { UpupUploaderPropsClassNames } from '../../shared/types'\nimport {\n    fileCanPreviewText,\n    fileGetExtension,\n    fileGetIsText,\n    fileIs3D,\n} from '../lib/file'\nimport { cn } from '../lib/tailwind'\nimport FileIcon from './FileIcon'\nimport ShouldRender from './shared/ShouldRender'\n\ntype Props = {\n    canPreview: boolean\n    setCanPreview: Dispatch<SetStateAction<boolean>>\n    fileType: string\n    fileName: string\n    fileUrl: string\n    fileSize?: number\n    classNames: UpupUploaderPropsClassNames\n    allowPreview: boolean\n    translations: Translations\n}\n\nexport default memo(\n    function FilePreviewThumbnail({\n        canPreview,\n        setCanPreview,\n        fileUrl,\n        fileName,\n        fileType,\n        fileSize,\n        classNames,\n        allowPreview,\n        translations: tr,\n    }: Props) {\n        const extension = useMemo(\n            () => fileGetExtension(fileType, fileName),\n            [fileType, fileName],\n        )\n\n        const is3D = useMemo(() => {\n            return fileIs3D(extension?.toLowerCase() || '')\n        }, [extension])\n\n        // Large text files (e.g. 3MB+ JSON) must not be rendered via <object> tags\n        // as the browser will attempt to parse and lay out the entire content,\n        // blocking the main thread and freezing the page.\n        const isOversizedText = useMemo(() => {\n            const isText = fileGetIsText(fileType, fileName)\n            return isText && !fileCanPreviewText(fileType, fileName, fileSize)\n        }, [fileType, fileName, fileSize])\n\n        if (is3D || isOversizedText) {\n            return (\n                <div className=\"upup-flex upup-flex-col upup-items-center upup-gap-2\">\n                    <FileIcon\n                        extension={extension}\n                        className={classNames.fileIcon}\n                    />\n                </div>\n            )\n        }\n\n        return (\n            <>\n                <ShouldRender if={!canPreview}>\n                    <object\n                        data={fileUrl}\n                        width=\"0%\"\n                        height=\"0%\"\n                        name={fileName}\n                        type={fileType}\n                        onLoad={() => setCanPreview(true)}\n                    >\n                        <p>{tr.loading}</p>\n                    </object>\n                    <FileIcon extension={extension} />\n                </ShouldRender>\n\n                <ShouldRender if={canPreview}>\n                    <FileIcon\n                        extension={extension}\n                        className={cn(\n                            {\n                                'md:upup-hidden': allowPreview,\n                            },\n                            classNames.fileIcon,\n                        )}\n                    />\n                    <div\n                        className={cn(\n                            `upup-relative upup-hidden upup-h-full upup-w-full ${\n                                allowPreview && 'md:upup-block'\n                            }`,\n                        )}\n                    >\n                        <object\n                            data={fileUrl}\n                            width=\"100%\"\n                            height=\"100%\"\n                            name={fileName}\n                            type={fileType}\n                            className=\"upup-absolute upup-h-full upup-w-full\"\n                        >\n                            <p>{tr.loading}</p>\n                        </object>\n                    </div>\n                </ShouldRender>\n            </>\n        )\n    },\n    (prev, next) =>\n        prev.canPreview === next.canPreview &&\n        prev.fileType === next.fileType &&\n        prev.fileUrl === next.fileUrl,\n)\n","import React, { forwardRef, JSX, memo, SVGAttributes, SVGProps } from 'react'\nimport {\n    TbFile,\n    TbFileTypeBmp,\n    TbFileTypeCss,\n    TbFileTypeCsv,\n    TbFileTypeDocx,\n    TbFileTypeHtml,\n    TbFileTypeJpg,\n    TbFileTypeJs,\n    TbFileTypeJsx,\n    TbFileTypePdf,\n    TbFileTypePhp,\n    TbFileTypePng,\n    TbFileTypePpt,\n    TbFileTypeRs,\n    TbFileTypeSql,\n    TbFileTypeSvg,\n    TbFileTypeTs,\n    TbFileTypeTsx,\n    TbFileTypeTxt,\n    TbFileTypeVue,\n    TbFileTypeXls,\n    TbFileTypeXml,\n    TbFileTypeZip,\n} from 'react-icons/tb'\nimport { useRootContext } from '../context/RootContext'\nimport { cn } from '../lib/tailwind'\n\ntype IconType = (props: SVGProps<SVGSVGElement>) => JSX.Element\n\nconst fileTypes: { [key: string]: IconType } = {\n    bmp: TbFileTypeBmp,\n    css: TbFileTypeCss,\n    csv: TbFileTypeCsv,\n    docx: TbFileTypeDocx,\n    html: TbFileTypeHtml,\n    jpg: TbFileTypeJpg,\n    js: TbFileTypeJs,\n    jsx: TbFileTypeJsx,\n    pdf: TbFileTypePdf,\n    png: TbFileTypePng,\n    php: TbFileTypePhp,\n    ppt: TbFileTypePpt,\n    rs: TbFileTypeRs,\n    sql: TbFileTypeSql,\n    svg: TbFileTypeSvg,\n    ts: TbFileTypeTs,\n    tsx: TbFileTypeTsx,\n    txt: TbFileTypeTxt,\n    vue: TbFileTypeVue,\n    xls: TbFileTypeXls,\n    xml: TbFileTypeXml,\n    zip: TbFileTypeZip,\n}\n\nexport default memo(\n    forwardRef<\n        SVGSVGElement,\n        {\n            extension?: string\n        } & SVGAttributes<SVGElement>\n    >(function FileIcon({ extension = '', className, ...restProps }, ref) {\n        const {\n            props: { dark },\n        } = useRootContext()\n        const IconComponent = fileTypes[extension] || TbFile\n        return (\n            <IconComponent\n                ref={ref}\n                className={cn('upup-text-5xl upup-text-blue-600', className, {\n                    'upup-text-[#59D1F9] dark:upup-text-[#59D1F9]': dark,\n                })}\n                {...restProps}\n            />\n        )\n    }),\n)\n","import React, { forwardRef, HTMLAttributes } from 'react'\nimport { useRootContext } from '../../context/RootContext'\nimport { cn } from '../../lib/tailwind'\nimport ShouldRender from './ShouldRender'\n\ntype Props = {\n    progress: number\n    showValue?: boolean\n    progressBarClassName?: string\n} & HTMLAttributes<HTMLDivElement>\n\nexport default forwardRef<HTMLDivElement, Props>(function ProgressBar(\n    { progress, className, progressBarClassName, showValue = false, ...rest },\n    ref,\n) {\n    const {\n        props: { classNames, dark },\n    } = useRootContext()\n    return (\n        <ShouldRender if={!!progress}>\n            <div\n                ref={ref}\n                className={cn(\n                    'upup-flex upup-items-center upup-gap-2',\n                    className,\n                    classNames.progressBarContainer,\n                )}\n                {...rest}\n            >\n                <div\n                    className={cn(\n                        'upup-h-[6px] upup-flex-1 upup-overflow-hidden upup-rounded-[4px] upup-bg-[#F5F5F5]',\n                        progressBarClassName,\n                        classNames.progressBar,\n                    )}\n                >\n                    <div\n                        style={{\n                            width: progress + '%',\n                        }}\n                        className={cn(\n                            'upup-h-full upup-bg-[#8EA5E7]',\n                            classNames.progressBarInner,\n                        )}\n                    />\n                </div>\n                <ShouldRender if={!!showValue}>\n                    <p\n                        className={cn(\n                            'upup-text-xs upup-font-semibold',\n                            {\n                                'upup-text-white': dark,\n                            },\n                            classNames.progressBarText,\n                        )}\n                    >\n                        {progress}%\n                    </p>\n                </ShouldRender>\n            </div>\n        </ShouldRender>\n    )\n})\n","import React, {\n    forwardRef,\n    HTMLAttributes,\n    memo,\n    MouseEventHandler,\n    useEffect,\n    useMemo,\n    useState,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { t } from '../../shared/i18n'\nimport { useRootContext } from '../context/RootContext'\nimport {\n    fileGetIsImage,\n    fileGetIsText,\n    PREVIEW_MAX_TEXT_SIZE,\n    PREVIEW_TEXT_TRUNCATE_LENGTH,\n} from '../lib/file'\nimport { cn } from '../lib/tailwind'\nimport ShouldRender from './shared/ShouldRender'\n\nexport default memo(\n    forwardRef<\n        HTMLDivElement,\n        HTMLAttributes<HTMLDivElement> & {\n            onStopPropagation: MouseEventHandler<HTMLDivElement>\n            fileUrl: string\n            fileName: string\n            fileType: string\n            fileSize?: number\n        }\n    >(function FilePreviewPortal(\n        {\n            onStopPropagation,\n            fileUrl,\n            fileName,\n            fileType,\n            fileSize,\n            ...restProps\n        },\n        ref,\n    ) {\n        const {\n            props: { dark, classNames },\n            translations: tr,\n        } = useRootContext()\n        const isImage = useMemo(() => fileGetIsImage(fileType), [fileType])\n        const isText = useMemo(\n            () => fileGetIsText(fileType, fileName),\n            [fileType, fileName],\n        )\n\n        const isOversizedText = useMemo(\n            () =>\n                isText &&\n                fileSize !== undefined &&\n                fileSize > PREVIEW_MAX_TEXT_SIZE,\n            [isText, fileSize],\n        )\n\n        const [textContent, setTextContent] = useState<string>('')\n        const [textLoading, setTextLoading] = useState(false)\n        const [textError, setTextError] = useState<string>()\n\n        const [isTruncated, setIsTruncated] = useState(false)\n\n        useEffect(() => {\n            let cancelled = false\n            const loadText = async () => {\n                if (!isText) return\n                try {\n                    setTextLoading(true)\n\n                    if (isOversizedText) {\n                        // For large text files, only read up to PREVIEW_TEXT_TRUNCATE_LENGTH\n                        // to avoid freezing the browser with massive DOM rendering\n                        const res = await fetch(fileUrl)\n                        const reader = res.body?.getReader()\n                        if (!reader) throw new Error('Cannot read file')\n\n                        const decoder = new TextDecoder()\n                        let result = ''\n                        let done = false\n\n                        while (\n                            !done &&\n                            result.length < PREVIEW_TEXT_TRUNCATE_LENGTH\n                        ) {\n                            const { value, done: streamDone } =\n                                await reader.read()\n                            done = streamDone\n                            if (value) {\n                                result += decoder.decode(value, {\n                                    stream: !done,\n                                })\n                            }\n                        }\n                        reader.cancel()\n\n                        if (!cancelled) {\n                            const wasTruncated =\n                                !done ||\n                                result.length > PREVIEW_TEXT_TRUNCATE_LENGTH\n                            if (wasTruncated) {\n                                result = result.slice(\n                                    0,\n                                    PREVIEW_TEXT_TRUNCATE_LENGTH,\n                                )\n                            }\n                            setIsTruncated(wasTruncated)\n                            setTextContent(result)\n                        }\n                    } else {\n                        const res = await fetch(fileUrl)\n                        const txt = await res.text()\n                        if (!cancelled) setTextContent(txt)\n                    }\n                } catch (e) {\n                    if (!cancelled)\n                        setTextError((e as Error)?.message || 'Preview error')\n                } finally {\n                    if (!cancelled) setTextLoading(false)\n                }\n            }\n            loadText()\n            return () => {\n                cancelled = true\n            }\n        }, [fileUrl, isText, isOversizedText])\n\n        return createPortal(\n            <div className=\"upup-scope\">\n                <div\n                    className=\"upup-fixed upup-inset-0 upup-z-[2147483647] upup-flex upup-items-center upup-justify-center upup-bg-black/40\"\n                    ref={ref}\n                    {...restProps}\n                >\n                    <div className=\"upup-relative upup-h-[90vh] upup-w-[90vw] upup-p-4\">\n                        <div\n                            className={cn(\n                                'upup-absolute upup-inset-0 upup-m-4 upup-bg-white',\n                                {\n                                    'upup-bg-[#232323] dark:upup-bg-[#232323]':\n                                        dark,\n                                },\n                                classNames.filePreviewPortal,\n                            )}\n                            onClick={onStopPropagation}\n                        >\n                            <ShouldRender if={isImage}>\n                                <img\n                                    src={fileUrl}\n                                    alt={fileName}\n                                    className=\"upup-h-full upup-w-full upup-rounded upup-object-contain\"\n                                />\n                            </ShouldRender>\n                            <ShouldRender if={!isImage}>\n                                <ShouldRender if={isText}>\n                                    <div className=\"upup-h-full upup-w-full upup-overflow-auto upup-p-4 upup-font-mono upup-text-xs\">\n                                        {textLoading && <p>{tr.loading}</p>}\n                                        {textError && (\n                                            <p>\n                                                {t(tr.previewError, {\n                                                    message: textError,\n                                                })}\n                                            </p>\n                                        )}\n                                        {!textLoading && !textError && (\n                                            <>\n                                                <pre className=\"upup-whitespace-pre-wrap\">\n                                                    {textContent}\n                                                </pre>\n                                                {isTruncated && (\n                                                    <div className=\"upup-mt-4 upup-rounded upup-border upup-border-yellow-500/30 upup-bg-yellow-500/10 upup-px-3 upup-py-2 upup-text-xs upup-text-yellow-400\">\n                                                        Content truncated - file\n                                                        is too large to preview\n                                                        in full.\n                                                    </div>\n                                                )}\n                                            </>\n                                        )}\n                                    </div>\n                                </ShouldRender>\n                                <ShouldRender if={!isText}>\n                                    <object\n                                        data={fileUrl}\n                                        width=\"100%\"\n                                        height=\"100%\"\n                                        name={fileName}\n                                        type={fileType}\n                                    >\n                                        <p>{tr.loading}</p>\n                                    </object>\n                                </ShouldRender>\n                            </ShouldRender>\n                        </div>\n                    </div>\n                </div>\n            </div>,\n            document.body,\n        )\n    }),\n)\n","import React, { useMemo } from 'react'\nimport { plural, t } from '../../../shared/i18n'\nimport { UploadStatus, useRootContext } from '../../context/RootContext'\nimport { cn } from '../../lib/tailwind'\nimport ShouldRender from './ShouldRender'\n\ntype Props = {\n    handleCancel(): void\n}\n\nexport default function MainBoxHeader({ handleCancel }: Readonly<Props>) {\n    const {\n        files,\n        setIsAddingMore,\n        isAddingMore,\n        translations: tr,\n        props: {\n            mini,\n            limit,\n            isProcessing,\n            dark,\n            classNames,\n            icons: { ContainerAddMoreIcon },\n        },\n        upload: { uploadStatus },\n    } = useRootContext()\n    const isUploading = uploadStatus === UploadStatus.ONGOING\n    const isLimitReached = limit === files.size\n    const cancelText = useMemo(\n        () => (isAddingMore ? tr.cancel : tr.removeAllFiles),\n        [isAddingMore, tr],\n    )\n\n    if (mini) return null\n\n    return (\n        <div\n            className={cn(\n                'upup-shadow-bottom upup-left-0 upup-right-0 upup-top-0 upup-z-10 upup-grid upup-grid-cols-4 upup-grid-rows-2 upup-items-center upup-justify-between upup-rounded-t-lg upup-bg-black/[0.025] upup-px-3 upup-py-2 md:upup-grid-rows-1',\n                {\n                    'upup-bg-white/5 dark:upup-bg-white/5': dark,\n                },\n                classNames.containerHeader,\n            )}\n        >\n            <button\n                className={cn(\n                    'upup-max-md upup-col-start-1 upup-col-end-3 upup-row-start-2 upup-p-1 upup-text-left upup-text-sm upup-text-blue-600 md:upup-col-end-2 md:upup-row-start-1',\n                    {\n                        'upup-text-[#30C5F7] dark:upup-text-[#30C5F7]': dark,\n                    },\n                    classNames.containerCancelButton,\n                )}\n                onClick={handleCancel}\n                disabled={isUploading || isProcessing}\n            >\n                {cancelText}\n            </button>\n            <span\n                className={cn(\n                    'upup-col-span-4 upup-text-center upup-text-sm upup-text-[#6D6D6D] md:upup-col-span-2',\n                    {\n                        'upup-text-gray-300 dark:upup-text-gray-300': dark,\n                    },\n                )}\n            >\n                <ShouldRender if={isAddingMore}>\n                    {tr.addingMoreFiles}\n                </ShouldRender>\n                <ShouldRender if={!isAddingMore}>\n                    {t(plural(tr, 'filesSelected', files.size), {\n                        count: files.size,\n                    })}\n                </ShouldRender>\n            </span>\n            <ShouldRender if={!isAddingMore && limit > 1 && !isLimitReached}>\n                <button\n                    className={cn(\n                        'upup-col-start-3 upup-col-end-5 upup-flex upup-items-center upup-justify-end upup-gap-1 upup-rounded-md upup-border upup-border-dashed upup-border-blue-400/50 upup-px-2 upup-py-1 upup-text-sm upup-text-blue-600 md:upup-col-start-4',\n                        {\n                            'upup-text-[#30C5F7] dark:upup-text-[#30C5F7]':\n                                dark,\n                        },\n                        classNames.containerAddMoreButton,\n                    )}\n                    onClick={() => setIsAddingMore(true)}\n                    disabled={isUploading || isProcessing}\n                >\n                    <ContainerAddMoreIcon /> {tr.addMore}\n                </button>\n            </ShouldRender>\n        </div>\n    )\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport {\n    TbCameraRotate,\n    TbCapture,\n    TbLoader,\n    TbPlus,\n    TbTrash,\n} from 'react-icons/tb'\nimport { en_US, mergeTranslations, t } from '../../shared/i18n'\nimport checkFileType from '../../shared/lib/checkFileType'\nimport {\n    FileWithParams,\n    ResolvedImageEditorOptions,\n    UploadAdapter,\n    UpupUploaderProps,\n} from '../../shared/types'\nimport { IRootContext, UploadStatus } from '../context/RootContext'\nimport {\n    checkFileSize,\n    compressFile,\n    fileAppendParams,\n    revokeFileUrl,\n    sizeToBytes,\n} from '../lib/file'\nimport {\n    blobToFileWithParams,\n    dataURLtoBlob,\n    revokeAndReplace,\n} from '../lib/imageEditorHelpers'\nimport {\n    fileFingerprint,\n    loadSession,\n} from '../lib/resumable/multipartSessionStore'\nimport { ProviderSDK } from '../lib/storage/provider'\nimport { UploadResult } from '../types/StorageSDK'\n\ntype FileProgress = {\n    id: string\n    loaded: number\n    total: number\n}\n\nexport type FilesProgressMap = Record<string, FileProgress>\n\nasync function uploadWithRetry(\n    fn: () => Promise<UploadResult>,\n    maxRetries: number,\n): Promise<UploadResult> {\n    for (let attempt = 1; attempt <= maxRetries; attempt++) {\n        try {\n            return await fn()\n        } catch (error) {\n            if (attempt === maxRetries) throw error\n        }\n    }\n    throw new Error('Upload failed after retries')\n}\n\nexport default function useRootProvider({\n    accept = '*',\n    mini = false,\n    dark = false,\n    limit: propLimit = 1,\n    isProcessing = false,\n    allowPreview = true,\n    showSelectFolderButton = false,\n    maxFileSize,\n    shouldCompress = false,\n    uploadAdapters = [UploadAdapter.INTERNAL, UploadAdapter.LINK],\n    onError: errorHandler,\n    onWarn: warningHandler,\n    icons = {},\n    classNames = {},\n    localePack,\n    translations: translationOverrides,\n    onIntegrationClick = () => {},\n    onFileClick = () => {},\n    onFileRemove = () => {},\n    onFilesDragOver = () => {},\n    onFilesDragLeave = () => {},\n    onFilesDrop = () => {},\n    onFileTypeMismatch = () => {},\n    imageEditor: imageEditorProp,\n    onFileUploadStart = () => {},\n    onFileUploadProgress = () => {},\n    onFilesUploadProgress = () => {},\n    onFileUploadComplete = () => {},\n    onFilesUploadComplete = () => {},\n    onFilesSelected = () => {},\n    onDoneClicked = () => {},\n    onPrepareFiles,\n    provider,\n    tokenEndpoint,\n    driveConfigs,\n    customProps,\n    enableAutoCorsConfig = false,\n    maxRetries,\n    resumable,\n}: UpupUploaderProps): IRootContext {\n    const inputRef = useRef<HTMLInputElement>(null)\n    const [isAddingMore, setIsAddingMore] = useState(false)\n    const [selectedFilesMap, setSelectedFilesMap] = useState<\n        Map<string, FileWithParams>\n    >(new Map())\n    const [activeAdapter, setActiveAdapter] = useState<UploadAdapter>()\n    const [uploadStatus, setUploadStatus] = useState(UploadStatus.PENDING)\n    const [filesProgressMap, setFilesProgressMap] = useState<FilesProgressMap>(\n        {} as FilesProgressMap,\n    )\n    const [uploadError, setUploadError] = useState('')\n    const [uploadSpeed, setUploadSpeed] = useState(0)\n    const [uploadEta, setUploadEta] = useState(0)\n    const [uploadedBytes, setUploadedBytes] = useState(0)\n    const [totalBytes, setTotalBytes] = useState(0)\n\n    // SDK ref for pause/resume control\n    const sdkRef = useRef<ProviderSDK | null>(null)\n    // Speed tracking refs\n    const speedSamplesRef = useRef<{ time: number; bytes: number }[]>([])\n    // Ref for totalBytes so progress callback always has the latest value\n    const totalBytesRef = useRef(0)\n    const [editingFile, setEditingFile] = useState<FileWithParams | null>(null)\n    const [editorQueue, setEditorQueue] = useState<FileWithParams[]>([])\n\n    // Keep a ref to selectedFilesMap for unmount cleanup\n    const selectedFilesMapRef = useRef(selectedFilesMap)\n    useEffect(() => {\n        selectedFilesMapRef.current = selectedFilesMap\n    }, [selectedFilesMap])\n\n    // Revoke all blob URLs on unmount to prevent memory leaks in SPAs\n    useEffect(() => {\n        return () => {\n            selectedFilesMapRef.current.forEach(file => revokeFileUrl(file))\n        }\n    }, [])\n\n    const limit = useMemo(\n        () => (mini ? 1 : Math.max(propLimit, 1)),\n        [mini, propLimit],\n    )\n    const multiple = useMemo(() => (mini ? false : limit > 1), [limit, mini])\n\n    const translations = useMemo(\n        () => mergeTranslations(localePack ?? en_US, translationOverrides),\n        [localePack, translationOverrides],\n    )\n\n    const totalProgress = useMemo(() => {\n        const filesProgressMapValues = Object.values(filesProgressMap)\n        if (!filesProgressMapValues.length) return 0\n\n        const loadedValues = filesProgressMapValues.reduce(\n            (a, b) => a + (b.loaded / b.total) * 100,\n            0,\n        )\n        return Math.round(loadedValues / filesProgressMapValues.length)\n    }, [filesProgressMap])\n\n    const resolvedImageEditor = useMemo<ResolvedImageEditorOptions>(() => {\n        if (imageEditorProp === true) {\n            return { enabled: true, autoOpen: 'never', display: 'inline' }\n        }\n        if (typeof imageEditorProp === 'object' && imageEditorProp !== null) {\n            return {\n                ...imageEditorProp,\n                enabled: imageEditorProp.enabled ?? false,\n                autoOpen: imageEditorProp.autoOpen ?? 'never',\n                display: imageEditorProp.display ?? 'inline',\n            }\n        }\n        return { enabled: false, autoOpen: 'never', display: 'inline' }\n    }, [imageEditorProp])\n\n    const openImageEditor = useCallback(\n        (file: FileWithParams) => {\n            setEditingFile(file)\n            resolvedImageEditor.onOpen?.(file)\n        },\n        [resolvedImageEditor],\n    )\n\n    const advanceEditorQueue = useCallback(() => {\n        setEditorQueue(prev => {\n            if (prev.length === 0) return prev\n            const [next, ...rest] = prev\n            setTimeout(() => openImageEditor(next), 0)\n            return rest\n        })\n    }, [openImageEditor])\n\n    const closeImageEditor = useCallback(() => {\n        const current = editingFile\n        setEditingFile(null)\n        advanceEditorQueue()\n        if (current) resolvedImageEditor.onCancel?.(current)\n    }, [editingFile, advanceEditorQueue, resolvedImageEditor])\n\n    const saveImageEdit = useCallback(\n        (editedImageData: string, mimeType?: string) => {\n            if (!editingFile) return\n\n            const original = editingFile\n            const outputMime =\n                mimeType ||\n                resolvedImageEditor.output?.mimeType ||\n                original.type\n            const quality = resolvedImageEditor.output?.quality\n\n            // Convert the base64 / dataURL to a Blob.\n            // If a quality or mimeType override is specified and the data is a\n            // plain dataURL, we re-encode via canvas; otherwise use as-is.\n            let blob: Blob\n            if (\n                (quality !== undefined || outputMime !== original.type) &&\n                editedImageData.startsWith('data:')\n            ) {\n                // Fast path: just decode the dataURL directly with the given mime.\n                const raw = dataURLtoBlob(editedImageData)\n                blob = new Blob([raw], { type: outputMime })\n            } else {\n                blob = dataURLtoBlob(editedImageData)\n            }\n\n            const newFile = blobToFileWithParams(\n                blob,\n                original,\n                resolvedImageEditor.output,\n            )\n\n            // Replace in the files map, revoking the old blob URL.\n            setSelectedFilesMap(prev =>\n                revokeAndReplace(prev, original.id, newFile),\n            )\n\n            resolvedImageEditor.onSave?.(newFile, original)\n\n            setEditingFile(null)\n            advanceEditorQueue()\n        },\n        [editingFile, resolvedImageEditor, advanceEditorQueue],\n    )\n\n    const replaceFile = useCallback(\n        (fileId: string, newFile: FileWithParams) => {\n            setSelectedFilesMap(prev => {\n                const next = new Map(prev)\n                next.set(fileId, newFile)\n                return next\n            })\n        },\n        [],\n    )\n\n    // Auto-open editor queue processing: when a queue is populated and no\n    // editor is currently open, open the next file.\n    useEffect(() => {\n        if (editingFile || editorQueue.length === 0) return\n        const [next, ...rest] = editorQueue\n        setEditorQueue(rest)\n        openImageEditor(next)\n    }, [editingFile, editorQueue, openImageEditor])\n\n    const onError = useCallback(\n        (message: string) => {\n            setUploadError(message)\n\n            if (errorHandler) errorHandler(message)\n        },\n        [errorHandler],\n    )\n\n    const onWarn = useCallback(\n        (message: string) => {\n            if (warningHandler) warningHandler(message)\n        },\n        [warningHandler],\n    )\n    function isFileWithParamsArray(\n        files: File[] | FileWithParams[],\n    ): files is FileWithParams[] {\n        return files.length > 0 && 'id' in files[0]\n    }\n    async function resetState() {\n        setIsAddingMore(false)\n        handleDone()\n    }\n    async function dynamicUpload(files: File[] | FileWithParams[]) {\n        const filesToUpload = isFileWithParamsArray(files)\n            ? files\n            : files.map(file => fileAppendParams(file))\n        return await proceedUpload(filesToUpload)\n    }\n    function dynamicallyReplaceFiles(files: File[] | FileWithParams[]) {\n        // Revoke old blob URLs to prevent memory leak\n        selectedFilesMap.forEach(file => revokeFileUrl(file))\n\n        const filesMap = new Map<string, FileWithParams>()\n        if (isFileWithParamsArray(files)) {\n            for (const f of files) {\n                filesMap.set(f.id, f)\n            }\n        } else {\n            for (const f of files) {\n                const fileWithParams = fileAppendParams(f)\n                filesMap.set(fileWithParams.id, fileWithParams)\n            }\n        }\n        setSelectedFilesMap(filesMap)\n    }\n    const handleSetSelectedFiles = (newFiles: File[]) => {\n        // Start from existing files to ensure appending behavior.\n        const newFilesMap = new Map(selectedFilesMap)\n        // Track existing URLs (when present) to avoid duplicates across drops.\n        const existingUrls = new Set(\n            Array.from(newFilesMap.values())\n                .map(v => (v as any).url)\n                .filter(Boolean),\n        ) as Set<string>\n\n        // Collect only the files that are actually accepted and added in this batch.\n        const addedThisBatch: FileWithParams[] = []\n\n        for (const file of newFiles) {\n            // Respect the limit strictly; stop when capacity is reached.\n            if (newFilesMap.size >= limit) {\n                onWarn(translations.allowedLimitSurpassed)\n                break\n            }\n\n            const fileWithParams = fileAppendParams(file)\n\n            if (!checkFileType(accept, file)) {\n                onError(\n                    t(translations.fileUnsupportedType, { name: file.name }),\n                )\n                onFileTypeMismatch(file, accept)\n                revokeFileUrl(fileWithParams)\n                continue\n            }\n\n            if (\n                maxFileSize?.size &&\n                maxFileSize?.unit &&\n                !checkFileSize(file, maxFileSize)\n            ) {\n                onError(\n                    t(translations.fileTooLargeName, {\n                        name: file.name,\n                        size: String(maxFileSize.size),\n                        unit: String(maxFileSize.unit),\n                    }),\n                )\n                revokeFileUrl(fileWithParams)\n                continue\n            }\n\n            if (newFilesMap.has(fileWithParams.id)) {\n                onWarn(\n                    t(translations.filePreviouslySelected, { name: file.name }),\n                )\n                revokeFileUrl(fileWithParams)\n                continue\n            }\n\n            const fileUrl = (file as any).url as string | undefined\n            if (fileUrl && existingUrls.has(fileUrl)) {\n                onWarn(\n                    t(translations.fileWithUrlPreviouslySelected, {\n                        url: fileUrl,\n                    }),\n                )\n                revokeFileUrl(fileWithParams)\n                continue\n            }\n\n            newFilesMap.set(fileWithParams.id, fileWithParams)\n            addedThisBatch.push(fileWithParams)\n            if (fileUrl) existingUrls.add(fileUrl)\n        }\n\n        // Apply state update once for better performance and atomicity.\n        setSelectedFilesMap(newFilesMap)\n\n        // Emit a single selection event for just-added files.\n        if (addedThisBatch.length) onFilesSelected(addedThisBatch)\n\n        // Auto-open image editor for newly added images if configured.\n        if (resolvedImageEditor.enabled && addedThisBatch.length) {\n            const newImages = addedThisBatch.filter(f =>\n                f.type.startsWith('image/'),\n            )\n\n            if (newImages.length > 0) {\n                if (\n                    resolvedImageEditor.autoOpen === 'single' &&\n                    newImages.length === 1\n                ) {\n                    openImageEditor(newImages[0])\n                } else if (resolvedImageEditor.autoOpen === 'always') {\n                    // Queue all: first one opens immediately, rest are queued.\n                    const [first, ...rest] = newImages\n                    openImageEditor(first)\n                    if (rest.length) {\n                        setEditorQueue(prev => [...prev, ...rest])\n                    }\n                }\n            }\n        }\n\n        setIsAddingMore(false)\n    }\n\n    const handleFileRemove = useCallback(\n        (fileId: string) => {\n            const file = selectedFilesMap.get(fileId)\n            if (!file) return\n\n            // Revoke blob URL to prevent memory leak\n            revokeFileUrl(file)\n\n            const selectedFilesMapCopy = new Map(selectedFilesMap)\n            selectedFilesMapCopy.delete(fileId)\n\n            setSelectedFilesMap(selectedFilesMapCopy)\n            onFileRemove(file)\n        },\n        [onFileRemove, selectedFilesMap],\n    )\n\n    const compressFiles = useCallback(\n        async (files: FileWithParams[]) => {\n            try {\n                return await Promise.all(\n                    files.map(async oldFile => {\n                        return await compressFile(oldFile)\n                    }),\n                )\n            } catch (error) {\n                files.forEach(file =>\n                    onError(\n                        t(translations.errorCompressingFile, {\n                            name: file.name,\n                        }),\n                    ),\n                )\n                throw error\n            }\n        },\n        [onError],\n    )\n\n    const handlePrepareFiles = useCallback(\n        async (files: FileWithParams[]) => {\n            // Pre-populate progress from existing multipart sessions\n            const progressMap = files.reduce((a, b) => {\n                let initialLoaded = 0\n                if (resumable?.mode === 'multipart') {\n                    const fp = fileFingerprint(b)\n                    const session = loadSession(fp)\n                    if (session?.uploadedBytes) {\n                        initialLoaded = session.uploadedBytes\n                    }\n                }\n                a[b.id] = {\n                    id: b.id,\n                    loaded: initialLoaded,\n                    total: b.size,\n                }\n                return a\n            }, {} as FilesProgressMap)\n            setFilesProgressMap(progressMap)\n\n            // Set total bytes for ETA calculation\n            const total = files.reduce((sum, f) => sum + f.size, 0)\n            setTotalBytes(total)\n            totalBytesRef.current = total\n            const initialUploaded = Object.values(progressMap).reduce(\n                (sum: number, fp: FileProgress) => sum + fp.loaded,\n                0,\n            )\n            setUploadedBytes(initialUploaded)\n            setUploadSpeed(0)\n            setUploadEta(0)\n            speedSamplesRef.current = []\n\n            return onPrepareFiles ? await onPrepareFiles(files) : files\n        },\n        [onPrepareFiles, resumable],\n    )\n    const proceedUpload = useCallback(\n        async (dynamicFiles: FileWithParams[] | undefined = undefined) => {\n            if (!selectedFilesMap.size && !dynamicFiles) return\n            setUploadStatus(UploadStatus.ONGOING)\n            setUploadError('')\n            const sendEvent = !dynamicFiles\n            const selectedFiles = dynamicFiles\n                ? dynamicFiles\n                : Array.from(selectedFilesMap.values())\n            try {\n                const compressedFiles = shouldCompress\n                    ? await compressFiles(selectedFiles)\n                    : selectedFiles\n                const processedFiles = await handlePrepareFiles(compressedFiles)\n                // Initialize SDK\n                const sdk = new ProviderSDK({\n                    provider,\n                    tokenEndpoint,\n                    constraints: {\n                        multiple,\n                        accept,\n                        maxFileSize:\n                            maxFileSize?.size && maxFileSize?.unit\n                                ? sizeToBytes(\n                                      maxFileSize.size,\n                                      maxFileSize.unit,\n                                  )\n                                : undefined,\n                    },\n                    customProps,\n                    enableAutoCorsConfig,\n                    resumable,\n                    translations: translations,\n                })\n\n                // Store SDK ref for pause/resume\n                sdkRef.current = sdk\n                speedSamplesRef.current = [{ time: Date.now(), bytes: 0 }]\n\n                // For multipart resumable uploads, filter out already-uploaded files on retry\n                const filesToUpload =\n                    resumable?.mode === 'multipart'\n                        ? processedFiles.filter(f => !f.key)\n                        : processedFiles\n\n                // Upload files with automatic retries if configured\n                const uploadOptions = {\n                    onFileUploadStart,\n                    onFileUploadProgress: (\n                        file: FileWithParams,\n                        progress: {\n                            loaded: number\n                            total: number\n                            percentage: number\n                        },\n                    ) => {\n                        // Skip visual updates while paused so the UI freezes immediately\n                        if (sdkRef.current?.isPaused) return\n\n                        setFilesProgressMap((prev: FilesProgressMap) => ({\n                            ...prev,\n                            [file.id]: {\n                                ...prev[file.id],\n                                loaded: progress.loaded,\n                            },\n                        }))\n\n                        // Update aggregate uploaded bytes for speed/ETA\n                        setFilesProgressMap((prev: FilesProgressMap) => {\n                            const totalLoaded = Object.values(prev).reduce(\n                                (sum: number, fp: FileProgress) =>\n                                    sum + fp.loaded,\n                                0,\n                            )\n                            setUploadedBytes(totalLoaded)\n\n                            // Rolling-average speed calculation (last 3 seconds)\n                            const now = Date.now()\n                            speedSamplesRef.current.push({\n                                time: now,\n                                bytes: totalLoaded,\n                            })\n                            // Keep only samples from last 3 seconds\n                            const cutoff = now - 3000\n                            speedSamplesRef.current =\n                                speedSamplesRef.current.filter(\n                                    (s: { time: number; bytes: number }) =>\n                                        s.time >= cutoff,\n                                )\n\n                            if (speedSamplesRef.current.length >= 2) {\n                                const oldest = speedSamplesRef.current[0]\n                                const newest =\n                                    speedSamplesRef.current[\n                                        speedSamplesRef.current.length - 1\n                                    ]\n                                const elapsed =\n                                    (newest.time - oldest.time) / 1000\n                                if (elapsed > 0) {\n                                    const speed =\n                                        (newest.bytes - oldest.bytes) / elapsed\n                                    setUploadSpeed(Math.max(0, speed))\n\n                                    const remaining =\n                                        totalBytesRef.current - totalLoaded\n                                    if (speed > 0) {\n                                        setUploadEta(\n                                            Math.ceil(remaining / speed),\n                                        )\n                                    }\n                                }\n                            }\n\n                            return prev\n                        })\n\n                        onFileUploadProgress(file, progress)\n                    },\n                    onFileUploadComplete,\n                    sendEvent,\n                    onError,\n                    onFilesUploadProgress: (completedFiles: number) =>\n                        onFilesUploadProgress(\n                            completedFiles,\n                            processedFiles.length,\n                        ),\n                }\n                const uploadResults = await Promise.all(\n                    filesToUpload.map(file =>\n                        maxRetries\n                            ? uploadWithRetry(\n                                  () => sdk.upload(file, uploadOptions),\n                                  maxRetries,\n                              )\n                            : sdk.upload(file, uploadOptions),\n                    ),\n                )\n                const finalFiles = uploadResults.map(result => result.file)\n                if (sendEvent) onFilesUploadComplete(finalFiles)\n\n                sdkRef.current = null\n                setUploadStatus(UploadStatus.SUCCESSFUL)\n                return finalFiles\n            } catch (error) {\n                onError((error as Error).message)\n                sdkRef.current = null\n                setUploadStatus(UploadStatus.FAILED)\n                // Preserve filesProgressMap so progress stays visible alongside the Retry button\n                return\n            }\n        },\n        [\n            selectedFilesMap,\n            shouldCompress,\n            compressFiles,\n            handlePrepareFiles,\n            provider,\n            tokenEndpoint,\n            multiple,\n            accept,\n            maxFileSize?.size,\n            maxFileSize?.unit,\n            customProps,\n            enableAutoCorsConfig,\n            resumable,\n            onFilesUploadComplete,\n            onFileUploadStart,\n            onFileUploadComplete,\n            onError,\n            onFileUploadProgress,\n            onFilesUploadProgress,\n            maxRetries,\n        ],\n    )\n    const handleCancel = useCallback(() => {\n        // Abort in-flight upload\n        sdkRef.current?.abort()\n\n        // Best-effort abort multipart uploads on the provider to avoid orphaned uploads\n        if (sdkRef.current && resumable?.mode === 'multipart') {\n            selectedFilesMap.forEach(file => {\n                void sdkRef.current?.abortMultipart(file)\n            })\n        }\n\n        sdkRef.current = null\n\n        // Revoke all blob URLs to prevent memory leak\n        selectedFilesMap.forEach(file => revokeFileUrl(file))\n\n        setUploadStatus(UploadStatus.PENDING)\n        setSelectedFilesMap(new Map())\n        setFilesProgressMap({})\n        setUploadSpeed(0)\n        setUploadEta(0)\n        setUploadedBytes(0)\n        setTotalBytes(0)\n    }, [resumable?.mode, selectedFilesMap])\n\n    const handlePause = useCallback(() => {\n        sdkRef.current?.pause()\n        setUploadStatus(UploadStatus.PAUSED)\n    }, [])\n\n    const handleResume = useCallback(() => {\n        sdkRef.current?.resume()\n        // Reset speed tracking on resume for accurate ETA\n        speedSamplesRef.current = [{ time: Date.now(), bytes: uploadedBytes }]\n        setUploadStatus(UploadStatus.ONGOING)\n    }, [uploadedBytes])\n\n    const handleDone = useCallback(() => {\n        onDoneClicked()\n        handleCancel()\n    }, [handleCancel, onDoneClicked])\n\n    return {\n        inputRef,\n        activeAdapter,\n        setActiveAdapter,\n        isAddingMore,\n        setIsAddingMore,\n        translations,\n        files: selectedFilesMap,\n        setFiles: handleSetSelectedFiles,\n        dynamicUpload,\n        resetState,\n        dynamicallyReplaceFiles,\n        handleDone,\n        handleCancel,\n        handlePause,\n        handleResume,\n        handleFileRemove,\n        editingFile,\n        openImageEditor,\n        closeImageEditor,\n        saveImageEdit,\n        replaceFile,\n        oneDriveConfigs: driveConfigs?.oneDrive,\n        googleDriveConfigs: driveConfigs?.googleDrive,\n        dropboxConfigs: driveConfigs?.dropbox,\n        upload: {\n            totalProgress,\n            filesProgressMap,\n            proceedUpload,\n            uploadStatus,\n            setUploadStatus,\n            uploadError,\n            uploadSpeed,\n            uploadEta,\n            uploadedBytes,\n            totalBytes,\n        },\n        props: {\n            mini,\n            dark,\n            maxRetries,\n            resumable,\n            onError,\n            onIntegrationClick,\n            onFileClick,\n            onFilesDragOver,\n            onFilesDragLeave,\n            onFilesDrop,\n            uploadAdapters,\n            accept,\n            maxFileSize,\n            limit,\n            isProcessing,\n            allowPreview,\n            showSelectFolderButton,\n            multiple,\n            icons: {\n                ContainerAddMoreIcon: icons.ContainerAddMoreIcon || TbPlus,\n                FileDeleteIcon: icons.FileDeleteIcon || TbTrash,\n                CameraCaptureIcon: icons.CameraCaptureIcon || TbCapture,\n                CameraRotateIcon: icons.CameraRotateIcon || TbCameraRotate,\n                CameraDeleteIcon: icons.CameraDeleteIcon || TbTrash,\n                LoaderIcon: icons.LoaderIcon || TbLoader,\n            },\n            classNames,\n            imageEditor: resolvedImageEditor,\n        },\n    }\n}\n","export default function checkFileType(accept: string, file: File) {\n    const fileType = file.type\n    // Return false for invalid inputs\n    if (!accept) return false\n    // Validate fileType has proper MIME format (type/subtype)\n    if (fileType) {\n        const [type, subtype] = fileType.split('/')\n        if (type && subtype) {\n            const acceptedTypes = accept.split(',').map(t => t.trim())\n            const isValidType =\n                acceptedTypes.includes('*') ||\n                acceptedTypes.some(item => {\n                    if (item.includes('/*')) {\n                        const [mainType] = item.split('/')\n                        return fileType.startsWith(mainType)\n                    }\n                    return item.toLowerCase() === fileType.toLowerCase()\n                })\n            if (isValidType) return true\n        }\n    }\n\n    const fileName = file.name ?? ''\n    if (!fileName) {\n        return false\n    }\n\n    const fileExt = fileName.split('.').pop()?.toLowerCase() || ''\n    if (fileExt) {\n        const acceptedTypes = accept.split(',').map(t => t.trim().toLowerCase())\n        const isValidExtension = acceptedTypes.some(ext => {\n            if (ext.startsWith('.')) {\n                return ext.slice(1) === fileExt\n            }\n            return false\n        })\n        if (isValidExtension) return true\n    }\n    return false\n}\n","import { UpupProvider } from '../../../shared/types'\n\nexport interface MultipartSession {\n    provider: UpupProvider\n    key: string\n    uploadId: string\n    partSize: number\n    updatedAt: number\n    /** Bytes uploaded so far (used for progress pre-population on resume) */\n    uploadedBytes?: number\n}\n\nconst STORAGE_PREFIX = 'upup_mp_'\nconst SESSION_TTL_MS = 24 * 60 * 60 * 1000 // 24 hours\n\n/**\n * Generate a deterministic fingerprint for a file to identify resumable sessions.\n */\nexport function fileFingerprint(file: File): string {\n    return `${file.name}:${file.size}:${file.lastModified}:${file.type}`\n}\n\nfunction storageKey(fingerprint: string): string {\n    return `${STORAGE_PREFIX}${fingerprint}`\n}\n\n/**\n * Save a multipart session to localStorage.\n */\nexport function saveSession(\n    fingerprint: string,\n    session: MultipartSession,\n): void {\n    try {\n        localStorage.setItem(storageKey(fingerprint), JSON.stringify(session))\n    } catch {\n        // localStorage may be unavailable; silently ignore\n    }\n}\n\n/**\n * Load a multipart session from localStorage, if it exists and is not expired.\n */\nexport function loadSession(fingerprint: string): MultipartSession | null {\n    try {\n        const raw = localStorage.getItem(storageKey(fingerprint))\n        if (!raw) return null\n\n        const session: MultipartSession = JSON.parse(raw)\n\n        // Expire stale sessions\n        if (Date.now() - session.updatedAt > SESSION_TTL_MS) {\n            removeSession(fingerprint)\n            return null\n        }\n\n        return session\n    } catch {\n        return null\n    }\n}\n\n/**\n * Update only the progress-related fields of an existing session.\n */\nexport function updateSessionProgress(\n    fingerprint: string,\n    uploadedBytes: number,\n): void {\n    try {\n        const raw = localStorage.getItem(storageKey(fingerprint))\n        if (!raw) return\n        const session: MultipartSession = JSON.parse(raw)\n        session.uploadedBytes = uploadedBytes\n        session.updatedAt = Date.now()\n        localStorage.setItem(storageKey(fingerprint), JSON.stringify(session))\n    } catch {\n        // silently ignore\n    }\n}\n\n/**\n * Remove a multipart session (on complete or abort).\n */\nexport function removeSession(fingerprint: string): void {\n    try {\n        localStorage.removeItem(storageKey(fingerprint))\n    } catch {\n        // silently ignore\n    }\n}\n\n/**\n * Clear all multipart sessions (e.g., on user cancel).\n */\nexport function clearAllSessions(): void {\n    try {\n        const keysToRemove: string[] = []\n        for (let i = 0; i < localStorage.length; i++) {\n            const key = localStorage.key(i)\n            if (key?.startsWith(STORAGE_PREFIX)) {\n                keysToRemove.push(key)\n            }\n        }\n        keysToRemove.forEach(k => localStorage.removeItem(k))\n    } catch {\n        // silently ignore\n    }\n}\n","import { en_US, mergeTranslations, t } from '../../../shared/i18n'\nimport type { Translations } from '../../../shared/i18n/types'\nimport {\n    FileWithParams,\n    MultipartCompleteResponse,\n    MultipartInitResponse,\n    MultipartListPartsResponse,\n    MultipartPart,\n    MultipartSignPartResponse,\n    PresignedUrlResponse,\n    ResumableUploadOptions,\n    UploadError,\n    UploadErrorType,\n    UpupProvider,\n    UpupUploaderProps,\n} from '../../../shared/types'\nimport { StorageSDK, UploadOptions, UploadResult } from '../../types/StorageSDK'\nimport {\n    fileFingerprint,\n    loadSession,\n    removeSession,\n    saveSession,\n    updateSessionProgress,\n} from '../resumable/multipartSessionStore'\n\ntype UploadConfig = Pick<\n    UpupUploaderProps,\n    'provider' | 'tokenEndpoint' | 'customProps'\n> & {\n    constraints?: {\n        multiple: boolean\n        accept: string\n        maxFileSize?: number\n    }\n    enableAutoCorsConfig: boolean\n    resumable?: ResumableUploadOptions\n    translations?: Partial<Translations>\n}\n\nexport class ProviderSDK implements StorageSDK {\n    private readonly config: UploadConfig\n    private readonly translations: Translations\n    private uploadCount = 0\n    private currentXhr: XMLHttpRequest | null = null\n    private _paused = false\n    private _pauseResolve: (() => void) | null = null\n    private _pausePromise: Promise<void> | null = null\n\n    constructor(config: UploadConfig) {\n        this.config = config\n        this.translations = mergeTranslations(en_US, config.translations)\n        this.validateConfig()\n        this.uploadCount = 0\n    }\n\n    /**\n     * Determine whether to use multipart upload.\n     * Multipart is used when resumable.mode === 'multipart' AND provider is not Azure.\n     */\n    private shouldUseMultipart(): boolean {\n        return (\n            this.config.resumable?.mode === 'multipart' &&\n            this.config.provider !== UpupProvider.Azure\n        )\n    }\n\n    async upload(\n        file: FileWithParams,\n        options = {} as UploadOptions,\n    ): Promise<UploadResult> {\n        try {\n            if (!this.config.constraints?.multiple && this.uploadCount > 0)\n                throw new UploadError(\n                    this.translations.multipleFilesNotAllowed,\n                    UploadErrorType.FILE_VALIDATION_ERROR,\n                )\n\n            options.onFileUploadStart?.(file)\n\n            if (this.shouldUseMultipart()) {\n                return await this.multipartUpload(file, options)\n            }\n            return await this.singleUpload(file, options)\n        } catch (error) {\n            throw this.handleError(error)\n        }\n    }\n\n    /**\n     * Abort any in-flight XHR request.\n     */\n    abort(): void {\n        if (this.currentXhr) {\n            this.currentXhr.abort()\n            this.currentXhr = null\n        }\n    }\n\n    /**\n     * Pause multipart upload — blocks between parts without aborting the current XHR.\n     */\n    pause(): void {\n        if (this._paused) return\n        this._paused = true\n        this._pausePromise = new Promise<void>(resolve => {\n            this._pauseResolve = resolve\n        })\n    }\n\n    /**\n     * Resume a paused multipart upload.\n     */\n    resume(): void {\n        if (!this._paused) return\n        this._paused = false\n        this._pauseResolve?.()\n        this._pauseResolve = null\n        this._pausePromise = null\n    }\n\n    get isPaused(): boolean {\n        return this._paused\n    }\n\n    /**\n     * Abort multipart upload on the server and clear session.\n     */\n    async abortMultipart(file: FileWithParams): Promise<void> {\n        const fingerprint = fileFingerprint(file)\n        const session = loadSession(fingerprint)\n        if (!session) return\n\n        try {\n            await this.tokenEndpointRequest({\n                action: 'multipart:abort',\n                provider: this.config.provider,\n                key: session.key,\n                uploadId: session.uploadId,\n            })\n        } catch {\n            // Best-effort abort\n        }\n        removeSession(fingerprint)\n    }\n\n    // ─── Single PUT upload (existing behavior) ───────────────────────\n\n    private async singleUpload(\n        file: FileWithParams,\n        options: UploadOptions,\n    ): Promise<UploadResult> {\n        // Get presigned URL from backend\n        const presignedData = await this.getPresignedUrl(file)\n\n        // Increment upload count\n        this.uploadCount++\n\n        // Upload using presigned URL\n        const uploadResponse = await this.uploadWithProgress(\n            presignedData.uploadUrl,\n            file,\n            options,\n        )\n\n        if (!uploadResponse.ok)\n            throw new Error(`status ${uploadResponse.status}`)\n        if (options.sendEvent) {\n            options.onFileUploadComplete?.(file, presignedData.key)\n        }\n        file.key = presignedData.key\n        if (file.thumbnail?.file) {\n            const thumbnailPresignedData = await this.getPresignedUrl(\n                file.thumbnail.file,\n                true,\n            )\n            const thumbnailUploadResponse = await this.uploadWithProgress(\n                thumbnailPresignedData.uploadUrl,\n                file.thumbnail.file,\n                options,\n                true,\n            )\n            if (!thumbnailUploadResponse.ok) {\n                throw new Error(`status ${thumbnailUploadResponse.status}`)\n            }\n            file.thumbnail.key = thumbnailPresignedData.key\n        }\n        return {\n            key: presignedData.key,\n            file,\n            httpStatus: uploadResponse.status,\n        }\n    }\n\n    // ─── Multipart resumable upload ──────────────────────────────────\n\n    private async multipartUpload(\n        file: FileWithParams,\n        options: UploadOptions,\n    ): Promise<UploadResult> {\n        const fingerprint = fileFingerprint(file)\n        const persist =\n            this.config.resumable?.mode === 'multipart' &&\n            (this.config.resumable.persist ?? true)\n\n        let key: string\n        let uploadId: string\n        let partSize: number\n        let existingParts: MultipartPart[] = []\n        let needsInit = true\n\n        // Step 1: Check for existing session (resume) or init new\n        const existingSession = persist ? loadSession(fingerprint) : null\n\n        if (existingSession) {\n            key = existingSession.key\n            uploadId = existingSession.uploadId\n            partSize = existingSession.partSize\n\n            // Get already-uploaded parts from S3 — fall back to fresh init on stale session\n            try {\n                const listResponse =\n                    await this.tokenEndpointRequest<MultipartListPartsResponse>(\n                        {\n                            action: 'multipart:listParts',\n                            provider: this.config.provider,\n                            key,\n                            uploadId,\n                        },\n                    )\n                existingParts = listResponse.parts\n                needsInit = false\n            } catch {\n                // Session is stale (upload ID expired / deleted) — remove and start fresh\n                console.warn(\n                    'Existing multipart session is stale, starting fresh upload',\n                )\n                removeSession(fingerprint)\n            }\n        }\n\n        if (needsInit) {\n            const chunkSizeBytes =\n                this.config.resumable?.mode === 'multipart'\n                    ? this.config.resumable.chunkSizeBytes\n                    : undefined\n\n            const initResponse =\n                await this.tokenEndpointRequest<MultipartInitResponse>({\n                    action: 'multipart:init',\n                    name: file.name,\n                    type: file.type,\n                    size: file.size,\n                    provider: this.config.provider,\n                    customProps: this.config.customProps,\n                    enableAutoCorsConfig: this.config.enableAutoCorsConfig,\n                    ...this.config.constraints,\n                    chunkSizeBytes,\n                })\n\n            key = initResponse.key\n            uploadId = initResponse.uploadId\n            partSize = initResponse.partSize\n\n            if (persist) {\n                saveSession(fingerprint, {\n                    provider: this.config.provider,\n                    key,\n                    uploadId,\n                    partSize,\n                    updatedAt: Date.now(),\n                    uploadedBytes: 0,\n                })\n            }\n        }\n\n        // Step 2: Compute parts and upload missing ones\n        const totalParts = Math.ceil(file.size / partSize)\n        const uploadedPartNumbers = new Set(\n            existingParts.map(p => p.partNumber),\n        )\n        const uploadedBytes = existingParts.reduce((sum, p) => {\n            const start = (p.partNumber - 1) * partSize\n            const end = Math.min(start + partSize, file.size)\n            return sum + (end - start)\n        }, 0)\n\n        let bytesUploaded = uploadedBytes\n\n        this.uploadCount++\n\n        // Fire initial progress for resumed uploads so UI immediately shows the resume point\n        if (uploadedBytes > 0 && options.onFileUploadProgress) {\n            options.onFileUploadProgress(file, {\n                loaded: uploadedBytes,\n                total: file.size,\n                percentage: (uploadedBytes / file.size) * 100,\n            })\n        }\n\n        for (let partNumber = 1; partNumber <= totalParts; partNumber++) {\n            if (uploadedPartNumbers.has(partNumber)) continue\n\n            // If paused, wait until resumed\n            if (this._paused && this._pausePromise) {\n                await this._pausePromise\n            }\n\n            const start = (partNumber - 1) * partSize\n            const end = Math.min(start + partSize, file.size)\n            const partBlob = file.slice(start, end)\n\n            // Get presigned URL for this part\n            const signResponse =\n                await this.tokenEndpointRequest<MultipartSignPartResponse>({\n                    action: 'multipart:signPart',\n                    provider: this.config.provider,\n                    key,\n                    uploadId,\n                    partNumber,\n                    contentLength: partBlob.size,\n                })\n\n            // Upload part with progress tracking\n            const partResponse = await this.uploadPartWithProgress(\n                signResponse.uploadUrl,\n                partBlob,\n                file,\n                options,\n                bytesUploaded,\n                file.size,\n            )\n\n            if (!partResponse.ok) {\n                throw new Error(\n                    `Part ${partNumber} upload failed with status ${partResponse.status}`,\n                )\n            }\n\n            bytesUploaded += partBlob.size\n\n            // Update session with progress so resume after refresh starts from here\n            if (persist) {\n                updateSessionProgress(fingerprint, bytesUploaded)\n            }\n        }\n\n        // Step 3: List parts (canonical ETags from S3) and complete\n        const finalListResponse =\n            await this.tokenEndpointRequest<MultipartListPartsResponse>({\n                action: 'multipart:listParts',\n                provider: this.config.provider,\n                key,\n                uploadId,\n            })\n\n        const completeResponse =\n            await this.tokenEndpointRequest<MultipartCompleteResponse>({\n                action: 'multipart:complete',\n                provider: this.config.provider,\n                key,\n                uploadId,\n                parts: finalListResponse.parts,\n            })\n\n        // Step 4: Cleanup session\n        removeSession(fingerprint)\n\n        if (options.sendEvent) {\n            options.onFileUploadComplete?.(file, completeResponse.key)\n        }\n\n        file.key = completeResponse.key\n\n        // Thumbnails use single PUT (no multipart)\n        if (file.thumbnail?.file) {\n            const thumbnailPresignedData = await this.getPresignedUrl(\n                file.thumbnail.file,\n                true,\n            )\n            const thumbnailUploadResponse = await this.uploadWithProgress(\n                thumbnailPresignedData.uploadUrl,\n                file.thumbnail.file,\n                options,\n                true,\n            )\n            if (!thumbnailUploadResponse.ok) {\n                throw new Error(`status ${thumbnailUploadResponse.status}`)\n            }\n            file.thumbnail.key = thumbnailPresignedData.key\n        }\n\n        return {\n            key: completeResponse.key,\n            file,\n            httpStatus: 200,\n        }\n    }\n\n    /**\n     * Upload a single part via XHR PUT, tracking progress relative to the full file.\n     */\n    private uploadPartWithProgress(\n        url: string,\n        partBlob: Blob,\n        file: FileWithParams,\n        { onFileUploadProgress, onFilesUploadProgress }: UploadOptions,\n        previouslyUploadedBytes: number,\n        totalFileSize: number,\n    ): Promise<Response> {\n        return new Promise((resolve, reject) => {\n            const xhr = new XMLHttpRequest()\n            this.currentXhr = xhr\n\n            xhr.upload.addEventListener('progress', event => {\n                if (event.lengthComputable && onFileUploadProgress) {\n                    const loaded = previouslyUploadedBytes + event.loaded\n                    onFileUploadProgress(file, {\n                        loaded,\n                        total: totalFileSize,\n                        percentage: (loaded / totalFileSize) * 100,\n                    })\n                }\n                if (event.lengthComputable && onFilesUploadProgress) {\n                    onFilesUploadProgress(this.uploadCount)\n                }\n            })\n\n            xhr.addEventListener('load', () => {\n                this.currentXhr = null\n                const isValidStatus = xhr.status >= 200 && xhr.status < 300\n                if (isValidStatus) {\n                    resolve(\n                        new Response(xhr.response, {\n                            status: xhr.status,\n                            headers: new Headers({\n                                ETag: xhr.getResponseHeader('ETag') ?? '',\n                            }),\n                        }),\n                    )\n                } else {\n                    reject(\n                        new Error(\n                            `Status: ${xhr.status} (${xhr.statusText}). Details: ${xhr.responseText}`,\n                        ),\n                    )\n                }\n            })\n\n            xhr.addEventListener('error', () => {\n                this.currentXhr = null\n                reject(\n                    new Error(\n                        `Network error during part upload - Status: ${xhr.status} (${xhr.statusText})`,\n                    ),\n                )\n            })\n\n            xhr.open('PUT', url)\n            xhr.send(partBlob)\n        })\n    }\n\n    // ─── Common helpers ──────────────────────────────────────────────\n\n    /**\n     * Generic request to tokenEndpoint with an action field.\n     */\n    private async tokenEndpointRequest<T>(\n        body: Record<string, unknown>,\n    ): Promise<T> {\n        const response = await fetch(this.config.tokenEndpoint, {\n            method: 'POST',\n            headers: { 'Content-Type': 'application/json' },\n            body: JSON.stringify(body),\n        })\n\n        if (!response.ok) {\n            const errorData = await response.json()\n            throw new Error(\n                errorData.details || `Token endpoint error: ${response.status}`,\n            )\n        }\n\n        return response.json()\n    }\n\n    private async getPresignedUrl(\n        file: FileWithParams | File,\n        isThumbnail?: boolean,\n    ): Promise<PresignedUrlResponse> {\n        const requestBody = {\n            name: file.name,\n            type: file.type,\n            size: file.size,\n            isThumbnail: isThumbnail,\n            provider: this.config.provider,\n            customProps: this.config.customProps,\n            enableAutoCorsConfig: this.config.enableAutoCorsConfig,\n            ...this.config.constraints,\n        }\n\n        const response = await fetch(this.config.tokenEndpoint, {\n            method: 'POST',\n            headers: { 'Content-Type': 'application/json' },\n            body: JSON.stringify(requestBody),\n        })\n\n        if (!response.ok) {\n            const errorData = await response.json()\n            throw new UploadError(\n                errorData.details || this.translations.failedToGetUploadUrl,\n                UploadErrorType.PRESIGNED_URL_ERROR,\n            )\n        }\n\n        const data = await response.json()\n\n        return data\n    }\n\n    private async uploadWithProgress(\n        url: string,\n        file: FileWithParams | File,\n        { onFileUploadProgress, onFilesUploadProgress }: UploadOptions,\n        isThumbnail?: boolean,\n    ): Promise<Response> {\n        return new Promise((resolve, reject) => {\n            const xhr = new XMLHttpRequest()\n\n            xhr.upload.addEventListener('progress', event => {\n                if (\n                    event.lengthComputable &&\n                    onFileUploadProgress &&\n                    !isThumbnail\n                ) {\n                    onFileUploadProgress(file as FileWithParams, {\n                        loaded: event.loaded,\n                        total: event.total,\n                        percentage: (event.loaded / event.total) * 100,\n                    })\n                }\n                if (\n                    event.lengthComputable &&\n                    onFilesUploadProgress &&\n                    !isThumbnail\n                ) {\n                    onFilesUploadProgress(this.uploadCount)\n                }\n            })\n\n            xhr.addEventListener('load', () => {\n                const isValidStatus = xhr.status >= 200 && xhr.status < 300\n\n                if (isValidStatus) {\n                    resolve(\n                        new Response(xhr.response, {\n                            status: xhr.status,\n                            headers:\n                                this.config.provider !== UpupProvider.Azure\n                                    ? new Headers({\n                                          ETag:\n                                              xhr.getResponseHeader('ETag') ??\n                                              '',\n                                      })\n                                    : undefined,\n                        }),\n                    )\n                } else {\n                    reject(\n                        new UploadError(\n                            t(this.translations.statusError, {\n                                status: String(xhr.status),\n                                statusText: xhr.statusText ?? '',\n                                details: xhr.responseText ?? '',\n                            }),\n                            UploadErrorType.UNKNOWN_UPLOAD_ERROR,\n                        ),\n                    )\n                }\n            })\n\n            xhr.addEventListener('error', () =>\n                reject(\n                    new UploadError(\n                        t(this.translations.networkErrorDuringUpload, {\n                            status: String(xhr.status),\n                            statusText: xhr.statusText ?? '',\n                        }),\n                        UploadErrorType.UNKNOWN_UPLOAD_ERROR,\n                    ),\n                ),\n            )\n\n            xhr.open('PUT', url)\n            if (this.config.provider === UpupProvider.Azure)\n                xhr.setRequestHeader('x-ms-blob-type', 'BlockBlob')\n            xhr.send(file)\n        })\n    }\n\n    validateConfig(): boolean {\n        const required = ['tokenEndpoint', 'provider'] as const\n        const missing = required.filter(key => !this.config[key])\n\n        // Validate required fields\n        if (missing.length > 0) {\n            throw new UploadError(\n                t(this.translations.missingRequiredConfiguration, {\n                    missing: missing.join(', '),\n                }),\n                UploadErrorType.FILE_VALIDATION_ERROR,\n            )\n        }\n\n        // Validate provider enum\n        if (!Object.values(UpupProvider).includes(this.config.provider)) {\n            throw new UploadError(\n                t(this.translations.invalidProvider, {\n                    provider: String(this.config.provider),\n                    validOptions: Object.values(UpupProvider).join(', '),\n                }),\n                UploadErrorType.CORS_CONFIG_ERROR,\n            )\n        }\n\n        // Validate tokenEndpoint format\n        try {\n            new URL(this.config.tokenEndpoint)\n        } catch (e) {\n            throw new UploadError(\n                t(this.translations.invalidTokenEndpoint, {\n                    tokenEndpoint: String(this.config.tokenEndpoint),\n                    error: String(e),\n                }),\n                UploadErrorType.CORS_CONFIG_ERROR,\n            )\n        }\n\n        // Validate resumable config\n        if (this.config.resumable?.mode === 'tus') {\n            throw new UploadError(\n                'Tus resumable uploads are not yet supported. Use mode: \"multipart\".',\n                UploadErrorType.FILE_VALIDATION_ERROR,\n            )\n        }\n\n        // Validate constraints if present\n        if (this.config.constraints) {\n            const { maxFileSize, accept } = this.config.constraints\n\n            if (maxFileSize !== undefined && maxFileSize <= 0) {\n                throw new UploadError(\n                    this.translations.maxFileSizeMustBeGreater,\n                    UploadErrorType.FILE_VALIDATION_ERROR,\n                )\n            }\n\n            if (\n                accept &&\n                !/^(\\*\\/\\*|\\*|[\\w-]+\\/(?:[\\w+.-]+|\\*)|\\.[\\w+.-]+)(,\\s*(\\*\\/\\*|\\*|[\\w-]+\\/(?:[\\w+.-]+|\\*)|\\.[\\w+.-]+))*$/.test(\n                    accept,\n                )\n            ) {\n                throw new UploadError(\n                    t(this.translations.invalidAcceptFormat, {\n                        accept: String(accept),\n                    }),\n                    UploadErrorType.FILE_VALIDATION_ERROR,\n                )\n            }\n        }\n\n        return true\n    }\n\n    private handleError(error: unknown): never {\n        // If it's already a structured UploadError, rethrow\n        if (error instanceof UploadError) throw error\n\n        // If it's an error from the backend with a specific error code\n        if (error instanceof Error && 'code' in error) {\n            const errorCode = (error as any).code\n            switch (errorCode) {\n                // Permission and Authentication Errors\n                case 'UNAUTHORIZED':\n                case 'FORBIDDEN':\n                case 'AUTHENTICATION_FAILED':\n                    throw new UploadError(\n                        this.translations.unauthorizedAccess,\n                        UploadErrorType.PERMISSION_ERROR,\n                    )\n\n                // URL and Credential Related Errors\n                case 'URL_EXPIRED':\n                case 'PRESIGNED_URL_INVALID':\n                    throw new UploadError(\n                        this.translations.presignedUrlInvalid,\n                        UploadErrorType.EXPIRED_URL,\n                        true,\n                    )\n\n                case 'TEMPORARY_CREDENTIALS_INVALID':\n                    throw new UploadError(\n                        this.translations.temporaryCredentialsInvalid,\n                        UploadErrorType.TEMPORARY_CREDENTIALS_ERROR,\n                        true,\n                    )\n\n                // CORS and Configuration Errors\n                case 'CORS_MISCONFIGURED':\n                case 'ORIGIN_NOT_ALLOWED':\n                    throw new UploadError(\n                        this.translations.corsMisconfigured,\n                        UploadErrorType.CORS_CONFIG_ERROR,\n                    )\n\n                // File Validation Errors\n                case 'FILE_TOO_LARGE':\n                    throw new UploadError(\n                        this.translations.fileTooLarge,\n                        UploadErrorType.FILE_VALIDATION_ERROR,\n                    )\n\n                case 'INVALID_FILE_TYPE':\n                    throw new UploadError(\n                        this.translations.invalidFileType,\n                        UploadErrorType.FILE_VALIDATION_ERROR,\n                    )\n\n                // Network and Infrastructure Errors\n                case 'NETWORK_ERROR':\n                case 'CONNECTION_TIMEOUT':\n                    throw new UploadError(\n                        this.translations.networkErrorDuringUpload,\n                        UploadErrorType.UNKNOWN_UPLOAD_ERROR,\n                        true,\n                    )\n\n                case 'STORAGE_QUOTA_EXCEEDED':\n                    throw new UploadError(\n                        this.translations.storageQuotaExceeded,\n                        UploadErrorType.PERMISSION_ERROR,\n                    )\n\n                case 'SIGNED_URL_GENERATION_FAILED':\n                    throw new UploadError(\n                        this.translations.signedUrlGenerationFailed,\n                        UploadErrorType.SIGNED_URL_ERROR,\n                        true,\n                    )\n\n                // Catch-all for any unhandled specific error codes\n                default:\n                    throw new UploadError(\n                        t(this.translations.uploadFailedWithCode, {\n                            code: String(errorCode),\n                        }),\n                        UploadErrorType.UNKNOWN_UPLOAD_ERROR,\n                        true,\n                    )\n            }\n        }\n\n        // Fallback for errors without specific codes\n        throw new UploadError(\n            t(this.translations.uploadFailed, {\n                message: (error as Error).message,\n            }),\n            UploadErrorType.UNKNOWN_UPLOAD_ERROR,\n            true,\n        )\n    }\n}\n","import { IRootContext, UploadStatus } from '../context/RootContext'\n\nexport default function useUpload({\n    upload,\n    files,\n    setFiles,\n    dynamicallyReplaceFiles,\n    dynamicUpload,\n    resetState,\n}: Pick<\n    IRootContext,\n    | 'upload'\n    | 'files'\n    | 'setFiles'\n    | 'dynamicallyReplaceFiles'\n    | 'resetState'\n    | 'dynamicUpload'\n>) {\n    const { proceedUpload, uploadStatus, uploadError, totalProgress } =\n        upload || {}\n\n    return {\n        upload: proceedUpload,\n        loading: uploadStatus === UploadStatus.ONGOING,\n        error: uploadError,\n        progress: totalProgress,\n        files: Array.from(files.values()).map(file => {\n            return file\n        }),\n        setFiles,\n        dynamicallyReplaceFiles,\n        dynamicUpload,\n        resetState,\n    }\n}\n"],"mappings":"AAEA,OAAOA,GAAS,cAAAC,GAAY,uBAAAC,OAA2B,QACvD,OAAS,YAAAC,OAAgB,iBCHlB,IAAMC,GACT,i9/BACSC,GACT,igzHACSC,GACT,yoLACSC,GACT,y1HCLG,IAAMC,GAAsB,CAE/B,OAAQ,SACR,KAAM,OACN,QAAS,aAGT,SAAU,YACV,YAAa,eACb,SAAU,WACV,QAAS,UACT,KAAM,OACN,OAAQ,SAGR,WAAY,oBACZ,YAAa,qBACb,YAAa,eACb,GAAI,KACJ,cAAe,kBACf,uBAAwB,wCACxB,yBAA0B,0CAG1B,iBACI,oEACJ,QAAS,WAGT,eAAgB,mBAChB,gBAAiB,oBACjB,kBAAmB,0BACnB,oBAAqB,2BACrB,QAAS,WAGT,gBAAiB,wBACjB,kBAAmB,yBAGnB,WAAY,cACZ,eAAgB,mBAChB,UAAW,SACX,MAAO,QACP,GAAI,KACJ,GAAI,KACJ,GAAI,KACJ,GAAI,KAGJ,aAAc,qBAGd,qBAAsB,0BACtB,iBAAkB,qBAClB,aAAc,qBACd,eAAgB,sBAGhB,OAAQ,UACR,OAAQ,SAGR,aAAc,iBACd,MAAO,QAGP,QAAS,UACT,eAAgB,qBAChB,SAAU,YAGV,MAAO,QACP,KAAM,OAGN,UAAW,aAGX,wBAAyB,wCACzB,qBAAsB,2BACtB,YAAa,4DACb,yBACI,oEACJ,6BAA8B,8CAC9B,gBACI,kEACJ,qBACI,yDACJ,yBAA0B,qCAC1B,oBACI,sFAEJ,mBAAoB,kCACpB,oBAAqB,0CACrB,4BAA6B,4CAC7B,kBAAmB,0CACnB,aAAc,kCACd,gBAAiB,2BACjB,qBAAsB,kCACtB,0BAA2B,uCAC3B,qBAAsB,0CACtB,aAAc,6BAGd,sBACI,wEACJ,0BACI,6JACJ,4BAA6B,kCAG7B,sBAAuB,oCACvB,oBAAqB,oCACrB,iBAAkB,6CAClB,uBAAwB,wCACxB,8BACI,6DACJ,qBAAsB,6BAGtB,iBAAkB,2BAClB,aAAc,gBACd,uBAAwB,2BACxB,kBAAmB,gCACnB,oBAAqB,qBACrB,qBAAsB,sCACtB,qBAAsB,sCACtB,0BAA2B,+BAC3B,qBAAsB,gDAGtB,6BACI,+CACJ,yBAA0B,0CAC1B,iCACI,gFACJ,aAAc,8BACd,mBAAoB,qCACpB,cAAe,8BACnB,ECrIO,SAASC,EACZC,EACAC,EACM,CACN,OAAKA,EACED,EAAS,QAAQ,iBAAkB,CAACE,EAAGC,IAAa,CAd/D,IAAAC,EAeQ,eAAOA,EAAAH,EAAOE,CAAG,IAAV,KAAAC,EAAe,KAAKD,CAAG,IAAI,EACtC,EAHoBH,CAIxB,CAYO,SAASK,GACZC,EACAC,EACAC,EACM,CAjCV,IAAAJ,EAAAK,EAmCI,IAAMN,EAAM,GAAGI,CAAO,GADPC,IAAU,EAAI,OAAS,QACP,GAC/B,OACIC,GAAAL,EAAAE,EAAaH,CAAG,IAAhB,KAAAC,EAAqBE,EAAaC,CAA6B,IAA/D,KAAAE,EAAoE,EAE5E,CAMO,SAASC,GACZC,EACAC,EACY,CACZ,OAAKA,EACE,CAAE,GAAGD,EAAM,GAAGC,CAAU,EADRD,CAE3B,CCnDA,OAAOE,OAAW,QAClB,OAAS,YAAAC,OAAgB,iBAEV,SAARC,IAAqC,CACxC,OACIF,GAAA,cAACC,GAAA,CAAS,UAAU,sDAAsD,CAElF,CCPA,OAAOE,IAEH,QAAAC,GACA,eAAAC,GACA,aAAAC,GACA,WAAAC,GACA,UAAAC,GACA,YAAAC,OACG,QCRP,OACI,iBAAAC,GAIA,cAAAC,OACG,QAsGP,IAAMC,GAAcC,GAA4B,CAC5C,MAAO,CAAC,EACR,MAAO,IAAI,GACf,CAAiB,EAEV,SAASC,GAAiB,CAE7B,OADqBC,GAAWH,EAAW,CAE/C,CAEA,IAAOI,GAAQJ,GCtHf,OAAOK,OAAU,OCAV,SAASC,GAAiBC,EAAqB,CAClD,OAAO,KACH,mBAAmBA,CAAG,EAAE,QAAQ,kBAAmB,CAACC,EAAGC,IACnD,OAAO,aAAa,SAASA,EAAI,EAAE,CAAC,CACxC,CACJ,CACJ,CDYO,IAAMC,GAAc,CACvBC,EACAC,EAAoE,MACnE,CAED,IAAMC,EADQ,CAAC,IAAK,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,IAAI,EAClD,QAAQD,CAAI,EAC5B,OAAOD,EAAO,KAAK,IAAI,KAAME,CAAC,CAClC,EAMO,SAASC,GACZC,EACAC,EACF,CACE,IAAMC,EAAWP,GAAYM,EAAa,KAAMA,EAAa,IAAI,EACjE,OAAID,EAAK,MAAQE,CAErB,CAEO,IAAMC,GAAoBH,GAAe,CAC5C,IAAMI,EACDJ,EAAa,cACbA,EAAa,oBACdA,EAAK,KACT,cAAO,OAAOA,EAAM,CAChB,GAAKA,EAAa,IAAMK,GAAiBD,CAAG,EAC5C,IAAMJ,EAAa,KAAO,IAAI,gBAAgBA,CAAI,CACtD,CAAC,EAEMA,CACX,EAMaM,GAAiBN,GAAyB,CAzDvD,IAAAO,GA0DQA,EAAAP,EAAK,MAAL,MAAAO,EAAU,WAAW,UACrB,IAAI,gBAAgBP,EAAK,GAAG,CAEpC,EAEA,eAAsBQ,GAAaC,EAAyB,CACxD,IAAMC,EAAS,MAAMD,EAAQ,YAAY,EAEnCE,EAAa,IAAI,KAAK,CAACC,GAAK,KAAKF,CAAM,CAAC,EAAGD,EAAQ,KAAO,MAAO,CACnE,KAAM,2BACN,aAAcA,EAAQ,YAC1B,CAAC,EACKI,EAAoBV,GAAiBQ,CAAU,EACrD,OAAAE,EAAkB,GAAKJ,EAAQ,GAC/BI,EAAkB,UAAYJ,EAAQ,UACtCI,EAAkB,SAAWJ,EAAQ,SACrCI,EAAkB,IAAMJ,EAAQ,IAGhCH,GAAcG,CAAO,EAEdI,CACX,CAEO,SAASC,GAKZC,EACAC,EACAC,EAII,CAAC,EACF,CACH,GAAM,CACF,cAAAC,EAAgB,GAChB,WAAAC,EAAa,GACb,WAAAC,EAAa,GACjB,EAAIH,EAEJ,GAAI,CAACD,EAAY,OAAOD,GAAA,YAAAA,EAAO,MAAM,EAAGK,GAExC,IAAIC,EAAeL,EACfM,EAEJ,OAAKJ,EAIDI,EAAYP,EAAM,IAAIf,GAAQA,EAAK,IAAI,GAHvCqB,EAAeL,EAAW,YAAY,EACtCM,EAAYP,EAAM,IAAIf,GAAQA,EAAK,KAAK,YAAY,CAAC,GAKlDe,EACF,OAAO,CAACQ,EAAOC,IAELL,EACDG,EAAUE,CAAK,IAAMH,EACrBC,EAAUE,CAAK,EAAE,SAASH,CAAY,CAC/C,EACA,MAAM,EAAGD,CAAU,CAC5B,CAEO,SAASK,GAAeC,EAAkB,CAC7C,OAAOA,EAAS,WAAW,QAAQ,CACvC,CAOO,IAAMC,GAAwB,IAAM,KAM9BC,GAA+B,IAKrC,SAASC,GAAcH,EAAkBI,EAA2B,CACvE,GAAI,CAACJ,EAAU,MAAO,GACtB,GAAIA,EAAS,WAAW,OAAO,EAAG,MAAO,GACzC,IAAMK,EAAQD,EAAS,YAAY,EACnC,OACIC,EAAM,SAAS,MAAM,GACrBA,EAAM,SAAS,KAAK,GACpBA,EAAM,SAAS,OAAO,GACtBA,EAAM,SAAS,MAAM,GACrBA,EAAM,SAAS,MAAM,GACrBA,EAAM,SAAS,KAAK,GACpBA,EAAM,SAAS,KAAK,GACpBA,EAAM,SAAS,MAAM,GACrBA,EAAM,SAAS,OAAO,CAE9B,CAKO,SAASC,GACZN,EACAI,EACAG,EACO,CACP,OAAKJ,GAAcH,EAAUI,CAAQ,EACjCG,IAAa,OAAkB,GAC5BA,GAAYN,GAF4B,EAGnD,CAEO,SAASO,GAAiBR,EAAkBI,EAAkB,CA7KrE,IAAAvB,EAAA4B,EA8KI,GAAI,CAACT,EACD,QAAOnB,EAAAuB,EAAS,MAAM,GAAG,EAAE,IAAI,IAAxB,YAAAvB,EAA2B,gBAAiB,GAEvD,IAAM6B,EAAYV,EAAS,MAAM,GAAG,EAC9BW,EAAYP,EAAS,MAAM,GAAG,EAC9BQ,IAAeH,EAAAE,EAAUA,EAAU,OAAS,CAAC,IAA9B,YAAAF,EAAiC,gBAAiB,GAIvE,MAHI,CAACC,EAAU,CAAC,GAGZA,EAAU,CAAC,EAAE,SAAS,GAAG,EAClBE,EAEJF,EAAU,CAAC,EAAE,YAAY,CACpC,CAEO,SAASG,GAASC,EAAa,CAmBlC,MAlByB,CACrB,MACA,MACA,QACA,MACA,MACA,MACA,KACA,KACA,MACA,MACA,MACA,MACA,MACA,OACA,MACA,IACJ,EACwB,SAASA,EAAI,YAAY,CAAC,CACtD,CEnMO,SAASC,GAAcC,EAAuB,CAdrD,IAAAC,EAAAC,EAeI,GAAM,CAACC,EAAQC,CAAU,EAAIJ,EAAQ,MAAM,GAAG,EACxCK,GAAOH,GAAAD,EAAAE,EAAO,MAAM,SAAS,IAAtB,YAAAF,EAA0B,KAA1B,KAAAC,EAAgC,2BACvCI,EAAS,KAAKF,CAAU,EACxBG,EAAQ,IAAI,WAAWD,EAAO,MAAM,EAC1C,QAASE,EAAI,EAAGA,EAAIF,EAAO,OAAQE,IAC/BD,EAAMC,CAAC,EAAIF,EAAO,WAAWE,CAAC,EAElC,OAAO,IAAI,KAAK,CAACD,CAAK,EAAG,CAAE,KAAMF,CAAK,CAAC,CAC3C,CAWO,SAASI,GACZC,EACAC,EACAC,EACc,CACd,IAAMC,EAAWD,GAAA,MAAAA,EAAQ,SACnBA,EAAO,SAASD,CAAQ,EACxBA,EAAS,KAETG,EAAO,IAAI,KAAK,CAACJ,CAAI,EAAGG,EAAU,CACpC,KAAMH,EAAK,MAAQC,EAAS,KAC5B,aAAc,KAAK,IAAI,CAC3B,CAAC,EAGKI,EAAiBD,EACvB,OAAAC,EAAe,GAAKJ,EAAS,GAC7BI,EAAe,IAAM,IAAI,gBAAgBD,CAAI,EAC7CC,EAAe,IAAMJ,EAAS,IAC9BI,EAAe,SAAWJ,EAAS,SACnCI,EAAe,UAAYJ,EAAS,UAE7BI,CACX,CAWO,SAASC,GACZC,EACAC,EACAC,EAC2B,CAC3B,IAAMC,EAAUH,EAAI,IAAIC,CAAM,EAC1BE,GACAC,GAAcD,CAAO,EAGzB,IAAME,EAAO,IAAI,IAAIL,CAAG,EAExB,OAAAK,EAAK,IAAIJ,EAAQC,CAAO,EACjBG,CACX,CAOO,SAASC,GAAkBC,EAA+B,CAC7D,OAAOA,EACD,CACI,QAAS,CACL,eAAgB,UAChB,aAAc,UACd,oBAAqB,UACrB,eAAgB,UAChB,WAAY,UACZ,YAAa,UACb,iBAAkB,UAClB,uBAAwB,UACxB,wBAAyB,UACzB,mBAAoB,2BACpB,mBAAoB,UACpB,eAAgB,UAChB,gBAAiB,UACjB,kBAAmB,UACnB,oBAAqB,UACrB,oBAAqB,UACrB,kBAAmB,UACnB,iBAAkB,UAClB,mBAAoB,UACpB,iBAAkB,UAClB,eAAgB,qBAChB,QAAS,UACT,cAAe,UACf,gBAAiB,UACjB,qBAAsB,UACtB,uBAAwB,UACxB,mBAAoB,UACpB,qBAAsB,UACtB,oBAAqB,UACrB,iBAAkB,SACtB,EACA,WAAY,CACR,WAAY,SAChB,CACJ,EACA,CACI,QAAS,CACL,eAAgB,UAChB,aAAc,UACd,oBAAqB,UACrB,eAAgB,UAChB,WAAY,UACZ,YAAa,UACb,iBAAkB,UAClB,uBAAwB,UACxB,wBAAyB,UACzB,mBAAoB,0BACpB,mBAAoB,UACpB,eAAgB,UAChB,gBAAiB,UACjB,kBAAmB,UACnB,oBAAqB,UACrB,oBAAqB,UACrB,kBAAmB,UACnB,iBAAkB,UAClB,mBAAoB,UACpB,iBAAkB,UAClB,eAAgB,yBAChB,QAAS,UACT,cAAe,UACf,gBAAiB,UACjB,qBAAsB,UACtB,uBAAwB,UACxB,mBAAoB,UACpB,qBAAsB,UACtB,oBAAqB,UACrB,iBAAkB,SACtB,EACA,WAAY,CACR,WAAY,SAChB,CACJ,CACV,CAMO,SAASC,GAA2BD,EAAuB,CAC9D,OAAOA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAiEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAoCV,CClRA,OAAqB,QAAAE,OAAY,OACjC,OAAS,WAAAC,OAAe,iBAEjB,SAASC,KAAMC,EAAsB,CACxC,OAAOF,GAAQD,GAAKG,CAAM,CAAC,CAC/B,CL0DA,IAAOC,GAAQC,GAAK,SAA2BC,EAAc,CA/D7D,IAAAC,EAgEI,GAAM,CAAE,KAAAC,EAAM,QAAAC,EAAS,OAAAC,CAAO,EAAIJ,EAC5B,CACF,MAAO,CAAE,KAAAK,EAAM,YAAaC,CAAa,CAC7C,EAAIC,EAAe,EAEbC,EAAeC,GAAuB,IAAI,EAG1C,CAACC,EAAiBC,CAAkB,EACtCC,GAAqD,IAAI,EACvD,CAACC,EAAiBC,CAAkB,EAAIF,GAGpC,IAAI,EACR,CAACG,EAAWC,CAAY,EAAIJ,GAAwB,IAAI,EAGxD,CAACK,EAAeC,CAAgB,EAAIN,GAG/B,IAAI,EAGfO,GAAU,IAAM,CACZ,GAAI,OAAO,QAAW,YAAa,OAEnC,IAAIC,EAAY,GACf,OAAC,SAAY,CACV,GAAI,CACA,GAAM,CAACC,EAAKC,CAAK,EAAI,MAAM,QAAQ,IAAI,CACnC,OAAO,8BAA8B,EACrC,OAAO,mBAAmB,EAAE,MAAM,IAAM,IAAI,CAChD,CAAC,EACD,GAAIF,EAAW,OACfT,EACI,IAAMU,EAAI,OACd,EACAP,EAAmB,CACf,KAAOO,EAAgC,KAIvC,MAAQA,EAAgC,KAI5C,CAAC,EACGC,GAAA,MAAAA,EAAO,mBACPJ,EACI,IACII,EAAM,iBAId,CAER,MAAQ,CACJ,GAAIF,EAAW,OACfJ,EACI,qFACJ,CACJ,CACJ,GAAG,EAEI,IAAM,CACTI,EAAY,EAChB,CACJ,EAAG,CAAC,CAAC,EAGL,IAAMG,EAAgBC,GACjBC,GAA2B,CACpBA,EAAE,MAAQ,WACVA,EAAE,gBAAgB,EAClBtB,EAAQ,EAEhB,EACA,CAACA,CAAO,CACZ,EAGMuB,EAAmBF,GACpBG,GAAmC,CAChC,GAAI,CAACA,EAAU,YAAa,OAC5B,IAAMC,EAAUD,EAAU,YAAY,WAAW,OAAO,EAClDA,EAAU,YACV,QAAQA,EAAU,UAAYzB,EAAK,IAAI,WACnCyB,EAAU,WACd,GACNvB,EAAOwB,EAASD,EAAU,QAAQ,CACtC,EACA,CAACzB,EAAK,KAAME,CAAM,CACtB,EAGMyB,EAAoBL,GACrBM,GAAiB,CAACC,GAAuB,IAAID,CAAI,EAClD,CAAC,CACL,EAGME,EAAenB,GAAA,MAAAA,EAAiB,MAChCZ,EAAAK,EAAa,OAAb,YAAAL,EAAmB,IACfgC,GAAI,CAvKlB,IAAAhC,EAwKmB,OAAAA,EAAAY,EAAgB,KACboB,EAAI,YAAY,CACpB,IAFC,KAAAhC,EAEIgC,IAEb,OAEAC,EAAiBC,GAAQ,IAAMC,GAAkB/B,CAAI,EAAG,CAACA,CAAI,CAAC,EAC9DgC,EAAqBF,GACvB,IAAMG,GAA2BjC,CAAI,EACrC,CAACA,CAAI,CACT,EAEA,OACIkC,GAAA,cAAC,OACG,IAAK/B,EACL,KAAK,SACL,aAAY,kBAAkBN,EAAK,IAAI,GACvC,SAAU,GACV,UAAWsC,EACP,wFACAnC,EAAO,oBAAsB,eACjC,EACA,UAAWkB,EACX,kBAAiBlB,EAAO,OAAS,SAGhCgC,GACGE,GAAA,cAAC,SACG,wBAAyB,CAAE,OAAQF,CAAmB,EAC1D,EAIJE,GAAA,cAAC,OACG,UAAWC,EACP,qFACAnC,EACM,yCACA,oCACV,GAEAkC,GAAA,cAAC,UACG,KAAK,SACL,UAAWC,EACP,yDACAnC,EACM,gDACA,6CACV,EACA,QAASF,GACZ,QAED,EACAoC,GAAA,cAAC,QACG,UAAWC,EACP,kCACAnC,EAAO,qBAAuB,oBAClC,GACH,WACYH,EAAK,IAClB,EAEAqC,GAAA,cAAC,QAAK,UAAU,YAAY,CAChC,EAGAA,GAAA,cAAC,OAAI,UAAU,kDACVxB,GACGwB,GAAA,cAAC,OAAI,UAAU,wEACXA,GAAA,cAAC,KACG,UAAWC,EACP,gCACAnC,EACM,oBACA,mBACV,GAECU,CACL,CACJ,EAGH,CAACL,GAAmB,CAACK,GAClBwB,GAAA,cAAC,OAAI,UAAU,+DACXA,GAAA,cAAC,OACG,UAAWC,EACP,gGACAnC,EACM,uBACA,sBACV,EACJ,CACJ,EAGHK,GAAmB,CAACK,GACjBwB,GAAA,cAACE,GAAA,CACG,cAAexB,EACf,kBAAmBY,GAEnBU,GAAA,cAAC7B,EAAA,CACG,OAAQR,EAAK,IACb,OAAQwB,EACR,QAASvB,EACT,iBAAkB,EAClB,kBAAmB,EACnB,MAAO+B,EACP,aACIrB,GAAA,MAAAA,EAAiB,KAEPA,EAAgB,KAIlB,OACF,OAEV,QAASmB,EACT,aAAc,IAAM,GACxB,CACJ,CAER,CACJ,CAER,CAAC,EAKKD,GAAyB,IAAI,IAAI,CACnC,SACA,WACA,iBACA,gBACA,iBACA,cACA,aACJ,CAAC,EAMD,SAASU,GAAc,CACnB,SAAAC,EACA,cAAAzB,EACA,kBAAAY,CACJ,EAOG,CACC,OAAIZ,EAEIsB,GAAA,cAACtB,EAAA,CAAc,kBAAmBY,GAC7Ba,CACL,EAGDH,GAAA,cAAAA,GAAA,cAAGG,CAAS,CACvB,CM5UA,OAAOC,GAEH,QAAAC,GACA,eAAAC,GACA,aAAAC,GACA,WAAAC,GACA,UAAAC,GACA,YAAAC,OACG,QACP,OAAS,gBAAAC,OAAoB,YA8D7B,IAAOC,GAAQC,GAAK,SAA0BC,EAAc,CAvE5D,IAAAC,EAwEI,GAAM,CAAE,KAAAC,EAAM,QAAAC,EAAS,OAAAC,CAAO,EAAIJ,EAC5B,CACF,MAAO,CAAE,KAAAK,EAAM,YAAaC,CAAa,CAC7C,EAAIC,EAAe,EAEbC,EAAaC,GAAuB,IAAI,EACxCC,EAAmBD,GAAuB,IAAI,EAG9C,CAACE,EAAiBC,CAAkB,EACtCC,GAAqD,IAAI,EACvD,CAACC,EAAiBC,CAAkB,EAAIF,GAGpC,IAAI,EACR,CAACG,EAAWC,CAAY,EAAIJ,GAAwB,IAAI,EAIxD,CAACK,EAAeC,CAAgB,EAAIN,GAG/B,IAAI,EAGfO,GAAU,IAAM,CACZ,GAAI,OAAO,QAAW,YAAa,OAEnC,IAAIC,EAAY,GACf,OAAC,SAAY,CACV,GAAI,CACA,GAAM,CAACC,EAAKC,CAAK,EAAI,MAAM,QAAQ,IAAI,CACnC,OAAO,8BAA8B,EACrC,OAAO,mBAAmB,EAAE,MAAM,IAAM,IAAI,CAChD,CAAC,EACD,GAAIF,EAAW,OACfT,EACI,IAAMU,EAAI,OACd,EACAP,EAAmB,CACf,KAAOO,EAAgC,KAIvC,MAAQA,EAAgC,KAI5C,CAAC,EACGC,GAAA,MAAAA,EAAO,mBACPJ,EACI,IACII,EAAM,iBAId,CAER,MAAQ,CACJ,GAAIF,EAAW,OACfJ,EACI,qFACJ,CACJ,CACJ,GAAG,EAEI,IAAM,CACTI,EAAY,EAChB,CACJ,EAAG,CAAC,CAAC,EAILD,GAAU,KACNV,EAAiB,QAAU,SAAS,cAC7B,IAAM,CACLA,EAAiB,mBAAmB,aACpCA,EAAiB,QAAQ,MAAM,CAEvC,GACD,CAAC,CAAC,EAGLU,GAAU,IAAM,CA3JpB,IAAAnB,GA4JQA,EAAAO,EAAW,UAAX,MAAAP,EAAoB,OACxB,EAAG,CAAC,CAAC,EAGL,IAAMuB,EAAgBC,GACjBC,GAA2B,CAjKpC,IAAAzB,EAwKY,GANIyB,EAAE,MAAQ,WACVA,EAAE,gBAAgB,EAClBvB,EAAQ,GAIRuB,EAAE,MAAQ,MAAO,CACjB,IAAMC,GACF1B,EAAAO,EAAW,UAAX,YAAAP,EAAoB,iBAChB,4EAER,GAAI,CAAC0B,GAAaA,EAAU,SAAW,EAAG,OAC1C,IAAMC,EAAQD,EAAU,CAAC,EACnBE,EAAOF,EAAUA,EAAU,OAAS,CAAC,EAEvCD,EAAE,SACE,SAAS,gBAAkBE,IAC3BF,EAAE,eAAe,EACjBG,EAAK,MAAM,GAGX,SAAS,gBAAkBA,IAC3BH,EAAE,eAAe,EACjBE,EAAM,MAAM,EAGxB,CACJ,EACA,CAACzB,CAAO,CACZ,EAGM2B,EAAqBL,GACtBC,GAAwBA,EAAE,gBAAgB,EAC3C,CAAC,CACL,EAGMK,EAAmBN,GACpBO,GAAmC,CAChC,GAAI,CAACA,EAAU,YAAa,OAC5B,IAAMC,EAAUD,EAAU,YAAY,WAAW,OAAO,EAClDA,EAAU,YACV,QAAQA,EAAU,UAAY9B,EAAK,IAAI,WACnC8B,EAAU,WACd,GACN5B,EAAO6B,EAASD,EAAU,QAAQ,CACtC,EACA,CAAC9B,EAAK,KAAME,CAAM,CACtB,EAIM8B,EAAoBT,GACrBU,GAAiB,CAACC,GAAuB,IAAID,CAAI,EAClD,CAAC,CACL,EAGME,EAAevB,GAAA,MAAAA,EAAiB,MAChCb,EAAAK,EAAa,OAAb,YAAAL,EAAmB,IACfqC,GAAI,CA/NlB,IAAArC,EAgOmB,OAAAA,EAAAa,EAAgB,KACbwB,EAAI,YAAY,CACpB,IAFC,KAAArC,EAEIqC,IAEb,OAEAC,EAAiBC,GAAQ,IAAMC,GAAkBpC,CAAI,EAAG,CAACA,CAAI,CAAC,EAC9DqC,EAAqBF,GACvB,IAAMG,GAA2BtC,CAAI,EACrC,CAACA,CAAI,CACT,EAEA,OAAOuC,GACHC,EAAA,cAAC,OAAI,UAAU,cACXA,EAAA,cAAC,OACG,IAAKrC,EACL,KAAK,SACL,aAAW,OACX,aAAY,eAAeN,EAAK,IAAI,GACpC,SAAU,GACV,UAAU,iIACV,QAASC,EACT,UAAWqB,GAEXqB,EAAA,cAAC,OACG,UAAWC,EACP,wIACAzC,EAAO,oBAAsB,eACjC,EACA,kBAAiBA,EAAO,OAAS,QACjC,QAASyB,GAERY,GACGG,EAAA,cAAC,SACG,wBAAyB,CACrB,OAAQH,CACZ,EACJ,EAIJG,EAAA,cAAC,OACG,UAAWC,EACP,qFACAzC,EACM,0CACA,yCACV,GAEAwC,EAAA,cAAC,MAAG,UAAU,iCAAgC,qBAC5B3C,EAAK,IACvB,EACA2C,EAAA,cAAC,UACG,KAAK,SACL,aAAW,eACX,UAAWC,EACP,sFACA,wDACAzC,EACM,qEACA,oEACV,EACA,QAASF,GACZ,MAED,CACJ,EAGA0C,EAAA,cAAC,OAAI,UAAU,kDACV7B,GACG6B,EAAA,cAAC,OAAI,UAAU,wEACXA,EAAA,cAAC,KACG,UAAWC,EACP,gCACAzC,EACM,oBACA,mBACV,GAECW,CACL,CACJ,EAGH,CAACL,GAAmB,CAACK,GAClB6B,EAAA,cAAC,OAAI,UAAU,+DACXA,EAAA,cAAC,OACG,UAAWC,EACP,gGACAzC,EACM,uBACA,sBACV,EACJ,CACJ,EAGHM,GAAmB,CAACK,GACjB6B,EAAA,cAACE,GAAA,CACG,cAAe7B,EACf,kBAAmBgB,GAEnBW,EAAA,cAAClC,EAAA,CACG,OAAQT,EAAK,IACb,OAAQ6B,EACR,QAAS5B,EACT,iBAAkB,EAClB,kBAAmB,EACnB,MAAOoC,EACP,aACIzB,GAAA,MAAAA,EAAiB,KAEPA,EAAgB,KAIlB,OACF,OAEV,QAASuB,EACT,aAAc,IAAM,GACxB,CACJ,CAER,CACJ,CACJ,CACJ,EACA,SAAS,IACb,CACJ,CAAC,EAMKD,GAAyB,IAAI,IAAI,CACnC,SACA,WACA,iBACA,gBACA,iBACA,cACA,aACJ,CAAC,EAOD,SAASW,GAAc,CACnB,SAAAC,EACA,cAAA9B,EACA,kBAAAgB,CACJ,EAOG,CACC,OAAIhB,EAEI2B,EAAA,cAAC3B,EAAA,CAAc,kBAAmBgB,GAC7Bc,CACL,EAGDH,EAAA,cAAAA,EAAA,cAAGG,CAAS,CACvB,CC1YA,OAAS,UAAAC,OAAc,gBACvB,OAAOC,OAAW,QCHlB,OAA2B,eAAAC,GAAa,WAAAC,GAAS,YAAAC,OAAgB,QAGlD,SAARC,IAA8B,CACjC,GAAM,CACF,MAAAC,EACA,cAAAC,EACA,aAAAC,EACA,OAAQ,CAAE,aAAAC,CAAa,EACvB,MAAO,CAAE,gBAAAC,EAAiB,iBAAAC,EAAkB,YAAAC,EAAa,aAAAC,CAAa,EACtE,SAAAC,CACJ,EAAIC,EAAe,EACb,CAACC,EAAYC,CAAa,EAAIC,GAAS,EAAK,EAE5CC,EAAqBC,GACvB,IAAMJ,GAAc,CAACT,EACrB,CAACS,EAAYT,CAAa,CAC9B,EAEMc,EAAoBD,GACtB,KAAO,CAACd,EAAM,MAAQE,GAAgBQ,IAAe,CAACT,EACtD,CAACA,EAAeD,EAAM,KAAME,EAAcQ,CAAU,CACxD,EAEMM,EAAoBF,GACtB,IAAMb,GAAA,KAAAA,EAAiBE,IAAiB,UACxC,CAACF,EAAeE,CAAY,CAChC,EAEMc,EAAmDC,GACrDC,GAAK,CACD,GAAIH,GAAqBT,EAAc,OACvCY,EAAE,eAAe,EAEjBR,EAAc,EAAI,EAClBQ,EAAE,aAAa,WAAa,OAE5B,IAAMnB,EAAQ,MAAM,KAAKmB,EAAE,aAAa,KAAK,EAC7Cf,EAAgBJ,CAAK,CACzB,EACA,CAACgB,EAAmBZ,EAAiBG,CAAY,CACrD,EAEMa,EAAoDF,GACtDC,GAAK,CACD,GAAIH,GAAqBT,EAAc,OACvCY,EAAE,eAAe,EAEjBR,EAAc,EAAK,EAEnB,IAAMX,EAAQ,MAAM,KAAKmB,EAAE,aAAa,KAAK,EAC7Cd,EAAiBL,CAAK,CAC1B,EACA,CAACgB,EAAmBX,EAAkBE,CAAY,CACtD,EAEMc,EAA+CH,GACjD,MAAMC,GAAK,CAzDnB,IAAAG,EA0DY,GAAIN,GAAqBT,EAAc,OACvCY,EAAE,eAAe,EAEjB,IAAMI,EAAKJ,EAAE,aACPK,EAAQ,MAAM,KAAKD,EAAG,OAAS,CAAC,CAAC,EACnCE,EAAuB,CAAC,EAG5B,IADyBH,EAAAE,EAAM,CAAC,IAAP,YAAAF,EAAkB,iBACtB,CACjB,IAAMI,EAAW,MAAOC,GAAgC,CACpD,GAAIA,EAAM,OACN,OAAO,MAAM,IAAI,QAAgB,CAACC,EAASC,IAAW,CAClDF,EAAM,KAAMG,GAAe,CACvB,GAAI,CAEA,IAAMC,EACFJ,EAAM,UAAY,IAAIG,EAAK,IAAI,GACnC,OAAO,eACHA,EACA,eACA,CACI,MAAOC,EAAK,QAAQ,MAAO,EAAE,EAC7B,aAAc,GACd,WAAY,GACZ,SAAU,EACd,CACJ,CACJ,MAAQ,CAER,CACAH,EAAQ,CAACE,CAAI,CAAC,CAClB,EAAGD,CAAM,CACb,CAAC,EACE,GAAIF,EAAM,YAAa,CAC1B,IAAMK,EAASL,EAAM,aAAa,EAC5BM,EAAiB,MAAM,IAAI,QAC7B,CAACL,EAASC,IAAW,CACjBG,EAAO,YAAYJ,EAASC,CAAM,CACtC,CACJ,EAEA,OADY,MAAM,QAAQ,IAAII,EAAQ,IAAIP,CAAQ,CAAC,GACxC,KAAK,CACpB,CACA,MAAO,CAAC,CACZ,EAOAD,GANoB,MAAM,QAAQ,IAC9BD,EACK,IAAIU,GAAG,CAzGhC,IAAAZ,EAyGoC,OAAAA,EAAAY,EAAW,mBAAX,YAAAZ,EAAA,KAAAY,GAA+B,EAC1C,OAAO,OAAO,EACd,IAAIR,CAAQ,CACrB,GAC2B,KAAK,CACpC,SAAW,0BAA4BF,EAAM,CAAC,GAAM,CAAC,GAAY,CAE7D,IAAMW,EAAiB,MACnBC,EACAL,EAAO,KACW,CAClB,GAAIK,EAAE,OAAS,OAAQ,CACnB,IAAMN,EAAO,MAAMM,EAAE,QAAQ,EAC7B,GAAI,CACA,OAAO,eAAeN,EAAM,eAAgB,CACxC,MAAOC,EAAOD,EAAK,KACnB,aAAc,GACd,WAAY,GACZ,SAAU,EACd,CAAC,CACL,MAAQ,CAER,CACA,MAAO,CAACA,CAAI,CAChB,SAAWM,EAAE,OAAS,YAAa,CAC/B,IAAMC,EAAc,CAAC,EACrB,aAAiB,CAACC,EAAMC,CAAK,IAAKH,EAAE,QAAQ,EACxCC,EAAI,KACA,GAAI,MAAMF,EACNI,EACAR,EAAOO,EAAO,GAClB,CACJ,EAEJ,OAAOD,CACX,CACA,MAAO,CAAC,CACZ,EACMG,EAAU,MAAM,QAAQ,IAC1BhB,EAAM,IACF,MAAMU,GAAG,CAjJjC,IAAAZ,EAiJoC,cAAOA,EAAAY,EAAW,wBAAX,YAAAZ,EAAA,KAAAY,IACvB,CACJ,EAIAT,GAHY,MAAM,QAAQ,IACtBe,EAAQ,OAAO,OAAO,EAAE,IAAKJ,GAAWD,EAAeC,CAAC,CAAC,CAC7D,GACmB,KAAK,CAC5B,MAEIX,EAAe,MAAM,KAAKF,EAAG,KAAK,EAGtCjB,EAAYmB,CAAY,EACxBjB,EAASiB,CAAY,EAErBd,EAAc,EAAK,CACvB,EACA,CAACK,EAAmBV,EAAaE,EAAUD,CAAY,CAC3D,EAEA,MAAO,CACH,WAAAG,EACA,mBAAAG,EACA,kBAAAE,EACA,eAAAE,EACA,gBAAAG,EACA,WAAAC,CACJ,CACJ,CC7KA,OAAOoB,GAAS,eAAAC,OAAmB,QACnC,OAAS,YAAAC,OAAgB,iBCDzB,OAA6B,eAAAC,GAAa,WAAAC,OAAe,QCKlD,IAAKC,QACRA,EAAA,SAAW,WACXA,EAAA,aAAe,eACfA,EAAA,UAAY,YACZA,EAAA,QAAU,UACVA,EAAA,KAAO,OACPA,EAAA,OAAS,SANDA,QAAA,IA2BAC,QACRA,EAAA,IAAM,MACNA,EAAA,MAAQ,QACRA,EAAA,UAAY,YACZA,EAAA,aAAe,eAJPA,QAAA,IA2PL,IAAMC,EAAN,cAA0B,KAAM,CAGnC,YACIC,EACOC,EAAO,uBACPC,EAAY,GACZC,EACT,CACE,MAAMH,CAAO,EAJN,UAAAC,EACA,eAAAC,EACA,YAAAC,EANX,KAAiB,0BAA4B,IASzC,KAAK,KAAO,cACZ,KAAK,OAASA,GAAA,KAAAA,EAAU,KAAK,yBACjC,CACJ,ECxSA,OAAOC,MAAW,QAClB,OAAOC,OAAY,eCDnB,OAA4B,UAAAC,GAAQ,YAAAC,OAAgB,QCApD,OAAS,eAAAC,GAAa,YAAAC,OAAgB,QACtC,OAAS,MAAMC,OAAY,OAGZ,SAARC,IAAqC,CACxC,GAAM,CACF,MAAO,CAAE,QAAAC,CAAQ,CACrB,EAAIC,EAAe,EACb,CAACC,EAASC,CAAU,EAAIC,GAAS,EAAK,EAEtCC,EAAaC,GACf,MAAOC,GAAgB,CACnB,GAAI,CAAAL,EAEJ,GAAI,CACAC,EAAW,EAAI,EAEf,IAAMK,EAAO,MADI,MAAM,MAAMD,CAAG,GACJ,KAAK,EAC3BE,EAAYD,EAAK,KAAK,MAAM,GAAG,EAAE,CAAC,EAMxC,OAJa,IAAI,KAAK,CAACA,CAAI,EAAG,GAAGE,GAAK,CAAC,IAAID,CAAS,GAAI,CACpD,KAAMD,EAAK,IACf,CAAC,CAGL,OAASG,EAAO,CACZX,EAASW,EAAgB,OAAO,EAChC,MACJ,QAAE,CACER,EAAW,EAAK,CACpB,CACJ,EACA,CAACD,EAASF,CAAO,CACrB,EAEA,MAAO,CAAE,QAAAE,EAAS,WAAAG,CAAW,CACjC,CD1Be,SAARO,IAAqC,CACxC,GAAM,CAAE,SAAAC,EAAU,iBAAAC,EAAkB,aAAAC,EAAc,MAAAC,CAAM,EAAIC,EAAe,EACrE,CAAE,WAAAC,CAAW,EAAIC,GAAkB,EACnCC,EAAYC,GAAe,IAAI,EAC/B,CAACC,EAAKC,CAAM,EAAIC,GAAS,EAAE,EAC3B,CAACC,EAAYC,CAAa,EAAIF,GAChC,aACJ,EA4BA,MAAO,CACH,IAAAF,EACA,UAAAF,EACA,WAAAK,EACA,QA3BY,SAAY,CAtBhC,IAAAE,EAuBQ,IAAML,GAAMK,EAAAP,EAAU,UAAV,YAAAO,EAAmB,gBAC1BL,GAELC,EAAOD,CAAG,CACd,EAuBI,iBArB2D,SAAY,CACvE,IAAMM,EAAO,MAAMV,EAAWI,CAAG,EAC7BM,IACAf,EAAS,CAACe,CAAI,CAAC,EACfL,EAAO,EAAE,EACTT,EAAiB,MAAS,EAElC,EAeI,SA/Ba,IAAMS,EAAO,EAAE,EAgC5B,mBAduB,IACvBG,EAAcG,GACVA,IAAc,cACR,OACA,aACV,EAUA,cAlCAJ,IAAe,cAAyB,QAAU,OAmClD,aAAAV,EACA,MAAAC,CACJ,CACJ,CEzDA,OAAOc,OAAkC,QAI1B,SAARC,GAAsC,CACzC,SAAAC,EACA,UAAAC,EAAY,EAChB,EAA+C,CAC3C,GAAM,CACF,MAAO,CAAE,KAAAC,EAAM,WAAAC,CAAW,CAC9B,EAAIC,EAAe,EAEnB,OACIC,GAAA,cAAC,OACG,UAAWC,EACP,6FACA,CACI,sFACIL,GAAaC,EACjB,CAACC,EAAW,WAAY,EACpB,CAACF,GAAaE,EAAW,YAC7B,CAACA,EAAW,YAAa,EACrBF,GAAaE,EAAW,YAChC,CACJ,GAECH,CACL,CAER,CC7BA,OAAOO,OAAkC,QAG1B,SAARC,EAA8B,CACjC,SAAAC,EACA,GAAIC,EACJ,UAAAC,EAAY,EAChB,EAA4D,CACxD,GAAM,CACF,MAAO,CACH,MAAO,CAAE,WAAAC,CAAW,CACxB,CACJ,EAAIC,EAAe,EAEnB,OAAIF,EAAkBG,GAAA,cAACF,EAAA,IAAW,EAC7BF,EAEEI,GAAA,cAAAA,GAAA,cAAGL,CAAS,EAFI,IAG3B,CJVe,SAARM,IAAkC,CACrC,GAAM,CACF,QAAAC,EACA,iBAAAC,EACA,SAAAC,EACA,mBAAAC,EACA,cAAAC,EACA,IAAAC,EACA,UAAAC,EACA,WAAAC,EACA,aAAcC,EACd,MAAO,CACH,KAAAC,EACA,WAAAC,EACA,MAAO,CAAE,kBAAAC,EAAmB,iBAAAC,EAAkB,iBAAAC,CAAiB,CACnE,CACJ,EAAIC,GAAkB,EAEtB,OACIC,EAAA,cAACC,GAAA,KACGD,EAAA,cAAC,OAAI,UAAU,8GACXA,EAAA,cAAC,OAAI,UAAU,0BACXA,EAAA,cAACE,EAAA,CAAa,GAAI,CAAC,CAACZ,GAChBU,EAAA,cAAC,OACG,UAAWG,EACP,wHACA,CACI,uCACIT,CACR,EACAC,EAAW,sBACf,EACA,MAAO,CAAE,gBAAiB,OAAOL,CAAG,GAAI,GAExCU,EAAA,cAAC,UACG,QAASb,EACT,UAAWgB,EACP,kIACAR,EAAW,kBACf,EACA,KAAK,UAELK,EAAA,cAACH,EAAA,IAAiB,CACtB,CACJ,CACJ,EAEAG,EAAA,cAACE,EAAA,CAAa,GAAI,CAACZ,GACfU,EAAA,cAACI,GAAA,CACG,MAAO,GACP,IAAKb,EACL,iBAAiB,aACjB,iBAAkB,CAAE,WAAAC,CAAW,EAC/B,UAAU,oCACd,CACJ,CACJ,EACAQ,EAAA,cAAC,OAAI,UAAU,wBACXA,EAAA,cAACE,EAAA,CAAa,GAAI,CAACZ,GACfU,EAAA,cAAC,UACG,UAAWG,EACP,uLACA,CACI,2CACIT,CACR,EACAC,EAAW,mBACf,EACA,QAASV,EACT,KAAK,UAELe,EAAA,cAAC,YACGA,EAAA,cAACJ,EAAA,IAAkB,CACvB,EACAI,EAAA,cAAC,YAAMP,EAAG,OAAQ,CACtB,EACAO,EAAA,cAAC,UACG,UAAWG,EACP,wLACAR,EAAW,kBACf,EACA,QAASP,EACT,KAAK,UAELY,EAAA,cAAC,YACGA,EAAA,cAACF,EAAA,IAAiB,CACtB,EACAE,EAAA,cAAC,YACIK,EAAEZ,EAAG,eAAgB,CAClB,KACIJ,IAAkB,QACZI,EAAG,MACHA,EAAG,IACjB,CAAC,CACL,CACJ,CACJ,EACAO,EAAA,cAACE,EAAA,CAAa,GAAI,CAAC,CAACZ,GAChBU,EAAA,cAAC,UACG,UAAWG,EACP,wHACA,CACI,2CACIT,CACR,EACAC,EAAW,eACf,EACA,QAAST,EACT,KAAK,UAEJO,EAAG,QACR,CACJ,CACJ,CACJ,CACJ,CAER,CK7HA,OAAOa,IAAS,aAAAC,OAAiB,QCCjC,OAAS,eAAAC,GAAa,aAAAC,GAAW,YAAAC,OAAgB,QCAjD,OAAS,WAAAC,OAA4B,UACrC,OAAS,eAAAC,GAAa,aAAAC,GAAW,UAAAC,GAAQ,YAAAC,OAAgB,QCSzD,IAAIC,GAAoC,KAE3BC,GAAsB,IAAwB,CACvD,GAAID,GAAU,OAAOA,GAGrB,IAAME,EAAUC,GAA8B,KAAKA,CAAG,EAChDC,EAAUD,GAAgB,CAE5B,GAAI,CACA,OAAO,KAAKA,CAAG,CACnB,MAAQ,CACJ,OAAOA,CACX,CACJ,EAEME,EAAUC,GAAmBJ,EAAO,KAAKI,CAAM,EAAE,EAEjDC,EAAQC,GACV,KAAK,UAAU,CAAE,MAAAA,EAAO,UAAW,KAAK,IAAI,CAAE,CAAC,EAE7CC,EAAaC,GAAe,KAAK,IAAI,EAAIA,EAAK,IAAU,GAAK,GAAK,IAExE,OAAAV,GAAW,CACP,QAAS,CAACW,EAAKH,IAAU,CACrB,GAAI,CACA,IAAMI,EAAWP,EAAOM,CAAG,EACrBE,EAAYX,EAAOK,EAAKC,CAAK,CAAC,EACpC,aAAa,QAAQI,EAAUC,CAAS,CAC5C,OAASC,EAAK,CACV,QAAQ,MAAM,+BAAgCA,CAAG,EACjD,aAAa,QAAQH,EAAKH,CAAK,CACnC,CACJ,EAEA,QAASG,GAAO,CACZ,IAAMC,EAAWP,EAAOM,CAAG,EAEvBI,EAAS,aAAa,QAAQH,CAAQ,EAG1C,GADKG,IAAQA,EAAS,aAAa,QAAQJ,CAAG,GAC1C,CAACI,EAAQ,OAAO,KAEpB,IAAMC,EAAYZ,EAAOW,CAAM,EAE/B,GAAI,CACA,GAAM,CAAE,MAAAP,EAAO,UAAAS,CAAU,EAAI,KAAK,MAAMD,CAAS,EACjD,GAAIR,GAASS,GAAa,CAACR,EAAUQ,CAAS,EAAG,OAAOT,EACpDA,IACA,aAAa,WAAWI,CAAQ,EAChC,aAAa,WAAWD,CAAG,EAEnC,MAAQ,CACJ,OAAOK,CACX,CACA,OAAO,IACX,EAEA,WAAYL,GAAO,CACf,aAAa,WAAWN,EAAOM,CAAG,CAAC,EACnC,aAAa,WAAWA,CAAG,CAC/B,EAEA,MAAOO,GAAQ,CACXA,EAAK,QAAQC,GAAK,CACd,aAAa,WAAWd,EAAOc,CAAC,CAAC,EACjC,aAAa,WAAWA,CAAC,CAC7B,CAAC,CACL,CACJ,EAEOnB,EACX,ED7EA,IAAMoB,GAAY,uBACZC,GAAc,wBACdC,GAAW,eAEXC,GAAW,mBAOXC,GAASC,GAAoB,EAE7BC,GAAkBC,GAAc,CAClC,GAAIA,EAAE,SAAS,eAAe,cAAc,EAAG,OAC/C,IAAMC,EAAMD,EAAE,SACRE,EAAUD,EAAI,cAAc,KAAK,EACjCE,EAAUF,EAAI,cAAc,KAAK,EACvCC,EAAQ,GAAK,eACbA,EAAQ,MAAM,QACV,6GAEJC,EAAQ,MAAM,QACV,gIAEJD,EAAQ,YAAYC,CAAO,EAE3B,IAAMC,EAAQH,EAAI,cAAc,OAAO,EACvCG,EAAM,YAAc,mDACpBH,EAAI,KAAK,YAAYG,CAAK,EAC1BH,EAAI,KAAK,YAAYC,CAAO,CAChC,EAGMG,GAAO,CAACC,EAAI,KACd,MAAM,KAAK,OAAO,gBAAgB,IAAI,WAAWA,CAAC,CAAC,CAAC,EAC/C,IACGC,GACI,qEACIA,EAAI,EACR,CACR,EACC,KAAK,EAAE,EAEVC,GAAUC,GACZ,OAAO,OAAO,OAAO,UAAW,IAAI,YAAY,EAAE,OAAOA,CAAG,CAAC,EAE3DC,GAAUC,GACZ,KAAK,OAAO,aAAa,GAAG,IAAI,WAAWA,CAAE,CAAC,CAAC,EAC1C,QAAQ,MAAO,GAAG,EAClB,QAAQ,MAAO,GAAG,EAClB,QAAQ,MAAO,EAAE,EAGnB,SAASC,GAAeC,EAAsB,CACjD,GAAM,CACF,MAAO,CAAE,QAAAC,CAAQ,EACjB,aAAAC,CACJ,EAAIC,EAAe,EAEb,CAACC,EAAOC,CAAM,EAAIC,GAAiB,EACnC,CAACC,EAAMC,CAAO,EAAIF,GAAiB,EACnC,CAACG,EAAMC,CAAO,EAAIJ,GAAsB,EACxC,CAACK,EAAMC,CAAO,EAAIN,GAAS,EAAK,EAChC,CAACO,EAAOC,CAAQ,EAAIR,GAAS,EAAK,EAElCS,EAASC,GAAsB,IAAI,EACnCC,EAAUD,GAA8C,IAAI,EAC5DE,EAAcF,GAAe,EAAE,EAE/BG,EAAWnB,GAAA,YAAAA,EAAK,kBAChBoB,GACFpB,GAAA,YAAAA,EAAK,uBAAwB,GAAG,OAAO,SAAS,MAAM,eAG1DqB,GAAU,IAAM,CACZ,IAAMC,EAAItC,GAAO,QAAQJ,EAAS,EAC5B2C,EAAKvC,GAAO,QAAQH,EAAW,EAC/B2C,EAAIxC,GAAO,QAAQF,EAAQ,EAC7BwC,GAAKE,IACLnB,EAAOiB,CAAC,EACRd,EAAQe,GAAM,MAAS,EACvBb,EAAQ,KAAK,MAAMc,CAAC,CAAC,GAEzBV,EAAS,EAAI,CACjB,EAAG,CAAC,CAAC,EAGL,IAAMW,EAAeC,GACjB,MAAOC,EAAgBC,IAAqB,CACxC5C,GAAO,QAAQJ,GAAW+C,CAAM,EAC5BC,GAAS5C,GAAO,QAAQH,GAAa+C,CAAO,EAEhD,GAAI,CACA,IAAMC,GACF,MAAM,IAAIC,GAAQ,CACd,YAAaH,CACjB,CAAC,EAAE,uBAAuB,GAC5B,OACII,EAAuB,CACzB,KAAMF,EAAK,KAAK,aAChB,MAAOA,EAAK,MACZ,QAASA,EAAK,kBACd,OAAQA,EAAK,OACb,WAAYA,EAAK,KAAK,WACtB,YAAaA,EAAK,KAAK,OAC3B,EACA7C,GAAO,QAAQF,GAAU,KAAK,UAAUiD,CAAO,CAAC,EAChDrB,EAAQqB,CAAO,CACnB,OAASC,EAAG,CACR,QAAQ,IAAI,kCAAmCA,CAAC,CACpD,CAEA3B,EAAOsB,CAAM,EACbnB,EAAQoB,GAAW,MAAS,EAC5BhB,EAAQ,EAAK,CACjB,EACA,CAAC,CACL,EAGMqB,EAAeP,GAAY,SAAY,CA/HjD,IAAAQ,EAgIQ,GAAI,CAACf,EAAU,CACXlB,EAAQC,EAAa,sBAAsB,EAC3C,MACJ,CACA,GAAIS,EACA,OAGJ,IAAMwB,EAAW3C,GAAK,GAAG,EACzB0B,EAAY,QAAUiB,EACtB,IAAMC,EAAYvC,GAAO,MAAMF,GAAOwC,CAAQ,CAAC,EAEzCE,EACF,sDACc,mBAAmBlB,CAAQ,CAAC,oCAEzB,mBAAmBC,CAAW,CAAC,oCAEtC,mBACN,8EACJ,CAAC,mBACkBgB,CAAS,8BAYhC,IATAF,EAAAnB,EAAO,UAAP,MAAAmB,EAAgB,QAChBnB,EAAO,QAAU,OAAO,KACpBsB,EACAtD,GACA,6BAA6B,OAAO,QAAU,EAAE,QAC5C,OAAO,QAAU,EACrB,8CACJ,EAEI,CAACgC,EAAO,QAAS,CACjBd,EAAQC,EAAa,YAAY,EACjC,MACJ,CAEAU,EAAQ,EAAI,EAGZK,EAAQ,QAAU,YAAY,SAAY,CAzKlD,IAAAiB,EAAAI,EA0KY,GAAKvB,EAAO,QACZ,CAAA7B,GAAe6B,EAAO,OAAO,EAC7B,GAAI,CAEA,GAAIA,EAAO,QAAQ,OAAQ,CACvB,cAAcE,EAAQ,OAAQ,EAC9BL,EAAQ,EAAK,EACb,MACJ,CAEA,IAAM2B,EAAOxB,EAAO,QAAQ,SAAS,KACrC,GAAI,CAACwB,EAAK,WAAWnB,CAAW,GAAK,CAACmB,EAAK,SAAS,OAAO,EACvD,OAEJ,cAActB,EAAQ,OAAQ,EAE9B,IAAMuB,EAAO,IAAI,IAAID,CAAI,EAAE,aAAa,IAAI,MAAM,EAC5CE,EAAO,IAAI,gBAAgB,CAC7B,KAAAD,EACA,UAAWrB,EACX,cAAeD,EAAY,QAC3B,WAAY,qBACZ,aAAcE,CAClB,CAAC,EAEKsB,EAAM,MAAM,MACd,uCACA,CACI,OAAQ,OACR,QAAS,CACL,eAAgB,mCACpB,EACA,KAAAD,CACJ,CACJ,EACA,GAAI,CAACC,EAAI,GAAI,MAAM,IAAI,MAAM,MAAMA,EAAI,KAAK,CAAC,EAC7C,IAAMC,GAAI,MAAMD,EAAI,KAAK,EAEzB,MAAMjB,EAAakB,GAAE,aAAcA,GAAE,aAAa,EAClD5B,EAAO,QAAQ,MAAM,CACzB,OAASiB,EAAG,CAER,IAAKE,EAAAF,EAAY,UAAZ,MAAAE,EAAqB,SAAS,kBAAmB,OACtD,QAAQ,MAAM,wBAAyBF,CAAC,EACnCA,EAAY,SAAW,iBACxB/B,EAAQC,EAAa,iBAAiB,EAC1CU,EAAQ,EAAK,GACb0B,EAAAvB,EAAO,UAAP,MAAAuB,EAAgB,QAChB,cAAcrB,EAAQ,OAAQ,CAClC,EACJ,EAAG,GAAG,CACV,EAAG,CAACE,EAAUC,EAAaT,EAAMV,EAASwB,CAAY,CAAC,EAGjDmB,EAAqBlB,GACvB,MAAOH,GAAuC,CAC1C,GAAI,CAACJ,EAAU,OAAO,KACtB,GAAI,CACA,IAAM0B,EAAI,MAAM,MAAM,uCAAwC,CAC1D,OAAQ,OACR,QAAS,CACL,eAAgB,mCACpB,EACA,KAAM,IAAI,gBAAgB,CACtB,WAAY,gBACZ,cAAetB,EACf,UAAWJ,CACf,CAAC,CACL,CAAC,EACD,GAAI,CAAC0B,EAAE,GAAI,MAAM,IAAI,MAAM,MAAMA,EAAE,KAAK,CAAC,EACzC,IAAMF,EAAI,MAAME,EAAE,KAAK,EACvB,OAAA7D,GAAO,QAAQJ,GAAW+D,EAAE,YAAY,EACxCtC,EAAOsC,EAAE,YAAY,EACrB,QAAQ,IAAI,4BAA4B,EACjCA,EAAE,YACb,OAASX,EAAG,CACR,eAAQ,MAAM,2BAA4BA,CAAC,EAC3C/B,EAAQC,EAAa,qBAAqB,EAC1C4C,EAAO,EACA,IACX,CACJ,EAEA,CAAC3B,EAAUlB,CAAO,CACtB,EAGM6C,EAASpB,GAAY,IAAM,CAjQrC,IAAAQ,EAkQQlD,GAAO,MAAM,CAACJ,GAAWC,GAAaC,EAAQ,CAAC,EAC/CuB,EAAO,MAAS,EAChBG,EAAQ,MAAS,EACjBE,EAAQ,MAAS,GACjBwB,EAAAnB,EAAO,UAAP,MAAAmB,EAAgB,QACZnB,EAAO,SAASA,EAAO,QAAQ,MAAM,EACzCH,EAAQ,EAAK,CACjB,EAAG,CAAC,CAAC,EAEL,MAAO,CACH,MAAOR,EACP,aAAcG,EACd,KAAAE,EACA,UAAW,CAACI,GAASF,EACrB,gBAAiB,CAAC,CAACP,EACnB,aAAA6B,EACA,OAAAa,EACA,cAAe1C,EAAQ,IAAI0B,GAAQ,CAAE,YAAa1B,CAAM,CAAC,EAAI,KAC7D,mBAAAwC,CACJ,CACJ,CDjRA,IAAMG,GAAkBC,IAA6B,CACjD,GAAIA,EAAM,GACV,KAAMA,EAAM,KACZ,aAAcA,EAAM,aACpB,SAAUA,EAAM,MAAM,IAAM,SAC5B,KAAMA,EAAM,KACZ,cAAe,IACnB,GAEO,SAASC,IAAa,CACzB,GAAM,CACF,MAAO,CAAE,QAAAC,CAAQ,EACjB,eAAAC,EACA,aAAAC,CACJ,EAAIC,EAAe,EAEb,CACF,gBAAAC,EACA,MAAAC,EACA,aAAAC,EACA,UAAAC,EACA,aAAAC,EACA,OAAAC,EACA,mBAAAC,CACJ,EAAIC,GAAeV,CAAc,EAE3B,CAACW,EAAMC,CAAO,EAAIC,GAAsB,EACxC,CAACC,EAAcC,CAAe,EAAIF,GAAsB,EAGxDG,EAAcb,GAAmBC,GAAS,CAACC,EAK3CY,EAAeC,GACjB,MACIC,EACAC,EAAS,OACTC,EAAsB,CAAC,EACvBC,EAAU,KACT,CACD,GAAI,CACA,IAAMC,EAAkC,CACpC,cAAe,UAAUnB,CAAK,EAClC,EAEMoB,EAA8B,CAChC,OAAAJ,EACA,QAAAG,CACJ,EAEIF,IAAS,OACTE,EAAQ,cAAc,EAAI,mBAC1BC,EAAe,KAAO,KAAK,UAAUH,CAAI,GAG7C,IAAMI,EAAW,MAAM,MAAMN,EAAKK,CAAc,EAEhD,GAAI,CAACC,EAAS,GAAI,CACd,IAAMC,EAAY,MAAMD,EAAS,KAAK,EAClCE,EAAe,sBAAsBF,EAAS,MAAM,IAExD,GAAI,CAKA,GAHAE,EADkB,KAAK,MAAMD,CAAS,EACb,eAAiBC,EAItCF,EAAS,SAAW,KACpBE,EAAa,SAAS,sBAAsB,GAC5CtB,GACA,CAACiB,EACH,CAIE,GAFI,MAAMb,EAAmBJ,CAAY,EAGrC,OAAOY,EAAaE,EAAKC,EAAQC,EAAM,EAAI,EAE3C,MAAM,IAAI,MACNpB,EAAa,2BACjB,CAER,CAGA,GACIwB,EAAS,SAAW,KACpBE,EAAa,SAAS,sBAAsB,GAC5C,CAACtB,EAED,MAAAN,EAAQE,EAAa,qBAAqB,EAC1CO,EAAO,EACD,IAAI,MACN,4CACJ,EAGAmB,EAAa,SAAS,eAAe,IACrCA,EACI1B,EAAa,0BAEzB,MAAQ,CAEJ,GACIwB,EAAS,SAAW,KACpBpB,GACA,CAACiB,GAKD,GAFI,MAAMb,EAAmBJ,CAAY,EAGrC,OAAOY,EAAaE,EAAKC,EAAQC,EAAM,EAAI,UAExCI,EAAS,SAAW,KAAO,CAACpB,EACnC,MAAAN,EAAQE,EAAa,qBAAqB,EAC1CO,EAAO,EACD,IAAI,MACN,4CACJ,EAGJmB,EAAeD,EACT,GAAGC,CAAY,KAAKD,CAAS,GAC7BC,CACV,CAEA,MAAM,IAAI,MAAMA,CAAY,CAChC,CAEA,OAAOF,CACX,OAASG,EAAO,CACZ,cAAQ,MAAM,qBAAsBA,CAAK,EACnCA,CACV,CACJ,EACA,CAACxB,EAAOC,EAAcI,EAAoBV,EAASS,CAAM,CAC7D,EAKMqB,EAAcX,GAAY,SAAY,CACxC,GAAI,CAMA,IAAMY,EAAO,MALI,MAAMb,EACnB,yDACA,OACA,IACJ,GAC4B,KAAK,EACjCL,EAAQ,CACJ,KAAMkB,EAAK,KAAK,aAChB,MAAOA,EAAK,KAChB,CAAC,CACL,OAASF,EAAO,CACZ7B,EAAQ,8BAA+B6B,EAAgB,OAAO,EAAE,CACpE,CACJ,EAAG,CAACX,EAAclB,CAAO,CAAC,EAKpBgC,EAAoBb,GAAY,SAAY,CAC9C,GAAI,CAcA,IAAMc,GADO,MAZI,MAAMf,EACnB,iDACA,OACA,CACI,KAAM,GACN,UAAW,GACX,mBAAoB,GACpB,gBAAiB,GACjB,oCAAqC,EACzC,CACJ,GAE4B,KAAK,GACd,QAAQ,IAAIrB,EAAc,EAE7CmB,EAAgB,CACZ,GAAI,OACJ,KAAM,UACN,SAAU,GACV,SAAUiB,CACd,CAAC,CACL,OAASJ,EAAO,CACZ7B,EAAQ,8BAA+B6B,EAAgB,OAAO,EAAE,CACpE,CACJ,EAAG,CAACX,EAAclB,CAAO,CAAC,EAK1B,OAAAkC,GAAU,IAAM,CACR7B,GAASD,GAAmB,CAACG,IAC3B,SAAY,CACV,GAAI,CACA,MAAMuB,EAAY,EAClB,MAAME,EAAkB,CAC5B,OAASH,EAAO,CACZ,QAAQ,MAAM,mCAAoCA,CAAK,CAC3D,CACJ,GAAG,CAEX,EAAG,CAACxB,EAAOD,EAAiBG,EAAWuB,EAAaE,CAAiB,CAAC,EAE/D,CACH,KAAApB,EACA,aAAAG,EACA,OAAAN,EACA,aAAAD,EACA,MAAAH,EACA,gBAAAD,EACA,UAAAG,EACA,YAAAU,CACJ,CACJ,CG9NA,OAAS,eAAAkB,GAAa,YAAAC,OAAgB,QAStC,IAAMC,GAAkBC,IAA6B,CACjD,GAAIA,EAAM,GACV,KAAMA,EAAM,KACZ,aAAcA,EAAM,aACpB,SAAUA,EAAM,MAAM,IAAM,SAC5B,KAAMA,EAAM,KACZ,cAAe,IACnB,GAQMC,GAAiB,MACnBC,EACAC,IACkB,CAClB,IAAMC,EAAW,MAAM,MACnB,wDACA,CACI,OAAQ,OACR,QAAS,CACL,cAAe,UAAUD,CAAK,GAC9B,eAAgB,kBACpB,EACA,KAAM,KAAK,UAAU,CACjB,KAAMD,EAAK,YACf,CAAC,CACL,CACJ,EAEMG,EAAO,MAAMD,EAAS,KAAK,EACjC,GAAI,CAACA,EAAS,GACV,MAAM,IAAI,MAAMC,EAAK,eAAiB,8BAA8B,EAGxE,OAAOA,EAAK,IAChB,EAEe,SAARC,GAAoCH,EAAgB,CACvD,GAAM,CACF,MAAO,CAAE,QAAAI,EAAS,OAAAC,CAAO,EACzB,iBAAAC,EACA,SAAAC,EACA,aAAAC,CACJ,EAAIC,EAAe,EACb,CAACC,EAAMC,CAAO,EAAIC,GAAwB,CAAC,CAAC,EAC5C,CAACC,EAAeC,CAAgB,EAAIF,GAAwB,CAAC,CAAC,EAC9D,CAACG,EAAYC,CAAa,EAAIJ,GAAS,EAAK,EAC5C,CAACK,EAAkBC,CAAmB,EAAIN,GAAS,CAAC,EACpD,CAACO,EAAgBC,CAAiB,EAAIR,GAAkB,EAAK,EAE7DS,EAAsBC,GACxB,MAAOvB,GAAsB,CACzBqB,EAAkB,EAAI,EACtB,GAAI,CACA,IAAMnB,EAAW,MAAM,MACnB,iDACA,CACI,OAAQ,OACR,QAAS,CACL,cAAe,UAAUD,CAAK,GAC9B,eAAgB,kBACpB,EACA,KAAM,KAAK,UAAU,CACjB,KAAMD,EAAK,aACX,UAAW,GACX,mBAAoB,EACxB,CAAC,CACL,CACJ,EAEMG,EAAO,MAAMD,EAAS,KAAK,EACjC,GAAI,CAACA,EAAS,GACV,MAAM,IAAI,MACNC,EAAK,eAAiB,iCAC1B,EAGJ,IAAMqB,EAAQrB,EAAK,QAAQ,IAAIN,EAAc,EAC7Ce,EAAQa,GAAY,CAChB,GAAGA,EACH,CAAE,GAAGzB,EAAM,SAAUwB,EAAO,SAAU,EAAK,CAC/C,CAAC,CACL,OAASE,EAAO,CACZrB,EAASqB,EAAgB,OAAO,CACpC,QAAE,CACEL,EAAkB,EAAK,CAC3B,CACJ,EACA,CAACpB,EAAOI,CAAO,CACnB,EAOMsB,EAAcJ,GAChB,MAAOvB,GAAsB,CACrBA,EAAK,SACL,MAAMsB,EAAoBtB,CAAI,EAE9Be,EAAiBa,GACMA,EAAU,KAAKC,GAAKA,EAAE,KAAO7B,EAAK,EAAE,EAEjD4B,EAAU,OAAOC,GAAKA,EAAE,KAAO7B,EAAK,EAAE,EACtC,CAAC,GAAG4B,EAAW5B,CAAI,CAC5B,CAET,EACA,CAACsB,CAAmB,CACxB,EAMMQ,EAAeP,GACjB,MAAOvB,EAAmBC,IAAkB,CACxC,GAAI,CACA,IAAM8B,EAAM,MAAMhC,GAAeC,EAAMC,CAAe,EACtD,GAAI,CAAC8B,EAAK,MAAM,IAAI,MAAM,4BAA4B,EAEtD,IAAMC,EAAmB,MAAM,MAAMD,EAAK,CACtC,OAAQ,KACZ,CAAC,EAED,GAAI,CAACC,EAAiB,GAClB,MAAM,IAAI,MACN,uBAAuBA,EAAiB,MAAM,EAClD,EAGJ,IAAMC,EAAO,MAAMD,EAAiB,KAAK,EACzC,OAAO,IAAI,KAAK,CAACC,CAAI,EAAGjC,EAAK,KAAM,CAC/B,KAAMiC,EAAK,MAAQ,0BACvB,CAAC,CACL,OAASP,EAAO,CACZrB,EAASqB,EAAgB,OAAO,EAChC,MACJ,CACJ,EACA,CAACrB,CAAO,CACZ,EAEM6B,EAAgBX,GAClB,MAAOC,EAAsBvB,IAAmB,CAC5C,GAAI,CAACA,EAAO,CACRI,EAAQI,EAAa,oBAAoB,EACzC,MACJ,CACA,IAAM0B,EAAWX,EAAM,IAAI,MAAOxB,EAAMoC,IAAU,CAC9C,IAAMC,EAAiB,MAAMP,EAAa9B,EAAMC,CAAK,EAErD,OAAAkB,EACI,KAAK,OAAQiB,EAAQ,GAAKZ,EAAM,OAAU,GAAG,CACjD,EAEOa,CACX,CAAC,EAED,OAAO,MAAM,QAAQ,IAAIF,CAAQ,CACrC,EACA,CAACL,EAAczB,CAAO,CAC1B,EAMMiC,EAAef,GAAY,SAAY,CAvLjD,IAAAgB,EAAAC,EAwLQ,GAAI1B,EAAc,SAAW,EAE7B,CAAAG,EAAc,EAAI,EAClBE,EAAoB,CAAC,EAErB,GAAI,CACA,IAAMsB,GACFF,EAAA,MAAML,EAAcpB,EAAeb,CAAK,IAAxC,YAAAsC,EACD,OAAO,SAEV/B,EAASiC,CAAyB,EAElC1B,EAAiB,CAAC,CAAC,EACnBR,EAAiB,MAAS,CAC9B,OAASmB,EAAO,CACZrB,EACIqC,EAAEjC,EAAa,qBAAsB,CACjC,SAAU+B,EAAAd,GAAA,YAAAA,EAAiB,UAAjB,KAAAc,EAA4B,EAC1C,CAAC,CACL,CACJ,QAAE,CACEvB,EAAc,EAAK,EACnBE,EAAoB,CAAC,CACzB,EACJ,EAAG,CACCe,EACA7B,EACAS,EACAP,EACAC,EACAP,CACJ,CAAC,EAKK0C,EAAuBpB,GAAY,IAAM,CAC3CR,EAAiB,CAAC,CAAC,EACnBI,EAAoB,CAAC,CACzB,EAAG,CAAC,CAAC,EAECyB,EAAwBrB,GAC1B,MAAOC,GAAyB,CAlOxC,IAAAe,EAAAC,EAmOY,GAAKhB,GAAA,MAAAA,EAAO,OACZ,CAAAP,EAAc,EAAI,EAClBE,EAAoB,CAAC,EACrB,GAAI,CACA,IAAM0B,EAAWrB,EAAM,OAAOK,GAAK,CAC/B,GAAI,CAACvB,GAAUA,IAAW,IAAK,MAAO,GACtC,IAAMwC,EAAMjB,EAAE,KAAK,MAAM,GAAG,EAAE,IAAI,GAAK,GACvC,OAAOvB,EAAO,SAASwC,CAAG,CAC9B,CAAC,EACKL,GACFF,EAAA,MAAML,EAAcW,EAAU5C,CAAK,IAAnC,YAAAsC,EACD,OAAO,SACV/B,EAASiC,CAAyB,EAClC1B,EAAiB,CAAC,CAAC,EACnBR,EAAiB,MAAS,CAC9B,OAASmB,EAAO,CACZrB,EACIqC,EAAEjC,EAAa,qBAAsB,CACjC,SAAU+B,EAAAd,GAAA,YAAAA,EAAiB,UAAjB,KAAAc,EAA4B,EAC1C,CAAC,CACL,CACJ,QAAE,CACEvB,EAAc,EAAK,EACnBE,EAAoB,CAAC,CACzB,EACJ,EACA,CAACb,EAAQ4B,EAAe7B,EAASE,EAAkBC,EAAUP,CAAK,CACtE,EAEM8C,EAAwBxB,GAAY,SAAY,CAhQ1D,IAAAgB,EAiQQ,GAAI,CACA,IAAMS,EAAUrC,EAAKA,EAAK,OAAS,CAAC,EACpC,GAAI,CAACqC,EAAS,OAEd,IAAMC,EAAkB,MAAOC,GAAuB,CAClD,GAAI,CAACjD,EAAO,MAAM,IAAI,MAAM,iBAAiB,EAE7C,IAAMkD,EAAU,MAAM,MAClB,iDACA,CACI,OAAQ,OACR,QAAS,CACL,cAAe,UAAUlD,CAAK,GAC9B,eAAgB,kBACpB,EACA,KAAM,KAAK,UAAU,CACjB,KAAMiD,EACN,UAAW,GACX,mBAAoB,EACxB,CAAC,CACL,CACJ,EACI/C,EAAO,MAAMgD,EAAQ,KAAK,EAC9B,GAAI,CAACA,EAAQ,GACT,MAAM,IAAI,MACNhD,EAAK,eAAiB,wBAC1B,EAEJ,IAAIiD,GAAUjD,EAAK,SAAW,CAAC,EAC/B,KAAOA,EAAK,UAAU,CAClB,IAAMkD,GAAO,MAAM,MACf,0DACA,CACI,OAAQ,OACR,QAAS,CACL,cAAe,UAAUpD,CAAK,GAC9B,eAAgB,kBACpB,EACA,KAAM,KAAK,UAAU,CAAE,OAAQE,EAAK,MAAO,CAAC,CAChD,CACJ,EAEA,GADAA,EAAO,MAAMkD,GAAK,KAAK,EACnB,CAACA,GAAK,GACN,MAAM,IAAI,MACNlD,EAAK,eAAiB,yBAC1B,EACJiD,GAAUA,GAAQ,OAAOjD,EAAK,SAAW,CAAC,CAAC,CAC/C,CAGA,OAAOiD,GACF,IAAIvD,EAAc,EAClB,OAAQyD,IAAmB,CAACA,GAAE,QAAQ,CAC/C,EAEMC,EAAaP,EAAgB,cAAgB,IAC7CxB,EAAQ,MAAMyB,EAAgBM,CAAS,EAC7C,MAAMX,EAAsBpB,CAAK,CACrC,OAASE,EAAO,CACZrB,EACIqC,EAAEjC,EAAa,qBAAsB,CACjC,SAAU8B,EAAAb,GAAA,YAAAA,EAAiB,UAAjB,KAAAa,EAA4B,EAC1C,CAAC,CACL,CACJ,CACJ,EAAG,CAACK,EAAuBvC,EAASM,EAAMV,CAAK,CAAC,EAEhD,MAAO,CACH,KAAAU,EACA,QAAAC,EACA,eAAAQ,EACA,YAAAO,EACA,cAAAb,EACA,WAAAE,EACA,aAAAsB,EACA,iBAAApB,EACA,qBAAAyB,EACA,sBAAAI,CACJ,CACJ,CChVA,OAAS,UAAAS,OAAc,gBAGvB,OAAOC,GAGH,aAAAC,GACA,WAAAC,GACA,YAAAC,OACG,QCCA,IAAMC,GAQT,CACA,uCAAwC,CACpC,eACI,0EACJ,UAAW,OACX,UAAYC,GACR,sCAAsCA,CAAE,qBAChD,EACA,0CAA2C,CACvC,eACI,oEACJ,UAAW,OACX,UAAYA,GACR,0CAA0CA,CAAE,qBACpD,EACA,2CAA4C,CACxC,eACI,4EACJ,UAAW,OACX,UAAYA,GACR,0CAA0CA,CAAE,cACpD,CACJ,EAMO,SAASC,GAAuBC,EAAkB,CACrD,OAAOH,GAAyBG,CAAQ,CAC5C,CAOO,SAASC,GAA2BC,EAA0B,CACjE,IAAMC,EAAaJ,GAAuBG,EAAK,QAAQ,EACvD,OAAIC,EAAmBA,EAAW,WAC1BD,EAAK,KAAK,MAAM,GAAG,EAAE,IAAI,GAAK,IAAI,YAAY,CAC1D,CAeO,SAASE,GAAoBF,EAAkBG,EAAyB,CAC3E,GAAI,CAACA,GAAUA,IAAW,IAAK,MAAO,GAEtC,IAAMC,EAAeL,GAA2BC,CAAI,EAC9CC,EAAaJ,GAAuBG,EAAK,QAAQ,EACjDK,EAAgBJ,EAChBA,EAAW,eACXD,EAAK,UAAY,GAIvB,OAFeG,EAAO,MAAM,GAAG,EAAE,IAAIG,GAAKA,EAAE,KAAK,EAAE,YAAY,CAAC,EAElD,KAAKC,GAAS,CACxB,GAAI,CAACA,EAAO,MAAO,GAGnB,GAAIA,EAAM,SAAS,GAAG,EAAG,CACrB,GAAIA,EAAM,SAAS,IAAI,EAAG,CAEtB,IAAMC,EAAWD,EAAM,MAAM,EAAGA,EAAM,QAAQ,GAAG,CAAC,EAClD,OAAOF,EAAc,YAAY,EAAE,WAAWG,EAAW,GAAG,CAChE,CACA,OAAOH,EAAc,YAAY,IAAME,CAC3C,CAGA,OAAIA,EAAM,WAAW,GAAG,EACbH,IAAiBG,EAAM,MAAM,CAAC,EAIlCH,IAAiBG,CAC5B,CAAC,CACL,CCxGA,OAAOE,MAAyC,QAChD,OAAS,YAAAC,GAAU,UAAAC,OAAc,iBAiBlB,SAARC,GAAoC,CACvC,KAAAC,EACA,QAAAC,EACA,KAAAC,EACA,cAAAC,EACA,WAAAC,EACA,SAAAC,EACA,WAAAC,CACJ,EAAoB,CAChB,GAAM,CACF,iBAAAC,EACA,aAAcC,EACd,MAAO,CAAE,KAAAC,EAAM,WAAAC,CAAW,CAC9B,EAAIC,EAAe,EAEnB,OAAKT,EAGDU,EAAA,cAAC,WACGA,EAAA,cAAC,OACG,UAAWC,EACP,kJACA,CACI,oFACIJ,CACR,EACAC,EAAW,WACf,GAEAE,EAAA,cAACE,EAAA,CAAa,GAAI,CAAC,CAACd,GAChBY,EAAA,cAAC,OAAI,UAAU,0CACTZ,EAAoB,IAAI,CAACe,EAAGC,IAC1BJ,EAAA,cAAC,KACG,IAAKG,EAAE,GACP,UAAWF,EACP,kFACA,CACI,+CACIJ,CACR,CACJ,EACA,MAAO,CACH,SAAU,IAAMT,EAAK,OAAS,IAC9B,cACIgB,IAAMhB,EAAK,OAAS,EAAI,OAAS,MACzC,EACA,QAAS,IACLC,EAASgB,GACLA,EAAK,MAAM,EAAGD,EAAI,CAAC,CACvB,GAGJJ,EAAA,cAAC,QAAK,UAAU,iDACXG,EAAE,IACP,EACAH,EAAA,cAACE,EAAA,CAAa,GAAIE,IAAMhB,EAAK,OAAS,GACjC,IAAI,IACA,GACT,CACJ,CACH,CACL,CACJ,EACAY,EAAA,cAAC,OAAI,UAAU,0CACXA,EAAA,cAAC,OAAI,UAAU,0HACXA,EAAA,cAACE,EAAA,CAAa,GAAI,CAAC,CAACZ,EAAK,SACrBU,EAAA,cAAC,OACG,IAAKV,EAAK,KACV,IAAKA,EAAK,QACV,UAAU,mCACd,CACJ,EACAU,EAAA,cAACE,EAAA,CAAa,GAAI,CAACZ,EAAK,SACpBU,EAAA,cAACM,GAAA,CAAO,UAAU,eAAe,CACrC,CACJ,EAEAN,EAAA,cAAC,UACG,UAAWC,EACP,+CACA,CACI,+CACIJ,CACR,EACAC,EAAW,iBACf,EACA,QAAS,IAAM,CACXP,EAAc,EACdI,EAAiB,MAAS,CAC9B,GAECC,EAAG,MACR,CACJ,CACJ,EAEAI,EAAA,cAACE,EAAA,CAAa,GAAIV,GACdQ,EAAA,cAAC,OACG,UAAWC,EACP,qEACA,CACI,oFACIJ,CACR,EACAC,EAAW,oBACf,GAEAE,EAAA,cAAC,SACG,KAAK,SACL,UAAWC,EACP,kKACA,CACI,oFACIJ,CACR,EACAC,EAAW,gBACf,EACA,YAAaF,EAAG,OAChB,MAAOF,EACP,SAAUa,GAAKd,EAASc,EAAE,cAAc,KAAK,EACjD,EACAP,EAAA,cAACQ,GAAA,CAAS,UAAU,mFAAmF,CAC3G,CACJ,CACJ,EA7Gc,IA+GtB,CClJA,OAAS,UAAAC,OAA+B,gBAGxC,OAAOC,OAAW,QCDlB,OAAOC,OAAkC,QACzC,OAAS,UAAAC,GAAQ,YAAAC,OAAgB,iBAKjC,IAAMC,GAAsD,GAAK,CAC7D,IAAMC,EAAM,0XACZ,EAAE,cAAc,IAAM,6BAA6BC,GAAiBD,CAAG,CAAC,GACxE,EAAE,cAAc,QAAU,IAC9B,EAEe,SAARE,GAAkC,CACrC,KAAAC,CACJ,EAEG,CAlBH,IAAAC,EAmBI,GAAM,CACF,MAAO,CAAE,KAAAC,CAAK,CAClB,EAAIC,EAAe,EACbC,EAAW,GACZJ,EAAsB,UAAaA,EAAoB,UAEtDK,EACF,aAAcL,GAAOC,EAAAD,EAAK,aAAL,YAAAC,EAAiB,MAAM,IAAMD,EAAK,cAE3D,OAAII,EAEIE,GAAA,cAAC,KAAE,UAAU,+BACTA,GAAA,cAACC,GAAA,CACG,UAAWC,EAAG,CACV,+CAAgDN,CACpD,CAAC,EACL,CACJ,EAEHG,EAYDC,GAAA,cAAC,OACG,IAAKD,EACL,IAAKL,EAAK,KACV,UAAU,+DACV,QAASJ,GACb,EAfIU,GAAA,cAAC,KAAE,UAAU,+BACTA,GAAA,cAACG,GAAA,CACG,UAAWD,EAAG,CACV,+CAAgDN,CACpD,CAAC,EACL,CACJ,CAWZ,CCzDA,OAAS,mBAAAQ,OAA6C,gBACtD,OAAOC,OAAuC,QAE9C,IAAMC,GAA2BF,GAWlB,SAARG,GAAmC,CACtC,SAAAC,CACJ,EAAgC,CAC5B,OAAOH,GAAA,cAACC,GAAA,KAA0BE,CAAS,CAC/C,CFAe,SAARC,GAAkC,CACrC,KAAAC,EACA,cAAAC,EACA,YAAAC,EACA,MAAAC,CACJ,EAAoC,CAChC,GAAM,CACF,MAAO,CAAE,KAAAC,EAAM,WAAAC,CAAW,CAC9B,EAAIC,EAAe,EACbC,EAAW,GACZP,EAAsB,UAAaA,EAAoB,UAEtDQ,EAAkBP,EAA6B,OACjDQ,GAAKA,EAAE,KAAOT,EAAK,EACvB,EAAE,OAEIU,EAAyB,CAC3B,KAAM,SACN,QAAS,GACT,UAAW,IACX,QAAS,CAAE,MAAOP,EAAQ,GAAK,EAC/B,EAAG,CAAE,MAAOA,EAAQ,GAAK,CAC7B,EAEA,OACIQ,GAAA,cAACC,GAAA,KACGD,GAAA,cAACE,GAAO,IAAP,CACG,IAAKb,EAAK,GACV,QAAS,CACL,QAAS,EACT,EAAG,EACP,EACA,QAAS,CACL,QAAS,EACT,EAAG,EACH,WAAAU,CACJ,EACA,WAAY,CACR,QAAS,EACT,EAAG,EACH,WAAAA,CACJ,EACA,KAAM,CAAE,QAAS,EAAG,EAAG,GAAI,WAAAA,CAAW,EACtC,WAAYA,EACZ,UAAWI,EACP,oKACA,CACI,mBAAoBP,EACpB,sBAAuBC,EACvB,sBAAuB,CAACA,EACxB,CAACH,EAAW,yBAA0B,EAClC,CAACG,GACDH,EAAW,0BACf,CAACA,EAAW,0BAA2B,EACnCG,GACAH,EAAW,0BACnB,CACJ,EACA,QAAS,IAAMH,EAAYF,CAAW,GAEtCW,GAAA,cAAC,OACG,UAAWG,EACP,yCACAT,EAAW,uBACf,GAEAM,GAAA,cAACI,GAAA,CAAiB,KAAMf,EAAM,EAC9BW,GAAA,cAAC,MACG,UAAWG,EACP,6CACA,CACI,+CACIV,CACR,EACAC,EAAW,kBACf,GAECL,EAAK,IACV,CACJ,CACJ,CACJ,CAER,CH7DA,SAASgB,GAAYC,EAAiCC,EAAgB,CAKlE,MAJiB,GACZD,EAAsB,UAAaA,EAAoB,WAGxD,CAACC,GAAUA,IAAW,IAAY,GAGjB,aAAcD,GAAQ,EAAE,aAAcA,GAEhDE,GAAoBF,EAAoBC,CAAM,EAIlDA,EAAO,SAASD,EAAK,KAAK,MAAM,GAAG,EAAE,IAAI,CAAE,CACtD,CAEe,SAARG,GAA8B,CACjC,eAAAC,EAAiB,GACjB,WAAAC,EACA,KAAAC,EACA,QAAAC,EACA,YAAAC,EACA,cAAAC,EACA,WAAAC,EACA,aAAAC,EACA,qBAAAC,EACA,sBAAAC,EACA,GAAGC,CACP,EAAoB,CArEpB,IAAAC,EAAAC,EAsEI,GAAM,CACF,MAAO,CAAE,OAAAf,EAAQ,KAAAgB,EAAM,WAAAC,CAAW,EAClC,aAAcC,CAClB,EAAIC,EAAe,EACb,CAACC,EAAYC,CAAa,EAAIC,GAAS,EAAE,EACzCC,GAASR,GAAAD,EAAAT,EAAKA,EAAK,OAAS,CAAC,IAApB,YAAAS,EAAuB,WAAvB,YAAAC,EAAgD,OAC3DhB,GAAQD,GAAYC,EAAMC,CAAM,GAE9BwB,EAAiBC,GACnB,IAAMC,GAAsBH,EAAOH,CAAU,GAAK,CAAC,EACnD,CAACA,EAAYG,CAAK,CACtB,EACMI,EAAYxB,GAAkB,CAACC,EAErC,OAAAwB,GAAU,IAAM,CACRxB,GAAYE,EAAQ,CAACF,CAAiB,CAAC,CAC/C,EAAG,CAACA,EAAYE,CAAO,CAAC,EAGpBuB,EAAA,cAACC,GAAA,CAAqB,UAAWH,GAC7BE,EAAA,cAACE,EAAA,CAAa,GAAI,GAAM,UAAWJ,GAC/BE,EAAA,cAAC,OAAI,UAAU,uFACXA,EAAA,cAACG,GAAA,CACG,WAAY,CAAC,EAACT,GAAA,MAAAA,EAAO,QACrB,KAAMlB,EACN,QAASC,EACT,WAAYc,EACZ,SAAUC,EACT,GAAGR,EACR,EACAgB,EAAA,cAACE,EAAA,CAAa,GAAI,CAAC,CAAC1B,GAChBwB,EAAA,cAAC,OACG,UAAWI,EACP,qEACA,CACI,sFACIjB,CACR,EACAC,EAAW,SACf,GAEAY,EAAA,cAACE,EAAA,CAAa,GAAI,CAAC,CAACP,EAAe,QAC/BK,EAAA,cAAC,MAAG,UAAU,YACTL,EAAe,IAAI,CAACU,EAAMC,IAEnBN,EAAA,cAACO,GAAA,CACG,IAAKF,EAAK,GACV,KAAMA,EACN,YACI/B,GAAkBM,EACZ,IAAM,CAAC,EACPF,EAEV,MAAO4B,EACP,cAAe3B,EACnB,CAEP,CACL,CACJ,EACAqB,EAAA,cAACE,EAAA,CAAa,GAAI,CAACP,EAAe,QAC9BK,EAAA,cAAC,OAAI,UAAU,6EACXA,EAAA,cAAC,KAAE,UAAU,gCACRX,EAAG,oBACR,CACJ,CACJ,CACJ,CACJ,EAEAW,EAAA,cAACE,EAAA,CACG,GAAI,CAAC,CAACvB,EAAc,QAAU,CAAC,CAACI,GAEhCiB,EAAA,cAACQ,GAAA,KACGR,EAAA,cAACS,GAAO,IAAP,CACG,IAAI,gBACJ,QAAS,CAAE,EAAG,OAAQ,OAAQ,CAAE,EAChC,QAAS,CAAE,EAAG,KAAM,OAAQ,MAAO,EACnC,KAAM,CAAE,EAAG,OAAQ,OAAQ,CAAE,EAC7B,WAAY,CAAE,SAAU,EAAI,EAC5B,UAAWL,EACP,yHACA,CACI,oFACIjB,CACR,EACAC,EAAW,WACf,GAEAY,EAAA,cAACE,EAAA,CAAa,GAAI,CAAC,CAACnB,GAChBiB,EAAA,cAAC,UACG,UAAWI,EACP,iJACA,CACI,+CACIjB,CACR,CACJ,EACA,QAAS,IACLJ,GAAA,YAAAA,IAEJ,SAAUH,GAETS,EAAG,gBACR,CACJ,EACAW,EAAA,cAAC,UACG,UAAWI,EACP,2IACA,CACI,qBAAsBxB,EACtB,2CACIO,CACR,EACAC,EAAW,mBACf,EACA,QAASP,EACT,SAAUD,GAET8B,EACGC,GACItB,EACA,WACAV,EAAc,MAClB,EACA,CAAE,MAAOA,EAAc,MAAO,CAClC,CACJ,EACAqB,EAAA,cAAC,UACG,UAAWI,EACP,8GACA,CACI,+CACIjB,CACR,EACAC,EAAW,sBACf,EACA,QAASN,EACT,SAAUF,GAETS,EAAG,MACR,CACJ,CACJ,CACJ,CACJ,CACJ,CACJ,CAER,CLtNe,SAARuB,IAAmC,CACtC,GAAM,CACF,KAAAC,EACA,aAAcC,EACd,OAAAC,EACA,MAAAC,EACA,gBAAAC,EACA,aAAAC,EACA,UAAAC,CACJ,EAAIC,GAAW,EAETC,EAAgB,UAClBN,EAAO,EACA,QAAQ,QAAQ,GAG3BO,GAAU,IAAM,CACR,CAACL,GAAmB,CAACD,GAAS,CAACG,GAC/BD,EAAa,CAErB,EAAG,CAACD,EAAiBD,EAAOG,EAAWD,CAAY,CAAC,EAEpD,IAAMK,EAAQC,GAAmBR,CAAK,EAEtC,OACIS,GAAA,cAACC,GAAA,CACG,WAAYZ,EACZ,KAAMD,EACN,cAAeQ,EACd,GAAIE,EACT,CAER,CWrCA,OAAOI,OAAW,QCClB,OAAS,eAAAC,GAAa,aAAAC,GAAW,UAAAC,GAAQ,YAAAC,OAAgB,QCDzD,OAAOC,OAAU,cACjB,OAAS,aAAAC,GAAW,YAAAC,OAAgB,QAMrB,SAARC,IAA+B,CAClC,GAAM,CAACC,EAAWC,CAAY,EAAIH,GAAkB,EAAK,EAEzD,OAAAD,GAAU,IAAM,CAIZD,GAAK,yCAA0C,MAAMM,GAAO,CACnDA,GAAKD,EAAa,EAAI,CAC/B,CAAC,CACL,EAAG,CAACD,CAAS,CAAC,EAKP,CAAE,UAAAA,CAAU,CACvB,CDfA,IAAMG,GAAgBC,GAAoB,EAC3B,SAARC,GACHC,EAAgB,CAAC,EACnB,CACE,GAAM,CAAE,iBAAAC,EAAkB,eAAAC,CAAe,EAAIF,EACvC,CACF,MAAO,CAAE,QAAAG,CAAQ,EACjB,aAAAC,CACJ,EAAIC,EAAe,EACb,CAACC,EAAMC,CAAO,EAAIC,GAAe,EACjC,CAACC,EAAaC,CAAc,EAAIF,GAAe,EAC/C,CAACG,EAAUC,CAAW,EAAIJ,GAAuB,EACjD,CAACK,EAAOC,CAAQ,EAAIN,GAAgB,EACpC,CAACO,EAAeC,CAAgB,EAAIR,GAAS,EAAK,EAClDS,EAAiBC,GAEb,IAAI,EAERC,EAAaC,GACf,MAAOC,GACI,MAAM,MAAMA,EAAK,CACpB,OAAQ,MACR,QAAS,CACL,cAAe,UAAUR,GAAA,YAAAA,EAAO,YAAY,EAChD,CACJ,CAAC,EAEL,CAACA,CAAK,CACV,EAEM,CAAE,UAAAS,CAAU,EAAIC,GAAY,EAO5BC,EAAeJ,GAAY,SAAY,CAIzC,IAAMK,EAAO,MAHI,MAAMN,EACnB,yHAAyHjB,CAAc,EAC3I,GAC4B,KAAK,EACjC,GAAIuB,EAAK,MAAO,CACZtB,EAAQsB,EAAK,KAAK,EAClB,MACJ,CACAb,EAAYa,EAAK,KAAK,CAC1B,EAAG,CAACN,EAAYjB,EAAgBC,CAAO,CAAC,EAMlCuB,EAAcN,GAAY,SAAY,CAIxC,IAAMK,EAAO,MAHI,MAAMN,EACnB,+CACJ,GAC4B,KAAK,EACjCZ,EAAQkB,CAAI,CAChB,EAAG,CAACN,CAAU,CAAC,EAETQ,EAAgB,SAAY,CAG9B9B,GAAc,WAAW,OAAO,EAChCU,EAAQ,MAAS,EACjBG,EAAe,MAAS,CAC5B,EAMMkB,EAAgBR,GAAY,IAAM,CACpC,GAAI,CAACT,EAAU,OAGf,IAAMkB,EAAU,IAAI,IAAIlB,EAAS,IAAImB,GAAKA,EAAE,EAAE,CAAC,EAGzCC,EAA+BpB,EAAS,OAC1CmB,GAAK,EAAEA,EAAE,SAAWD,EAAQ,IAAIC,EAAE,QAAQ,CAAC,CAAC,EAChD,EAGME,EAAyD,CAAC,EAEhErB,EAAS,QAAQsB,GAAQ,CACjBA,EAAK,SACLA,EAAK,QAAQ,QAAQC,GAAY,CACxBF,EAAsBE,CAAQ,IAC/BF,EAAsBE,CAAQ,EAAI,CAAC,GAEvCF,EAAsBE,CAAQ,EAAE,KAAKD,CAAI,CAC7C,CAAC,CAET,CAAC,EAOD,IAAME,EAAWF,GAAqB,CAClC,IAAMG,EAAWJ,EAAsBC,EAAK,EAAE,EAC1CG,GAAYA,EAAS,SACrBH,EAAK,SAAWG,EAChBA,EAAS,QAAQD,CAAO,EAEhC,EAGAJ,EAAe,QAAQI,CAAO,EAE9BzB,EAAe,CACX,GAAI,aACJ,KAAM,QACN,SAAUqB,CACd,CAAC,CACL,EAAG,CAACpB,CAAQ,CAAC,EAEb0B,GAAU,IAAM,CAKZ,IAAMC,EAAiBzC,GAAc,QAAQ,OAAO,EAC9C0C,EAAcD,EAAiB,KAAK,MAAMA,CAAc,EAAI,KAElE,GAAIC,GAAeA,EAAY,WAAa,KAAK,IAAI,EACjD,OAAOzB,EAASyB,CAAW,EAE3BjB,IACE,SAAY,CAEV,IAAMkB,GADS,MAAM,OAAO,QACN,SAAS,OAAO,gBAAgB,CAClD,UAAWvC,EACX,MAAO,kGACP,QAAS,QACT,SAASwC,EAAsB,CAnJnD,IAAAC,EAoJwB,GAAKD,GAAA,MAAAA,EAAe,MAahBtC,EACIwC,EAAEvC,EAAa,oBAAqB,CAChC,QAAS,QAAOsC,EAAAD,GAAA,YAAAA,EAAe,QAAf,KAAAC,EAAwB,EAAE,CAC9C,CAAC,CACL,MAhBA,QAAA1B,EAAiB,EAAK,EACtBnB,GAAc,QACV,QACA,KAAK,UAAU,CACX,GAAG4C,EACH,WACI,KAAK,IAAI,GACRA,EAAc,WAAa,IAAM,GAC1C,CAAC,CACL,EACO3B,EAAS2B,CAAa,CAQrC,EACA,eAAeG,EAA2C,CAEtD5B,EAAiB,EAAI,EACrBb,EACIwC,EAAEvC,EAAa,oBAAqB,CAChC,QAASwC,EAAM,SAAWA,EAAM,IACpC,CAAC,CACL,CACJ,CACJ,CAAC,EACD3B,EAAe,QAAUuB,EACzBA,EAAO,mBAAmB,CAAC,CAAC,CAChC,GAAG,CAEX,EAAG,CAAClB,EAAWrB,EAAkBE,CAAO,CAAC,EAKzCkC,GAAU,IAAM,CACRxB,IACE,UACE,MAAMa,EAAY,EAClB,MAAMF,EAAa,KAG/B,EAAG,CAACA,EAAcE,EAAab,CAAK,CAAC,EAKrCwB,GAAU,IAAM,CACZT,EAAc,CAClB,EAAG,CAACA,CAAa,CAAC,EAKlB,IAAMiB,EAAYzB,GAAY,IAAM,CA9MxC,IAAAsB,EA+MQ1B,EAAiB,EAAK,GACtB0B,EAAAzB,EAAe,UAAf,MAAAyB,EAAwB,mBAAmB,CAAC,EAChD,EAAG,CAAC,CAAC,EAEL,MAAO,CAAE,KAAApC,EAAM,YAAAG,EAAa,cAAAkB,EAAe,MAAAd,EAAO,cAAAE,EAAe,UAAA8B,CAAU,CAC/E,CEnNA,OAAS,YAAAC,OAAgB,QAQzB,SAASC,GAA0BC,EAAyBC,EAAkB,CAC1E,OAAOD,EAAU,SAASC,CAAI,EACxBD,EAAU,OAAOE,GAAKA,EAAE,KAAOD,EAAK,EAAE,EACtC,CAAC,GAAGD,EAAWC,CAAI,CAC7B,CAEe,SAARE,GAAwCC,EAAe,CAC1D,GAAM,CACF,MAAO,CAAE,QAAAC,EAAS,OAAAC,CAAO,EACzB,mBAAAC,EACA,iBAAAC,EACA,SAAAC,EACA,aAAAC,CACJ,EAAIC,EAAe,EACb,CAACC,EAAMC,CAAO,EAAIC,GAAiB,CAAC,CAAC,EACrC,CAACC,EAAeC,CAAgB,EAAIF,GAAuB,CAAC,CAAC,EAC7D,CAACG,EAAYC,CAAa,EAAIJ,GAAS,EAAK,EAC5C,CAACK,EAAkBC,CAAmB,EAAIN,GAAS,CAAC,EAEpDO,EAAepB,GAA4B,CACzC,aAAcA,EAAMY,EAAQS,GAAY,CAAC,GAAGA,EAAUrB,CAAY,CAAC,EAEnEe,EAAiBhB,GACbD,GAA0BC,EAAWC,CAAI,CAC7C,CACR,EAEMsB,EAAgB,MAAOC,GAAwB,CACjD,IAAMC,EAAWD,EAAM,IAAI,MAAOvB,EAAMyB,IAAU,CAC9C,IAAMC,EAAiB,MAAMC,EAAa3B,CAAI,EAE9C,OAAI0B,IACCA,EAAyC,cACtC1B,EAAK,eAEbmB,EAAoB,KAAK,OAAQM,EAAQ,GAAKF,EAAM,OAAU,GAAG,CAAC,EAE3DG,CACX,CAAC,EAED,OAAO,MAAM,QAAQ,IAAIF,CAAQ,CACrC,EAEMG,EAAe,MAAO3B,GAAqB,CAC7C,GAAI,CACA,IAAM4B,EAAaC,GAAuB7B,EAAK,QAAQ,EACnD8B,EACAC,EACAC,EAEAJ,GAGAE,EAAMF,EAAW,UAAU5B,EAAK,EAAE,EAClC+B,EAAW/B,EAAK,KAAK,SAAS,IAAI4B,EAAW,SAAS,EAAE,EAClD5B,EAAK,KACL,GAAGA,EAAK,IAAI,IAAI4B,EAAW,SAAS,GAC1CI,EAAWJ,EAAW,iBAGtBE,EAAM,6CAA6C9B,EAAK,EAAE,QAAQM,GAAA,YAAAA,EAAoB,cAAc,aACpGyB,EAAW/B,EAAK,KAChBgC,EAAWhC,EAAK,UAAY,4BAGhC,IAAMiC,EAAW,MAAM,MAAMH,EAAK,CAC9B,QAAS,CACL,cAAe,UAAU3B,GAAA,YAAAA,EAAO,YAAY,EAChD,CACJ,CAAC,EAED,GAAI,CAAC8B,EAAS,GAAI,CACd,IAAMC,EAAO,MAAMD,EAAS,KAAK,EAAE,MAAM,IAAM,EAAE,EACjD,MAAM,IAAI,MACN,uBAAuBA,EAAS,MAAM,GAClCC,EAAO,MAAMA,CAAI,GAAK,EAC1B,EACJ,CACJ,CAEA,IAAMC,EAAO,MAAMF,EAAS,KAAK,EACjC,OAAO,IAAI,KAAK,CAACE,CAAI,EAAGJ,EAAU,CAAE,KAAMC,CAAS,CAAC,CACxD,OAASI,EAAO,CACZhC,EAASgC,GAAA,YAAAA,EAAiB,OAAO,EACjC,MACJ,CACJ,EAEMC,EAAe,SAAY,CAjGrC,IAAAC,EAkGQ,GAAIxB,EAAc,SAAW,EAE7B,CAAAG,EAAc,EAAI,EAClBE,EAAoB,CAAC,EAErB,GAAI,CACA,IAAMoB,GAAmB,MAAMjB,EAAcR,CAAa,GAAG,OACzD,OACJ,EAGAN,EAAS+B,CAAyB,EAGlCxB,EAAiB,CAAC,CAAC,EACnBR,EAAiB,MAAS,CAC9B,OAAS6B,EAAO,CACZhC,EACIoC,EAAE/B,EAAa,qBAAsB,CACjC,SAAU6B,EAAAF,GAAA,YAAAA,EAAiB,UAAjB,KAAAE,EAA4B,EAC1C,CAAC,CACL,CACJ,QAAE,CACErB,EAAc,EAAK,EACnBE,EAAoB,CAAC,CACzB,EACJ,EAEMsB,EAAc,MAAOlB,GAAwB,CA9HvD,IAAAe,EA+HQ,GAAKf,GAAA,MAAAA,EAAO,OACZ,CAAAN,EAAc,EAAI,EAClBE,EAAoB,CAAC,EACrB,GAAI,CACA,IAAMuB,EAAWnB,EAAM,OAAOtB,GAAK0C,GAAoB1C,EAAGI,CAAM,CAAC,EAC3DkC,GAAmB,MAAMjB,EAAcoB,CAAQ,GAAG,OACpD,OACJ,EACAlC,EAAS+B,CAAyB,EAClCxB,EAAiB,CAAC,CAAC,EACnBR,EAAiB,MAAS,CAC9B,OAAS6B,EAAO,CACZhC,EACIoC,EAAE/B,EAAa,qBAAsB,CACjC,SAAU6B,EAAAF,GAAA,YAAAA,EAAiB,UAAjB,KAAAE,EAA4B,EAC1C,CAAC,CACL,CACJ,QAAE,CACErB,EAAc,EAAK,EACnBE,EAAoB,CAAC,CACzB,EACJ,EA8BA,MAAO,CACH,KAAAR,EACA,QAAAC,EACA,YAAAQ,EACA,cAAAN,EACA,WAAAE,EACA,aAAAqB,EACA,iBAAAnB,EACA,qBApCyB,IAAM,CAC/BH,EAAiB,CAAC,CAAC,EACnBI,EAAoB,CAAC,CACzB,EAkCI,sBAhC0B,SAAY,CA3J9C,IAAAmB,EA4JQ,GAAI,CACA,IAAMM,EAAUjC,EAAKA,EAAK,OAAS,CAAC,EACpC,GAAI,CAACiC,EAAS,OAEd,IAAMrB,EAAsB,CAAC,EACvBsB,EAAQC,GAA4B,CAClC,aAAcA,GAAQ,MAAM,QAAQA,EAAK,QAAQ,EACjDA,EAAK,SAAS,QAAQC,GAASF,EAAKE,CAAY,CAAC,EAChDxB,EAAM,KAAKuB,CAAkB,CACtC,EACAD,EAAKD,CAAc,EAEnB,MAAMH,EAAYlB,CAAK,CAC3B,OAASa,EAAO,CACZhC,EACIoC,EAAE/B,EAAa,qBAAsB,CACjC,SAAU6B,EAAAF,GAAA,YAAAA,EAAiB,UAAjB,KAAAE,EAA4B,EAC1C,CAAC,CACL,CACJ,CACJ,CAYA,CACJ,CC7LA,OAAOU,OAAW,QAUH,SAARC,GAAmC,CACtC,aAAAC,EACA,QAAAC,CACJ,EAAoB,CAChB,GAAM,CACF,MAAO,CAAE,KAAAC,EAAM,WAAAC,CAAW,CAC9B,EAAIC,EAAe,EAEnB,OACIC,GAAA,cAACC,GAAA,KACGD,GAAA,cAAC,OAAI,UAAU,8HACXA,GAAA,cAAC,KACG,UAAWE,EACP,gCACA,CACI,+CACIL,CACR,EACAC,EAAW,WACf,GACH,qBACsBH,EAAa,6BACpC,EACAK,GAAA,cAAC,UACG,KAAK,SACL,UAAWE,EACP,kKACA,CACI,gGACIL,CACR,CACJ,EACA,QAASD,GACZ,gBACiBD,CAClB,CACJ,CACJ,CAER,CJzCe,SAARQ,IAAuC,CAC1C,GAAM,CAAE,mBAAAC,CAAmB,EAAIC,EAAe,EACxC,CACF,KAAAC,EACA,YAAaC,EACb,cAAAC,EACA,MAAAC,EACA,cAAAC,EACA,UAAAC,CACJ,EAAIC,GAAeR,CAAkB,EAC/BS,EAAQC,GAAuBL,CAAK,EAE1C,OAAIC,GAAiB,CAACD,EAEdM,GAAA,cAACC,GAAA,CACG,aAAa,eACb,QAASL,EACb,EAKJI,GAAA,cAACE,GAAA,CACG,WAAYV,EACZ,KAAMD,EACN,cAAeE,EACd,GAAGK,EACR,CAER,CKrCA,OAAOK,MAAW,QAEX,IAAMC,GAAe,IACxBD,EAAA,cAAC,OACG,cAAY,OACZ,UAAU,QACV,MAAM,KACN,OAAO,KACP,QAAQ,YACR,UAAU,uBAEVA,EAAA,cAAC,QACG,EAAE,4aACF,KAAK,eACL,SAAS,UACb,CACJ,EAmBG,IAAME,GAAc,IACvBC,EAAA,cAAC,OACG,UAAU,sBACV,cAAY,OACZ,UAAU,QACV,MAAM,KACN,OAAO,KACP,QAAQ,aAERA,EAAA,cAAC,QACG,EAAE,8MACF,KAAK,eACL,SAAS,UACZ,CACL,EAwBG,IAAMC,GAAkB,IAC3BC,EAAA,cAAC,OACG,cAAY,OACZ,UAAU,QACV,MAAM,KACN,OAAO,KACP,QAAQ,aAERA,EAAA,cAAC,KAAE,SAAS,UAAU,KAAK,QACvBA,EAAA,cAAC,QACG,EAAE,mGACF,KAAK,UACT,EACAA,EAAA,cAAC,QACG,EAAE,oGACF,KAAK,UACT,EACAA,EAAA,cAAC,QACG,EAAE,2HACF,KAAK,UACT,EACAA,EAAA,cAAC,QACG,EAAE,4FACF,KAAK,UACT,EACAA,EAAA,cAAC,QACG,EAAE,0GACF,KAAK,UACT,EACAA,EAAA,cAAC,QACG,EAAE,wHACF,KAAK,UACT,CACJ,CACJ,EAiCG,IAAMC,GAAe,IACxBC,EAAA,cAAC,OACG,cAAY,OACZ,UAAU,QACV,MAAM,KACN,OAAO,KACP,QAAQ,aAERA,EAAA,cAAC,KAAE,KAAK,OAAO,SAAS,WACpBA,EAAA,cAAC,QACG,EAAE,0JACF,KAAK,UACR,EACDA,EAAA,cAAC,QACG,EAAE,kKACF,KAAK,UACR,EACDA,EAAA,cAAC,QACG,EAAE,yJACF,KAAK,UACR,EACDA,EAAA,cAAC,QACG,EAAE,qKACF,KAAK,UACR,CACL,CACJ,EAkBG,IAAMC,GAAW,IACpBC,EAAA,cAAC,OACG,cAAY,OACZ,UAAU,QACV,MAAM,KACN,OAAO,KACP,QAAQ,aAERA,EAAA,cAAC,QACG,EAAE,k3BACF,KAAK,UACL,SAAS,UACZ,CACL,EAGSC,GAAa,IACtBD,EAAA,cAAC,OACG,cAAY,OACZ,UAAU,QACV,MAAM,KACN,OAAO,KACP,QAAQ,aAERA,EAAA,cAAC,QACG,EAAE,4cACF,KAAK,UACL,SAAS,UACZ,CACL,ECrNJ,OAAOE,OAAW,QCAlB,OAAS,mBAAAC,OAAuB,sBAChC,OAAS,UAAAC,OAAc,oCACvB,OAAS,6CAAAC,OAAiD,+EAE1D,OAAS,aAAAC,GAAW,YAAAC,OAAgB,QCEpC,OAGI,eAAAC,GACA,aAAAC,GACA,YAAAC,OACG,QAWP,IAAMC,GAAgBC,GAAoB,EAE3B,SAARC,GAAiC,CACpC,aAAAC,EACA,QAAAC,EACA,iBAAAC,CACJ,EAAU,CACN,GAAM,CACF,MAAO,CAAE,QAAAC,CAAQ,EACjB,aAAAC,CACJ,EAAIC,EAAe,EACb,CAACC,EAAOC,CAAQ,EAAIC,GAAyB,EAC7C,CAACC,EAAeC,CAAgB,EAAIF,GAAS,EAAK,EAClD,CAACG,EAAkBC,CAAmB,EAAIJ,GAAS,EAAK,EACxD,CAACK,EAAkBC,CAAmB,EAAIN,GAAS,EAAK,EACxD,CAACO,EAAeC,CAAgB,EAAIR,GAAS,EAAK,EAGxDS,GAAU,IAAM,EACO,SAAY,CA1CvC,IAAAC,EAAAC,EA2CY,GAAI,GAACnB,GAAgBS,GAErB,GAAI,CACA,MAAMT,EAAa,WAAW,EAC9BU,EAAiB,EAAI,EAGrB,IAAMU,EAAWpB,EAAa,eAAe,EAC7C,GAAIoB,EAAS,OAAS,EAClB,GAAI,CACA,IAAMC,EAAgB,CAClB,OAAQ,CACJ,YACA,sBACA,gBACJ,EACA,QAASD,EAAS,CAAC,CACvB,EACME,EACF,MAAMtB,EAAa,mBAAmBqB,CAAa,EACnDC,GACAf,EAAS,CACL,OAAQe,EAAS,YACjB,UAAWA,EAAS,UAAW,QAAQ,CAC3C,CAAC,CACT,OAASC,EAAO,CACZpB,EACIqB,EAAEpB,EAAa,6BAA8B,CACzC,SAAUc,EAAAK,GAAA,YAAAA,EAAiB,UAAjB,KAAAL,EAA4B,EAC1C,CAAC,CACL,CACJ,CAER,OAASK,EAAO,CACZpB,EACIqB,EAAEpB,EAAa,yBAA0B,CACrC,SAAUe,EAAAI,GAAA,YAAAA,EAAiB,UAAjB,KAAAJ,EAA4B,EAC1C,CAAC,CACL,EACAT,EAAiB,EAAK,CAC1B,CACJ,GAEW,CACf,EAAG,CAACD,EAAeT,EAAcG,CAAO,CAAC,EAEzC,IAAMsB,EACFC,GAAY,SAAkD,CA1FtE,IAAAR,EAAAC,EA2FY,GACI,CAACnB,GACD,CAACS,GACDE,GACAE,EAEA,OAAO,KAEX,IAAMc,EAA6B,CAC/B,OAAQ,CAAC,YAAa,sBAAuB,gBAAgB,EAC7D,OAAQ,gBACZ,EAEA,GAAI,CACAb,EAAoB,EAAI,EACxBF,EAAoB,EAAI,EAExB,IAAMQ,EAAWpB,EAAa,eAAe,EAC7C,GAAIoB,EAAS,OAAS,EAClB,GAAI,CAEA,OAAO,MAAMpB,EAAa,mBAAmB,CACzC,GAAG2B,EACH,QAASP,EAAS,CAAC,CACvB,CAAC,CACL,OAASG,EAAO,CACZpB,EACIqB,EAAEpB,EAAa,iCAAkC,CAC7C,SAAUc,EAAAK,GAAA,YAAAA,EAAiB,UAAjB,KAAAL,EAA4B,EAC1C,CAAC,CACL,CACJ,CAIJ,IAAMU,EACF,MAAM5B,EAAa,WAAW2B,CAAY,EAE9C,OAAIC,EACO,MAAM5B,EAAa,mBAAmB,CACzC,GAAG2B,EACH,QAASC,EAAc,OAC3B,CAAC,EAEE,IACX,OAASL,EAAO,CACZ,OAAApB,EACIqB,EAAEpB,EAAa,aAAc,CACzB,SAAUe,EAAAI,GAAA,YAAAA,EAAiB,UAAjB,KAAAJ,EAA4B,EAC1C,CAAC,CACL,EACO,IACX,QAAE,CACEP,EAAoB,EAAK,EACzBE,EAAoB,EAAK,CAC7B,CACJ,EAAG,CACCd,EACAS,EACAE,EACAE,EACAV,CACJ,CAAC,EAEC0B,EAAeH,GAAY,SAAY,CA3JjD,IAAAR,EA4JQ,GAAI,GAACT,GAAiBE,GAAoBE,GAE1C,GAAI,CACA,IAAMS,EAAW,MAAMG,EAAO,EAC9B,GAAIH,EAAU,CACV,IAAMQ,EAA2B,CAC7B,OAAQR,EAAS,YACjB,UAAWA,EAAS,UAAW,QAAQ,CAC3C,EACAf,EAASuB,CAAQ,EACjBd,EAAiB,EAAK,EACtBnB,GAAc,QAAQ,kBAAmB,MAAM,CACnD,MAEImB,EAAiB,EAAI,CAE7B,OAASO,EAAO,CACZpB,EACIqB,EAAEpB,EAAa,mBAAoB,CAC/B,SAAUc,EAAAK,GAAA,YAAAA,EAAiB,UAAjB,KAAAL,EAA4B,EAC1C,CAAC,CACL,EACAF,EAAiB,EAAI,EACrBT,EAAS,MAAS,EAClBV,GAAc,WAAW,iBAAiB,CAC9C,CACJ,EAAG,CAACY,EAAeE,EAAkBE,EAAkBY,EAAQtB,CAAO,CAAC,EAEjE4B,EAAgBL,GAAY,SAAY,CAxLlD,IAAAR,EAyLQ,GAAI,GAAClB,GAAgB,CAACS,GAAiBI,GAEvC,GAAI,CACAC,EAAoB,EAAI,EACxB,IAAMM,EAAWpB,EAAa,eAAe,EAEzCoB,EAAS,OAAS,GAElB,MAAMpB,EAAa,YAAY,CAC3B,QAASoB,EAAS,CAAC,EACnB,sBAAuB,OAAO,SAAS,MAC3C,CAAC,EAILb,EAAS,MAAS,EAClBN,EAAQ,MAAS,EACjBC,EAAiB,MAAS,EAG1BF,EAAa,WAAW,EAGxBH,GAAc,QAAQ,eAAgB,MAAM,EAG5CA,GAAc,WAAW,iBAAiB,CAC9C,OAAS0B,EAAO,CACZpB,EACIqB,EAAEpB,EAAa,cAAe,CAC1B,SAAUc,EAAAK,GAAA,YAAAA,EAAiB,UAAjB,KAAAL,EAA4B,EAC1C,CAAC,CACL,CACJ,QAAE,CACEJ,EAAoB,EAAK,EAEzB,WAAW,IAAMjB,GAAc,WAAW,cAAc,EAAG,GAAI,CACnE,CACJ,EAAG,CACCG,EACAS,EACAI,EACAZ,EACAC,EACAC,CACJ,CAAC,EAGDc,GAAU,IAAM,CACZ,GAAI,CAACR,GAAiBE,GAAoBE,GAAoBP,EAC1D,OAEJ,IAAI0B,EAgBJ,OAdkB,SAAY,CAE1B,IAAMC,EAAuBpC,GAAc,QAAQ,cAAc,EAC3DqC,EAAkBrC,GAAc,QAAQ,iBAAiB,EAE/D,GAAIoC,GAAwBC,EAAiB,SAE5BlC,GAAA,YAAAA,EAAc,mBAAoB,CAAC,GACvC,SAAW,IACpBgC,EAAmB,WAAW,IAAM,CAChCH,EAAa,CACjB,EAAG,GAAI,EACf,GAEU,EAEH,IAAM,CACLG,GAAkB,aAAaA,CAAgB,CACvD,CACJ,EAAG,CACCvB,EACAE,EACAE,EACAP,EACAuB,EACA7B,CACJ,CAAC,EAED,IAAMmC,EAAYT,GAAY,IAAM,CAChCV,EAAiB,EAAK,EACtBa,EAAa,CACjB,EAAG,CAACA,CAAY,CAAC,EAEjB,MAAO,CACH,MAAAvB,EACA,QAASyB,EACT,cAAAtB,EACA,iBAAAE,EACA,cAAAI,EACA,UAAAoB,CACJ,CACJ,CCxRA,OAAS,2BAAAC,OAA+B,sBACxC,OAAS,aAAAC,GAAW,YAAAC,OAAgB,QAGpC,IAAMC,GAAkBC,GAAqB,CACzC,GAAM,CACF,MAAO,CAAE,QAAAC,CAAQ,EACjB,aAAAC,CACJ,EAAIC,EAAe,EACb,CAACC,EAAcC,CAAe,EAAIC,GAAkC,EACpE,CAACC,EAAgBC,CAAiB,EAAIF,GAAS,EAAI,EAEzD,OAAAG,GAAU,IAAM,CACZ,IAAIC,EAAU,GAsCd,OAAKN,IApCkB,SAAY,CAC/B,GAAI,CAACJ,EAAU,CACXQ,EAAkB,EAAK,EACvBP,EAAQC,EAAa,gBAAgB,EACrC,MACJ,CAEA,GAAI,CACA,IAAMS,EAAW,IAAIC,GAAwB,CACzC,KAAM,CACF,SAAAZ,EACA,UAAW,2CACX,YAAa,OAAO,SAAS,OAC7B,0BAA2B,EAC/B,EACA,MAAO,CACH,cAAe,iBACf,uBAAwB,EAC5B,EACA,OAAQ,CACJ,sBAAuB,GACvB,kBAAmB,IACnB,kBAAmB,IACnB,iBAAkB,IAClB,YAAa,EACjB,CACJ,CAAC,EAEGU,GAASL,EAAgBM,CAAQ,CACzC,OAASE,EAAO,CACZZ,EAASY,EAAgB,OAAO,CACpC,QAAE,CACMH,GAASF,EAAkB,EAAK,CACxC,CACJ,GAEkC,EAE3B,IAAM,CACTE,EAAU,EACd,CACJ,EAAG,CAACV,EAAUI,EAAcH,CAAO,CAAC,EAE7B,CACH,aAAAG,EACA,eAAAG,CACJ,CACJ,EAEOO,GAAQf,GFvDA,SAARgB,GAA6BC,EAAW,GAAI,CAC/C,GAAM,CACF,MAAO,CAAE,QAAAC,CAAQ,CACrB,EAAIC,EAAe,EACb,CAACC,EAAMC,CAAO,EAAIC,GAAwB,EAC1C,CAACC,EAAeC,CAAgB,EAAIF,GAAuB,EAC3D,CAACG,EAAaC,CAAc,EAAIJ,GAAiB,EACjD,CAAE,aAAAK,CAAa,EAAIC,GAAeX,CAAQ,EAC1C,CACF,MAAAY,EACA,QAAAC,EACA,cAAAC,EACA,iBAAAC,EACA,cAAAC,EACA,UAAAC,CACJ,EAAIC,GAAgB,CAChB,aAAAR,EACA,QAAAN,EACA,iBAAAG,CACJ,CAAC,EAGD,OAAAY,GAAU,IAAM,CAEZ,GAAI,EADYP,GAASE,GAAiB,CAACC,IAC3B,CAACL,EAAc,CAC3BD,EAAe,MAAS,EACxB,MACJ,CAEA,GAAI,CACA,IAAMW,EAAWV,EAAa,eAAe,EAC7C,GAAIU,EAAS,SAAW,EAAG,MAAM,IAAI,MAAM,mBAAmB,EAE9D,IAAMC,EAAe,IAAIC,GACrBZ,EACA,CACI,QAASU,EAAS,CAAC,EACnB,OAAQ,CACJ,YACA,iBACA,qBACJ,EACA,gBAAiBG,GAAgB,KACrC,CACJ,EAEMC,EAASC,GAAO,mBAAmB,CACrC,aAAAJ,CACJ,CAAC,EAEDZ,EAAee,CAAM,CACzB,OAASE,EAAO,CACZzB,EACI,oCAAqCyB,GAAA,YAAAA,EAAiB,OAAO,EACjE,EACAjB,EAAe,MAAS,CAC5B,CACJ,EAAG,CAACC,EAAcE,EAAOE,EAAeC,EAAkBd,CAAO,CAAC,EAGlEkB,GAAU,IAAM,CACZ,GAAI,CAACX,EAAa,QAEC,SAAY,CAC3B,GAAI,CACA,IAAMmB,EAAU,MAAMnB,EAAY,IAAI,KAAK,EAAE,IAAI,EACjDJ,EAAQ,CAAE,KAAMuB,EAAQ,YAAa,KAAMA,EAAQ,IAAK,CAAC,EAUzD,IAAMC,GARgB,MAAMpB,EACvB,IAAI,yBAAyB,EAC7B,OACG,6DACJ,EACC,OAAO,YAAY,EACnB,IAAI,GAEmB,MAAM,IAAKqB,GAAW,CArFlE,IAAAC,EAqFsE,OAClD,GAAID,EAAK,GACT,KAAMA,EAAK,KACX,SAAU,CAAC,CAACA,EAAK,OACjB,SAAUA,EAAK,OAAS,CAAC,EAAI,OAC7B,aAAYC,EAAAD,EAAK,aAAL,YAAAC,EAAkB,KAAM,KACpC,+BACID,EAAK,8BAA8B,EACvC,KAAMA,EAAK,IACf,EAAE,EAEFtB,EAAiB,CACb,GAAI,OACJ,KAAM,WACN,SAAU,GACV,SAAUqB,CACd,CAAC,CACL,OAASF,EAAO,CACZzB,EACI,wCACKyB,GAAA,YAAAA,EAAiB,QAC1B,CACJ,CACJ,GAEW,CACf,EAAG,CAAClB,EAAaP,CAAO,CAAC,EAElB,CACH,KAAAE,EACA,cAAAG,EACA,QAAAO,EACA,YAAAL,EACA,MAAAI,EACA,cAAAI,EACA,UAAAC,CACJ,CACJ,CGxHA,OAAS,YAAAc,OAAgB,QAIzB,IAAMC,GAAkBC,GAAW,CANnC,IAAAC,EAMuC,OACnC,GAAID,EAAK,GACT,KAAMA,EAAK,KACX,SAAU,CAAC,CAACA,EAAK,OACjB,SAAUA,EAAK,OAAS,CAAC,EAAI,OAC7B,aAAYC,EAAAD,EAAK,aAAL,YAAAC,EAAkB,KAAM,KACpC,+BAAgCD,EAAK,8BAA8B,EACnE,KAAMA,EAAK,IACf,GAEME,GAAiB,MAAOC,EAAoBC,IAAwB,CAEtE,IAAMC,EAAW,MAAMD,EAClB,IAAI,mBAAmBD,EAAK,EAAE,EAAE,EAChC,OAAO,8BAA8B,EACrC,IAAI,EAET,GAAIE,EAAS,8BAA8B,EACvC,OAAOA,EAAS,8BAA8B,EAUlD,IAAMC,GAPa,MAAMF,EACpB,IAAI,mBAAmBD,EAAK,EAAE,aAAa,EAC3C,KAAK,CACF,KAAM,OACN,MAAO,WACX,CAAC,GAEsB,KAAK,OAAO,MAAM,MAAM,EAAE,CAAC,EAMtD,OALmB,MAAMC,EACpB,IAAI,aAAaE,CAAO,EAAE,EAC1B,OAAO,WAAW,EAClB,IAAI,GAES,UAAU,8BAA8B,CAC9D,EAEe,SAARC,GAAqCH,EAAsB,CAC9D,GAAM,CACF,SAAAI,EACA,iBAAAC,EACA,MAAO,CAAE,QAAAC,EAAS,OAAAC,CAAO,EACzB,aAAAC,CACJ,EAAIC,EAAe,EACb,CAACC,EAAgBC,CAAiB,EAAIC,GAAkB,EACxD,CAACC,EAAMC,CAAO,EAAIF,GAAyB,CAAC,CAAC,EAC7C,CAACG,EAAeC,CAAgB,EAAIJ,GAAyB,CAAC,CAAC,EAC/D,CAACK,EAAYC,CAAa,EAAIN,GAAS,EAAK,EAC5C,CAACO,EAAkBC,CAAmB,EAAIR,GAAS,CAAC,EAEpDS,EAAsB,MAAOtB,GAAuB,CAxD9D,IAAAF,EAyDQc,EAAkB,EAAI,EACtB,GAAI,CASA,IAAMW,GARW,MAAMtB,GAAA,YAAAA,EACjB,IAAI,mBAAmBD,EAAK,EAAE,aAC/B,OACG,+DAEH,OAAO,cACP,QAEkB,MAAM,IAAIJ,EAAc,EAC/CmB,EAAQS,GAAY,CAAC,GAAGA,EAAU,CAAE,GAAGxB,EAAM,SAAUuB,CAAM,CAAC,CAAC,CACnE,OAASE,EAAO,CACZlB,EACImB,EAAEjB,EAAa,qBAAsB,CACjC,SAAUX,EAAA2B,GAAA,YAAAA,EAAiB,UAAjB,KAAA3B,EAA4B,EAC1C,CAAC,CACL,CACJ,QAAE,CACEc,EAAkB,EAAK,CAC3B,CACJ,EAEMe,EAAgB,MAAOC,IACR,MAAM3B,GAAA,YAAAA,EACjB,IAAI,mBAAmB2B,CAAQ,aAChC,OACG,+DAEH,OAAO,cACP,QACW,MAAM,IAAIhC,EAAc,EAGtCiC,EAAyB,MAAOC,GAAyB,CAC3D,IAAMP,EAAwB,CAAC,EACzBQ,EAAkB,CAACD,CAAY,EACrC,KAAOC,EAAM,QAAQ,CACjB,IAAMH,EAAWG,EAAM,MAAM,EACvBC,EAAW,MAAML,EAAcC,CAAQ,EAC7C,QAAWK,KAASD,EACZC,EAAM,SAAUF,EAAM,KAAKE,EAAM,EAAE,EAClCV,EAAM,KAAKU,CAAK,CAE7B,CACA,OAAOV,CACX,EAEMW,EAAc,MAAOlC,GAAuB,CAC9C,GAAI,CAACC,EAAa,CACdM,EAAQE,EAAa,yBAAyB,EAC9C,MACJ,CAEIT,EAAK,SAAU,MAAMsB,EAAoBtB,CAAI,EAE7CiB,EAAiBkB,GACIA,EAAU,OAAOC,GAAKA,EAAE,KAAOpC,EAAK,EAAE,EAAE,OACnDmC,EAAU,OAAOC,GAAKA,EAAE,KAAOpC,EAAK,EAAE,EACtC,CAAC,GAAGmC,EAAWnC,CAAI,CAE5B,CACT,EAEMqC,EAAgB,MAAOd,GAA0B,CACnD,IAAMe,EAAWf,EAAM,IAAI,MAAOvB,EAAMuC,IAAU,CA1H1D,IAAAzC,EAAA0C,GA2HY,IAAMC,EAAiB,MAAMC,EAAa1C,CAAI,EAG9C,OAAIwC,IAAA1C,EAAAE,EAAK,aAAL,YAAAF,EAAiB,QAAjB,MAAA0C,GAAwB,KACxB,OAAO,eAAeC,EAAgB,gBAAiB,CACnD,MAAOzC,EAAK,WAAW,MAAM,IAC7B,SAAU,GACV,WAAY,GACZ,aAAc,EAClB,CAAC,EAGLqB,EAAoB,KAAK,OAAQkB,EAAQ,GAAKhB,EAAM,OAAU,GAAG,CAAC,EAE3DkB,CACX,CAAC,EAED,OAAO,MAAM,QAAQ,IAAIH,CAAQ,CACrC,EAEMI,EAAe,MAAO1C,GAAuB,CA/IvD,IAAAF,EAAA0C,EAgJQ,GAAI,CACA,IAAMG,EAAM,MAAM5C,GAAeC,EAAMC,CAAY,EACnD,GAAI,CAAC0C,EAAK,MAAM,IAAI,MAAM,4BAA4B,EAEtD,IAAMC,EAAW,MAAM,MAAMD,EAAK,CAC9B,OAAQ,KACZ,CAAC,EACD,GAAI,CAACC,EAAS,GACV,MAAM,IAAI,MAAM,uBAAuBA,EAAS,MAAM,EAAE,EAE5D,IAAMC,EAAO,MAAMD,EAAS,KAAK,EACjC,OAAO,IAAI,KAAK,CAACC,CAAI,EAAG7C,EAAK,KAAM,CAC/B,MAAMwC,GAAA1C,EAAAE,EAAK,OAAL,YAAAF,EAAW,WAAX,KAAA0C,EAAuB,0BACjC,CAAC,CACL,OAASf,EAAO,CACZlB,EAASkB,EAAgB,OAAO,EAChC,MACJ,CACJ,EAEMqB,EAAe,SAAY,CApKrC,IAAAhD,EAqKQ,GAAIkB,EAAc,SAAW,EAE7B,CAAAG,EAAc,EAAI,EAClBE,EAAoB,CAAC,EAErB,GAAI,CACA,IAAM0B,GAAmB,MAAMV,EAAcrB,CAAa,GAAG,OACzD,OACJ,EAGAX,EAAS0C,CAAyB,EAGlC9B,EAAiB,CAAC,CAAC,EACnBX,EAAiB,MAAS,CAC9B,OAASmB,EAAO,CACZlB,EACImB,EAAEjB,EAAa,qBAAsB,CACjC,SAAUX,EAAA2B,GAAA,YAAAA,EAAiB,UAAjB,KAAA3B,EAA4B,EAC1C,CAAC,CACL,CACJ,QAAE,CACEqB,EAAc,EAAK,EACnBE,EAAoB,CAAC,CACzB,EACJ,EAEM2B,EAAc,MAAOzB,GAA0B,CAjMzD,IAAAzB,EAkMQ,GAAKyB,GAAA,MAAAA,EAAO,OACZ,CAAAJ,EAAc,EAAI,EAClBE,EAAoB,CAAC,EACrB,GAAI,CACA,IAAM4B,EAAW1B,EAAM,OAAOa,GAAK,CAC/B,GAAI,CAAC5B,GAAUA,IAAW,IAAK,MAAO,GACtC,IAAM0C,EAAMd,EAAE,KAAK,MAAM,GAAG,EAAE,IAAI,GAAK,GACvC,OAAO5B,EAAO,SAAS0C,CAAG,CAC9B,CAAC,EACKH,GAAmB,MAAMV,EAAcY,CAAQ,GAAG,OACpD,OACJ,EACA5C,EAAS0C,CAAyB,EAClC9B,EAAiB,CAAC,CAAC,EACnBX,EAAiB,MAAS,CAC9B,OAASmB,EAAO,CACZlB,EACImB,EAAEjB,EAAa,qBAAsB,CACjC,SAAUX,EAAA2B,GAAA,YAAAA,EAAiB,UAAjB,KAAA3B,EAA4B,EAC1C,CAAC,CACL,CACJ,QAAE,CACEqB,EAAc,EAAK,EACnBE,EAAoB,CAAC,CACzB,EACJ,EAyBA,MAAO,CACH,KAAAP,EACA,QAAAC,EACA,eAAAJ,EACA,YAAAuB,EACA,cAAAlB,EACA,WAAAE,EACA,aAAA4B,EACA,iBAAA1B,EACA,qBAjCyB,IAAM,CAC/BH,EAAiB,CAAC,CAAC,EACnBI,EAAoB,CAAC,CACzB,EA+BI,sBA7B0B,SAAY,CAjO9C,IAAAvB,EAkOQ,GAAI,CACA,IAAMqD,EAAUrC,EAAKA,EAAK,OAAS,CAAC,EACpC,GAAI,CAACqC,EAAS,OACd,GAAI,CAAClD,EAAa,CACdM,EAAQE,EAAa,yBAAyB,EAC9C,MACJ,CACA,IAAMc,EAAQ,MAAMM,EAAuBsB,EAAQ,EAAE,EACrD,MAAMH,EAAYzB,CAAK,CAC3B,OAASE,EAAO,CACZlB,EACImB,EAAEjB,EAAa,qBAAsB,CACjC,SAAUX,EAAA2B,GAAA,YAAAA,EAAiB,UAAjB,KAAA3B,EAA4B,EAC1C,CAAC,CACL,CACJ,CACJ,CAaA,CACJ,CJxPe,SAARsD,IAAoC,CACvC,GAAM,CAAE,gBAAAC,CAAgB,EAAIC,EAAe,EACrC,CACF,KAAAC,EACA,cAAeC,EACf,QAASC,EACT,YAAAC,EACA,MAAAC,EACA,cAAAC,EACA,UAAAC,CACJ,EAAIC,GAAYT,GAAA,YAAAA,EAAiB,kBAAkB,EAC7CU,EAAQC,GAAoBN,CAAW,EAE7C,OAAIE,GAAiB,CAACD,EACXM,GAAA,cAACC,GAAA,CAAkB,aAAa,WAAW,QAASL,EAAW,EAItEI,GAAA,cAACE,GAAA,CACG,WAAYX,EACZ,KAAMD,EACN,cAAeE,EACd,GAAGM,EACR,CAER,CKjCA,OAAOK,IAA2B,YAAAC,OAAgB,QAMnC,SAARC,IAA+B,CAClC,GAAM,CACF,SAAAC,EACA,iBAAAC,EACA,aAAcC,EACd,MAAO,CACH,MAAO,CAAE,WAAAC,CAAW,EACpB,KAAAC,EACA,WAAAC,CACJ,CACJ,EAAIC,EAAe,EACb,CAACC,EAAKC,CAAM,EAAIC,GAAS,EAAE,EAC3B,CAAE,QAAAC,EAAS,WAAAC,CAAW,EAAIC,GAAkB,EAelD,OACIC,GAAA,cAACC,GAAA,KACGD,GAAA,cAAC,QAAK,SAf8C,MAAME,GAAK,CACnEA,EAAE,eAAe,EACjB,IAAMC,EAAO,MAAML,EAAWJ,CAAG,EAC7BS,IACA,OAAO,OAAOA,EAAM,CAChB,IAAAT,CACJ,CAAC,EACDP,EAAS,CAACgB,CAAI,CAAC,EACfR,EAAO,EAAE,EACTP,EAAiB,MAAS,EAElC,EAI0C,UAAU,uBACxCY,GAAA,cAAC,SACG,KAAK,MACL,YAAaX,EAAG,aAChB,UAAWe,EACP,4HACA,CACI,gGACIb,CACR,EACAC,EAAW,QACf,EACA,MAAOE,EACP,SAAUQ,GAAKP,EAAOO,EAAE,cAAc,KAAK,EAC/C,EACAF,GAAA,cAAC,UACG,UAAWI,EACP,mJACA,CACI,sGACIb,CACR,EACAC,EAAW,cACf,EACA,KAAK,SACL,SAAU,CAACE,GAEVG,EAAUG,GAAA,cAACV,EAAA,IAAW,EAAKD,EAAG,KACnC,CACJ,CACJ,CAER,CClDO,IAAMgB,GAA6D,CACrE,SAAyB,WACzB,aAA6B,cAC7B,UAA0B,WAC1B,QAAwB,UACxB,KAAqB,OACrB,OAAuB,QAC5B,EAEaC,GAAsB,CAC9B,SAAyB,CACtB,cACA,QAAS,WACT,KAAMC,GACN,UAAW,MACf,EACC,aAA6B,CAC1B,kBACA,QAAS,cACT,KAAMC,GACN,UAAWC,EACf,EACC,UAA0B,CACvB,eACA,QAAS,WACT,KAAMC,GACN,UAAWC,EACf,EACC,QAAwB,CACrB,aACA,QAAS,UACT,KAAMC,GACN,UAAWC,EACf,EACC,KAAqB,CAClB,UACA,QAAS,OACT,KAAMC,GACN,UAAWC,EACf,EACC,OAAuB,CACpB,YACA,QAAS,SACT,KAAMC,GACN,UAAWC,EACf,CAOJ,E9BhEe,SAARC,IAAsC,CACzC,GAAM,CACF,SAAAC,EACA,iBAAAC,EACA,SAAAC,EACA,aAAAC,EACA,MAAO,CAAE,eAAAC,EAAgB,mBAAAC,CAAmB,CAChD,EAAIC,EAAe,EAEbC,EAAiBC,GACnB,IACI,OAAO,OAAOC,EAAmB,EAC5B,OAAOC,GAAQN,EAAe,SAASM,EAAK,EAAE,CAAC,EAC/C,IAAIA,IAAS,CACV,GAAGA,EACH,KAAMP,EAAaO,EAAK,OAAO,CACnC,EAAE,EACV,CAACN,EAAgBD,CAAY,CACjC,EAEMQ,EAAqBC,GACtBC,GAA6B,CA1BtC,IAAAC,EA2BYT,EAAmBQ,CAAS,EACxBA,IAAc,YAAwBC,EAAAd,EAAS,UAAT,MAAAc,EAAkB,QACvDb,EAAiBY,CAAS,CACnC,EACA,CAACb,EAAUK,EAAoBJ,CAAgB,CACnD,EAEMc,EACFH,GACII,GAAK,CACDd,EAAS,MAAM,KAAKc,EAAE,cAAc,OAAS,CAAC,CAAC,CAAC,EAChDA,EAAE,cAAc,MAAQ,EAC5B,EACA,CAACd,CAAQ,CACb,EAEJ,MAAO,CACH,eAAAK,EACA,mBAAAI,EACA,sBAAAI,CACJ,CACJ,CDxCe,SAARE,IAAmC,CACtC,GAAM,CACF,MAAO,CACH,KAAAC,EACA,OAAAC,EACA,SAAAC,EACA,MAAAC,EACA,YAAAC,EACA,KAAAC,EACA,WAAAC,EACA,uBAAAC,CACJ,EACA,aAAcC,EACd,aAAAC,EACA,gBAAAC,EACA,SAAAC,EACA,SAAAC,CACJ,EAAIC,EAAe,EACb,CAAE,eAAAC,EAAgB,mBAAAC,EAAoB,sBAAAC,CAAsB,EAC9DC,GAAmB,EAEjBC,EAAyBC,GAAY,IAAM,CACzCR,EAAS,UACTA,EAAS,QAAQ,gBAAgB,iBAAiB,EAClDA,EAAS,QAAQ,gBAAgB,WAAW,EAC5CA,EAAS,QAAQ,MAAM,EAE/B,EAAG,CAACA,CAAQ,CAAC,EAEPS,EAA0BD,GAAY,SAAY,CACpD,IAAME,EAAY,OAClB,GAAIA,EAAU,oBACV,GAAI,CACA,IAAMC,EAAkB,MAAMD,EAAU,oBAAoB,EACtDE,EAAgB,CAAC,EAEvB,eAAeC,EAASC,EAAgBC,EAAO,GAAI,CAC/C,cAAiBC,KAASF,EAAU,OAAO,EAAG,CAC1C,IAAMG,EAAUF,EACV,GAAGA,CAAI,IAAIC,EAAM,IAAI,GACrBA,EAAM,KACZ,GAAIA,EAAM,OAAS,OAAQ,CACvB,IAAME,EAAO,MAAMF,EAAM,QAAQ,EAC/BE,EAAa,mBAAqBD,EACpCL,EAAM,KAAKM,CAAI,CACnB,MAAWF,EAAM,OAAS,aACtB,MAAMH,EAASG,EAAOC,CAAO,CAErC,CACJ,CACA,MAAMJ,EAASF,CAAe,EAC1BC,EAAM,OAAS,IACfX,EAASW,CAAK,EACVZ,EAAS,UACTA,EAAS,QAAQ,MAAQ,IAGrC,MAAQ,CAER,MAGIA,EAAS,UACTA,EAAS,QAAQ,aAAa,kBAAmB,MAAM,EACvDA,EAAS,QAAQ,aAAa,YAAa,MAAM,EACjDA,EAAS,QAAQ,MAAM,EAGnC,EAAG,CAACA,EAAUC,CAAQ,CAAC,EAEvB,OACIkB,EAAA,cAAC,OACG,UAAWC,EACP,iEACA,CACI,gBAAiBtB,EACjB,8FACI,CAACA,CACT,CACJ,GAEAqB,EAAA,cAACE,EAAA,CAAa,GAAIvB,GACdqB,EAAA,cAAC,OACG,UAAWC,EACP,yHACA,CACI,uCAAwC1B,CAC5C,EACAC,EAAW,eACf,GAEAwB,EAAA,cAAC,UACG,UAAWC,EACP,0FACA,CACI,+CACI1B,CACR,EACAC,EAAW,qBACf,EACA,QAAS,IAAMI,EAAgB,EAAK,GAEpCoB,EAAA,cAAC,OACG,MAAM,6BACN,MAAM,KACN,OAAO,KACP,QAAQ,YACR,KAAK,OACL,OAAO,eACP,YAAY,IACZ,cAAc,QACd,eAAe,SAEfA,EAAA,cAAC,YAAS,OAAO,kBAAkB,CACvC,EAAM,MAEV,EACAA,EAAA,cAAC,QACG,UAAWC,EACP,gEACA,CACI,6CACI1B,CACR,CACJ,GACH,mBAED,CACJ,CACJ,EACAyB,EAAA,cAACE,EAAA,CAAa,GAAI,CAAChC,GACf8B,EAAA,cAAC,OACG,UAAWC,EACP,kKACAzB,EAAW,iBACf,GAECQ,EAAe,IAAI,CAAC,CAAE,KAAAmB,EAAM,GAAAC,EAAI,KAAAC,CAAK,IAClCL,EAAA,cAAC,UACG,IAAKI,EACL,KAAK,SACL,UAAWH,EACP,0MACA,CACI,mDACI1B,CACR,EACAC,EAAW,aACf,EACA,UAAW8B,GAAK,CACRA,EAAE,MAAQ,SAASA,EAAE,eAAe,CAC5C,EACA,QAAS,IAAMrB,EAAmBmB,CAAE,GAEpCJ,EAAA,cAACG,EAAA,IAAK,EACNH,EAAA,cAAC,QACG,UAAWC,EACP,mCACA,CACI,6CACI1B,CACR,EACAC,EAAW,iBACf,GAEC6B,CACL,CACJ,CACH,CACL,CACJ,EACAL,EAAA,cAAC,SACG,KAAK,OACL,OAAQ7B,EACR,UAAU,cACV,cAAY,kBACZ,IAAKU,EACL,SAAUT,EACV,SAAUc,EACd,EACChB,EACG8B,EAAA,cAAC,UACG,KAAK,SACL,QAASZ,EACT,UAAU,yHAEVY,EAAA,cAACO,GAAA,CACG,KAAM,GACN,UAAWN,EACP,gDACA,CACI,sBAAuB,CAAC1B,EACxB,uCAAwCA,CAC5C,CACJ,EACJ,EACAyB,EAAA,cAAC,KACG,UAAWC,EAAG,qCAAsC,CAChD,8CACI,CAAC1B,EACL,6CAA8CA,CAClD,CAAC,GACJ,0BAED,CACJ,EAEAyB,EAAA,cAAC,OAAI,UAAU,mHACXA,EAAA,cAAC,OAAI,UAAU,6EACXA,EAAA,cAAC,QACG,UAAWC,EACP,mDACA,CACI,uCACI1B,CACR,CACJ,GAECF,EAAQ,EAAIK,EAAG,YAAcA,EAAG,UACrC,EACAsB,EAAA,cAAC,UACG,KAAK,SACL,UAAWC,EACP,0FACA,CACI,+CACI1B,CACR,CACJ,EACA,QAASa,GAERV,EAAG,WACR,EACCD,GACGuB,EAAA,cAAAA,EAAA,cACIA,EAAA,cAAC,QACG,UAAWC,EACP,mDACA,CACI,uCACI1B,CACR,CACJ,GAEC,IACAG,EAAG,EACR,EACAsB,EAAA,cAAC,UACG,KAAK,SACL,UAAWC,EACP,0FACA,CACI,+CACI1B,CACR,CACJ,EACA,QAASe,GAERZ,EAAG,aACR,CACJ,CAER,EACAsB,EAAA,cAAC,KACG,UAAWC,EACP,oEACA,CACI,6CACI1B,CACR,CACJ,IAECD,GAAA,YAAAA,EAAa,QAAQA,GAAA,YAAAA,EAAa,OAC/B0B,EAAA,cAAAA,EAAA,cACKQ,EAAEC,GAAO/B,EAAI,qBAAsBL,CAAK,EAAG,CACxC,KAAMC,EAAY,KAClB,KAAMA,EAAY,IACtB,CAAC,CACL,CAER,CACJ,CAER,CAER,CgCrSA,OAAS,UAAAoC,OAAc,gBACvB,OAAOC,OAAW,QAMH,SAARC,IAA+B,CAClC,GAAM,CACF,cAAAC,EACA,iBAAAC,EACA,aAAcC,EACd,MAAO,CAAE,KAAAC,EAAM,KAAAC,EAAM,WAAAC,CAAW,CACpC,EAAIC,EAAe,EACbC,EACFP,GAAiBQ,GAAoBR,CAAa,EAAE,UAClDS,EAAOT,GAAiBQ,GAAoBR,CAAa,EAAE,KAEjE,MAAI,CAACO,GAAmBJ,GAAQ,CAACH,GAAiB,CAACS,EAAa,KAG5DC,GAAA,cAACC,GAAA,KACGD,GAAA,cAACE,GAAO,IAAP,CACG,QAAS,CAAE,EAAG,OAAQ,EACtB,QAAS,CAAE,EAAG,IAAK,EACnB,KAAM,CAAE,EAAG,OAAQ,EACnB,UAAU,8DACV,IAAI,gBAEJF,GAAA,cAAC,OACG,UAAWG,EACP,kKACA,CACI,oFACIT,CACR,EACAC,EAAW,iBACf,GAEAK,GAAA,cAACD,EAAA,IAAK,EACNC,GAAA,cAAC,UACG,UAAWG,EACP,oFACA,CACI,+CACIT,CACR,EACAC,EAAW,uBACf,EACA,QAAS,IAAMJ,EAAiB,MAAS,EACzC,KAAK,UAEJC,EAAG,MACR,CACJ,EACAQ,GAAA,cAACH,EAAA,IAAgB,CACrB,CACJ,CAER,CC3DA,OAAS,UAAAO,OAAc,gBACvB,OAAOC,GAAS,QAAAC,OAAY,QAC5B,OAAS,uBAAAC,GAAqB,sBAAAC,OAA0B,iBCFxD,OAAOC,IAA4B,QAAAC,GAAM,eAAAC,GAAa,YAAAC,OAAgB,QCAtE,OAAOC,IAKH,QAAAC,GACA,aAAAC,GACA,WAAAC,OACG,QCRP,OAAOC,IAAmC,QAAAC,GAAM,WAAAC,OAAe,QCA/D,OAAOC,IAAS,cAAAC,GAAiB,QAAAC,OAAqC,QACtE,OACI,UAAAC,GACA,iBAAAC,GACA,iBAAAC,GACA,iBAAAC,GACA,kBAAAC,GACA,kBAAAC,GACA,iBAAAC,GACA,gBAAAC,GACA,iBAAAC,GACA,iBAAAC,GACA,iBAAAC,GACA,iBAAAC,GACA,iBAAAC,GACA,gBAAAC,GACA,iBAAAC,GACA,iBAAAC,GACA,gBAAAC,GACA,iBAAAC,GACA,iBAAAC,GACA,iBAAAC,GACA,iBAAAC,GACA,iBAAAC,GACA,iBAAAC,OACG,iBAMP,IAAMC,GAAyC,CAC3C,IAAKC,GACL,IAAKC,GACL,IAAKC,GACL,KAAMC,GACN,KAAMC,GACN,IAAKC,GACL,GAAIC,GACJ,IAAKC,GACL,IAAKC,GACL,IAAKC,GACL,IAAKC,GACL,IAAKC,GACL,GAAIC,GACJ,IAAKC,GACL,IAAKC,GACL,GAAIC,GACJ,IAAKC,GACL,IAAKC,GACL,IAAKC,GACL,IAAKC,GACL,IAAKC,GACL,IAAKC,EACT,EAEOC,GAAQC,GACXC,GAKE,SAAkB,CAAE,UAAAC,EAAY,GAAI,UAAAC,EAAW,GAAGC,CAAU,EAAGC,EAAK,CAClE,GAAM,CACF,MAAO,CAAE,KAAAC,CAAK,CAClB,EAAIC,EAAe,EACbC,EAAgBhC,GAAU0B,CAAS,GAAKO,GAC9C,OACIC,GAAA,cAACF,EAAA,CACG,IAAKH,EACL,UAAWM,EAAG,mCAAoCR,EAAW,CACzD,+CAAgDG,CACpD,CAAC,EACA,GAAGF,EACR,CAER,CAAC,CACL,EDpDA,IAAOQ,GAAQC,GACX,SAA8B,CAC1B,WAAAC,EACA,cAAAC,EACA,QAAAC,EACA,SAAAC,EACA,SAAAC,EACA,SAAAC,EACA,WAAAC,EACA,aAAAC,EACA,aAAcC,CAClB,EAAU,CACN,IAAMC,EAAYC,GACd,IAAMC,GAAiBP,EAAUD,CAAQ,EACzC,CAACC,EAAUD,CAAQ,CACvB,EAEMS,EAAOF,GAAQ,IACVG,IAASJ,GAAA,YAAAA,EAAW,gBAAiB,EAAE,EAC/C,CAACA,CAAS,CAAC,EAKRK,EAAkBJ,GAAQ,IACbK,GAAcX,EAAUD,CAAQ,GAC9B,CAACa,GAAmBZ,EAAUD,EAAUE,CAAQ,EAClE,CAACD,EAAUD,EAAUE,CAAQ,CAAC,EAEjC,OAAIO,GAAQE,EAEJG,GAAA,cAAC,OAAI,UAAU,wDACXA,GAAA,cAACC,GAAA,CACG,UAAWT,EACX,UAAWH,EAAW,SAC1B,CACJ,EAKJW,GAAA,cAAAA,GAAA,cACIA,GAAA,cAACE,EAAA,CAAa,GAAI,CAACnB,GACfiB,GAAA,cAAC,UACG,KAAMf,EACN,MAAM,KACN,OAAO,KACP,KAAMC,EACN,KAAMC,EACN,OAAQ,IAAMH,EAAc,EAAI,GAEhCgB,GAAA,cAAC,SAAGT,EAAG,OAAQ,CACnB,EACAS,GAAA,cAACC,GAAA,CAAS,UAAWT,EAAW,CACpC,EAEAQ,GAAA,cAACE,EAAA,CAAa,GAAInB,GACdiB,GAAA,cAACC,GAAA,CACG,UAAWT,EACX,UAAWW,EACP,CACI,iBAAkBb,CACtB,EACAD,EAAW,QACf,EACJ,EACAW,GAAA,cAAC,OACG,UAAWG,EACP,qDACIb,GAAgB,eACpB,EACJ,GAEAU,GAAA,cAAC,UACG,KAAMf,EACN,MAAM,OACN,OAAO,OACP,KAAMC,EACN,KAAMC,EACN,UAAU,yCAEVa,GAAA,cAAC,SAAGT,EAAG,OAAQ,CACnB,CACJ,CACJ,CACJ,CAER,EACA,CAACa,EAAMC,IACHD,EAAK,aAAeC,EAAK,YACzBD,EAAK,WAAaC,EAAK,UACvBD,EAAK,UAAYC,EAAK,OAC9B,EErHA,OAAOC,IAAS,cAAAC,OAAkC,QAWlD,IAAOC,GAAQC,GAAkC,SAC7C,CAAE,SAAAC,EAAU,UAAAC,EAAW,qBAAAC,EAAsB,UAAAC,EAAY,GAAO,GAAGC,CAAK,EACxEC,EACF,CACE,GAAM,CACF,MAAO,CAAE,WAAAC,EAAY,KAAAC,CAAK,CAC9B,EAAIC,EAAe,EACnB,OACIC,GAAA,cAACC,EAAA,CAAa,GAAI,CAAC,CAACV,GAChBS,GAAA,cAAC,OACG,IAAKJ,EACL,UAAWM,EACP,yCACAV,EACAK,EAAW,oBACf,EACC,GAAGF,GAEJK,GAAA,cAAC,OACG,UAAWE,EACP,qFACAT,EACAI,EAAW,WACf,GAEAG,GAAA,cAAC,OACG,MAAO,CACH,MAAOT,EAAW,GACtB,EACA,UAAWW,EACP,gCACAL,EAAW,gBACf,EACJ,CACJ,EACAG,GAAA,cAACC,EAAA,CAAa,GAAI,CAAC,CAACP,GAChBM,GAAA,cAAC,KACG,UAAWE,EACP,kCACA,CACI,kBAAmBJ,CACvB,EACAD,EAAW,eACf,GAECN,EAAS,GACd,CACJ,CACJ,CACJ,CAER,CAAC,EHjCD,IAAOY,GAAQC,GAAK,SAAqBC,EAAc,CACnD,GAAM,CACF,SAAAC,EACA,OAAAC,EACA,SAAAC,EACA,QAAAC,EACA,SAAAC,EACA,WAAAC,EACA,cAAAC,EACA,iBAAAC,EACA,GAAGC,CACP,EAAIT,EAEE,CACF,iBAAAU,EACA,aAAcC,EACd,gBAAAC,EACA,OAAQ,CAAE,iBAAAC,CAAiB,EAC3B,MAAO,CACH,WAAAC,EACA,MAAO,CAAE,eAAAC,CAAe,EACxB,aAAAC,EACA,YAAAC,CACJ,EACA,MAAAC,CACJ,EAAIC,EAAe,EAEbC,EAAUC,GAAQ,IAAMC,GAAerB,CAAQ,EAAG,CAACA,CAAQ,CAAC,EAC5DsB,EAASF,GACX,IAAMG,GAAcvB,EAAUE,CAAQ,EACtC,CAACF,EAAUE,CAAQ,CACvB,EAGMsB,EAAiBJ,GACnB,IAAMK,GAAmBzB,EAAUE,EAAUE,CAAQ,EACrD,CAACJ,EAAUE,EAAUE,CAAQ,CACjC,EAEMsB,EAAWN,GACb,IAAG,CArEX,IAAAO,EAAAC,EAsEY,YAAK,QACAD,EAAAf,EAAiBX,CAAM,IAAvB,YAAA0B,EAA0B,UACvBC,EAAAhB,EAAiBX,CAAM,IAAvB,YAAA2B,EAA0B,OAC1B,GACR,GACJ,CAAC3B,EAAQW,CAAgB,CAC7B,EAEAiB,GAAU,IAAM,EAIPV,GAAYG,GAAUE,IAAoB,CAACnB,GAC5CC,EAAc,EAAI,CAC1B,EAAG,CAACa,EAASG,EAAQE,EAAgBnB,EAAYC,CAAa,CAAC,EAE/D,IAAMwB,EAA2DC,GAAK,CAClEA,EAAE,gBAAgB,EAClBtB,EAAiBR,CAAM,CAC3B,EAEM+B,EAA0DD,GAAK,CACjEA,EAAE,gBAAgB,EAClB,IAAME,EAAOhB,EAAM,IAAIhB,CAAM,EACzBgC,GAAMtB,EAAgBsB,CAAI,CAClC,EAEMC,EAAiB,CAACC,EAA2BzB,IAAqB,CACpE,GAAI,CAACyB,GAASA,IAAU,EAAG,OAAOzB,EAAG,UACrC,IAAM0B,EAAI,KACJC,EAAQ,CAAC3B,EAAG,MAAOA,EAAG,GAAIA,EAAG,GAAIA,EAAG,EAAE,EACtC4B,EAAI,KAAK,MAAM,KAAK,IAAIH,CAAK,EAAI,KAAK,IAAIC,CAAC,CAAC,EAClD,OAAO,KAAK,MAAOD,EAAQ,KAAK,IAAIC,EAAGE,CAAC,EAAK,EAAE,EAAI,GAAK,IAAMD,EAAMC,CAAC,CACzE,EAEA,OACIC,GAAA,cAAC,OAAI,UAAU,oBAAqB,GAAG/B,GACnC+B,GAAA,cAAC,OACG,UAAWC,EACP,gHACA,mDACA,CACI,CAAC3B,EAAW,qBAAsB,EAC9BA,EAAW,uBAAyBI,EAAM,KAAO,EACrD,CAACJ,EAAW,mBAAoB,EAC5BA,EAAW,qBAAuBI,EAAM,OAAS,CACzD,CACJ,EACA,MACIE,EAAU,CAAE,gBAAiB,OAAOhB,CAAO,GAAI,EAAI,QAGvDoC,GAAA,cAACE,EAAA,CAAa,GAAI,CAACtB,GACfoB,GAAA,cAAC,OAAI,UAAU,wEACXA,GAAA,cAACG,GAAA,CACG,WAAYrC,EACZ,cAAeC,EACf,SAAUN,EACV,SAAUE,EACV,QAASC,EACT,SAAUC,EACV,aAAcW,EACd,WAAYF,EACZ,aAAcH,EAClB,CACJ,CACJ,EAECS,GAAWH,EAAY,SACpBuB,GAAA,cAAC,UACG,UAAWC,EACP,oDACA,oEACA,oEACA,+CACA,gCACA,2DACJ,EACA,QAASR,EACT,KAAK,SACL,SAAU,CAAC,CAACN,EACZ,aAAW,cAEXa,GAAA,cAAC,OACG,MAAM,6BACN,QAAQ,YACR,KAAK,eACL,UAAU,oBACV,cAAY,QAEZA,GAAA,cAAC,QAAK,EAAE,0IAA0I,CACtJ,CACJ,EAGJA,GAAA,cAAC,UACG,UAAWC,EACP,sDACA,oEACA,mEACA,8CACA,gCACA,4DACA3B,EAAW,gBACf,EACA,QAASiB,EACT,KAAK,SACL,SAAU,CAAC,CAACJ,EACZ,aAAYhB,EAAG,YAEf6B,GAAA,cAACzB,EAAA,CAAe,UAAU,oBAAoB,CAClD,EAEAyB,GAAA,cAACI,GAAA,CACG,UAAU,uDACV,qBAAqB,wCACrB,SAAUjB,EACd,CACJ,EAEAa,GAAA,cAAC,OAAI,UAAU,yBACXA,GAAA,cAAC,OAAI,UAAU,sFACVrC,CACL,EACAqC,GAAA,cAAC,OAAI,UAAU,sEACVL,EAAe9B,EAAUM,CAAE,CAChC,EACCK,GAAgBV,GACbkC,GAAA,cAAC,UACG,KAAK,SACL,UAAU,uJACV,QAAShC,GAERG,EAAG,cACR,CAER,CACJ,CAER,CAAC,EIjND,OAAOkC,GACH,cAAAC,GAEA,QAAAC,GAEA,aAAAC,GACA,WAAAC,GACA,YAAAC,OACG,QACP,OAAS,gBAAAC,OAAoB,YAY7B,IAAOC,GAAQC,GACXC,GASE,SACE,CACI,kBAAAC,EACA,QAAAC,EACA,SAAAC,EACA,SAAAC,EACA,SAAAC,EACA,GAAGC,CACP,EACAC,EACF,CACE,GAAM,CACF,MAAO,CAAE,KAAAC,EAAM,WAAAC,CAAW,EAC1B,aAAcC,CAClB,EAAIC,EAAe,EACbC,EAAUC,GAAQ,IAAMC,GAAeV,CAAQ,EAAG,CAACA,CAAQ,CAAC,EAC5DW,EAASF,GACX,IAAMG,GAAcZ,EAAUD,CAAQ,EACtC,CAACC,EAAUD,CAAQ,CACvB,EAEMc,EAAkBJ,GACpB,IACIE,GACAV,IAAa,QACbA,EAAWa,GACf,CAACH,EAAQV,CAAQ,CACrB,EAEM,CAACc,EAAaC,CAAc,EAAIC,GAAiB,EAAE,EACnD,CAACC,EAAaC,CAAc,EAAIF,GAAS,EAAK,EAC9C,CAACG,EAAWC,CAAY,EAAIJ,GAAiB,EAE7C,CAACK,EAAaC,CAAc,EAAIN,GAAS,EAAK,EAEpD,OAAAO,GAAU,IAAM,CACZ,IAAIC,EAAY,GAyDhB,OAxDiB,SAAY,CApEzC,IAAAC,EAqEgB,GAAKf,EACL,GAAI,CAGA,GAFAQ,EAAe,EAAI,EAEfN,EAAiB,CAIjB,IAAMc,GAASD,GADH,MAAM,MAAM5B,CAAO,GACZ,OAAJ,YAAA4B,EAAU,YACzB,GAAI,CAACC,EAAQ,MAAM,IAAI,MAAM,kBAAkB,EAE/C,IAAMC,EAAU,IAAI,YAChBC,EAAS,GACTC,EAAO,GAEX,KACI,CAACA,GACDD,EAAO,OAASE,IAClB,CACE,GAAM,CAAE,MAAAC,EAAO,KAAMC,CAAW,EAC5B,MAAMN,EAAO,KAAK,EACtBG,EAAOG,EACHD,IACAH,GAAUD,EAAQ,OAAOI,EAAO,CAC5B,OAAQ,CAACF,CACb,CAAC,EAET,CAGA,GAFAH,EAAO,OAAO,EAEV,CAACF,EAAW,CACZ,IAAMS,EACF,CAACJ,GACDD,EAAO,OAASE,GAChBG,IACAL,EAASA,EAAO,MACZ,EACAE,EACJ,GAEJR,EAAeW,CAAY,EAC3BlB,EAAea,CAAM,CACzB,CACJ,KAAO,CAEH,IAAMM,EAAM,MADA,MAAM,MAAMrC,CAAO,GACT,KAAK,EACtB2B,GAAWT,EAAemB,CAAG,CACtC,CACJ,OAASC,EAAG,CACHX,GACDJ,GAAce,GAAA,YAAAA,EAAa,UAAW,eAAe,CAC7D,QAAE,CACOX,GAAWN,EAAe,EAAK,CACxC,CACJ,GACS,EACF,IAAM,CACTM,EAAY,EAChB,CACJ,EAAG,CAAC3B,EAASa,EAAQE,CAAe,CAAC,EAE9BwB,GACHC,EAAA,cAAC,OAAI,UAAU,cACXA,EAAA,cAAC,OACG,UAAU,+GACV,IAAKnC,EACJ,GAAGD,GAEJoC,EAAA,cAAC,OAAI,UAAU,sDACXA,EAAA,cAAC,OACG,UAAWC,EACP,oDACA,CACI,2CACInC,CACR,EACAC,EAAW,iBACf,EACA,QAASR,GAETyC,EAAA,cAACE,EAAA,CAAa,GAAIhC,GACd8B,EAAA,cAAC,OACG,IAAKxC,EACL,IAAKC,EACL,UAAU,2DACd,CACJ,EACAuC,EAAA,cAACE,EAAA,CAAa,GAAI,CAAChC,GACf8B,EAAA,cAACE,EAAA,CAAa,GAAI7B,GACd2B,EAAA,cAAC,OAAI,UAAU,mFACVpB,GAAeoB,EAAA,cAAC,SAAGhC,EAAG,OAAQ,EAC9Bc,GACGkB,EAAA,cAAC,SACIG,EAAEnC,EAAG,aAAc,CAChB,QAASc,CACb,CAAC,CACL,EAEH,CAACF,GAAe,CAACE,GACdkB,EAAA,cAAAA,EAAA,cACIA,EAAA,cAAC,OAAI,UAAU,4BACVvB,CACL,EACCO,GACGgB,EAAA,cAAC,OAAI,UAAU,4IAA2I,2DAI1J,CAER,CAER,CACJ,EACAA,EAAA,cAACE,EAAA,CAAa,GAAI,CAAC7B,GACf2B,EAAA,cAAC,UACG,KAAMxC,EACN,MAAM,OACN,OAAO,OACP,KAAMC,EACN,KAAMC,GAENsC,EAAA,cAAC,SAAGhC,EAAG,OAAQ,CACnB,CACJ,CACJ,CACJ,CACJ,CACJ,CACJ,EACA,SAAS,IACb,CACJ,CAAC,CACL,EL/LA,IAAOoC,GAAQC,GAAK,SAAkB,CAAE,KAAAC,CAAK,EAAU,CACnD,GAAM,CACF,MAAAC,EACA,MAAO,CAAE,WAAAC,EAAY,YAAAC,CAAY,CACrC,EAAIC,EAAe,EACb,CAACC,EAAmBC,CAAoB,EAAIC,GAAS,EAAK,EAC1D,CAACC,EAAYC,CAAa,EAAIF,GAAS,EAAK,EAE5CG,EAAwDC,GAC1DC,GAAK,CACDA,EAAE,gBAAgB,CACtB,EACA,CAAC,CACL,EACMC,EAAoBF,GAAY,IAAM,CACxCL,EAAqB,EAAI,CAC7B,EAAG,CAAC,CAAC,EAEL,OACIQ,GAAA,cAAC,OACG,cAAY,iBACZ,UAAWC,EACP,oGACA,CACI,CAACb,EAAW,gBAAiB,EACzBA,EAAW,kBAAoBD,EAAM,KAAO,EAChD,CAACC,EAAW,cAAe,EACvBA,EAAW,gBAAkBD,EAAM,OAAS,CACpD,CACJ,GAEAa,GAAA,cAACE,GAAA,CACG,SAAUhB,EAAK,KACf,SAAUA,EAAK,KACf,OAAQA,EAAK,GACb,QAASA,EAAK,IACd,SAAUA,EAAK,KACf,WAAYQ,EACZ,cAAeC,EACf,iBAAkBI,EAClB,QAAS,IAAMV,EAAYH,CAAI,EACnC,EAECQ,GAAcH,GACXS,GAAA,cAACG,GAAA,CACG,kBAAmBP,EACnB,QAAS,IAAMJ,EAAqB,EAAK,EACzC,SAAUN,EAAK,KACf,QAASA,EAAK,IACd,SAAUA,EAAK,KACf,SAAUA,EAAK,KACnB,CAER,CAER,CAAC,EMlED,OAAOkB,IAAS,WAAAC,OAAe,QAUhB,SAARC,GAA+B,CAAE,aAAAC,CAAa,EAAoB,CACrE,GAAM,CACF,MAAAC,EACA,gBAAAC,EACA,aAAAC,EACA,aAAcC,EACd,MAAO,CACH,KAAAC,EACA,MAAAC,EACA,aAAAC,EACA,KAAAC,EACA,WAAAC,EACA,MAAO,CAAE,qBAAAC,CAAqB,CAClC,EACA,OAAQ,CAAE,aAAAC,CAAa,CAC3B,EAAIC,EAAe,EACbC,EAAcF,IAAiB,UAC/BG,EAAiBR,IAAUL,EAAM,KACjCc,EAAaC,GACf,IAAOb,EAAeC,EAAG,OAASA,EAAG,eACrC,CAACD,EAAcC,CAAE,CACrB,EAEA,OAAIC,EAAa,KAGbY,GAAA,cAAC,OACG,UAAWC,EACP,sOACA,CACI,uCAAwCV,CAC5C,EACAC,EAAW,eACf,GAEAQ,GAAA,cAAC,UACG,UAAWC,EACP,6JACA,CACI,+CAAgDV,CACpD,EACAC,EAAW,qBACf,EACA,QAAST,EACT,SAAUa,GAAeN,GAExBQ,CACL,EACAE,GAAA,cAAC,QACG,UAAWC,EACP,uFACA,CACI,6CAA8CV,CAClD,CACJ,GAEAS,GAAA,cAACE,EAAA,CAAa,GAAIhB,GACbC,EAAG,eACR,EACAa,GAAA,cAACE,EAAA,CAAa,GAAI,CAAChB,GACdiB,EAAEC,GAAOjB,EAAI,gBAAiBH,EAAM,IAAI,EAAG,CACxC,MAAOA,EAAM,IACjB,CAAC,CACL,CACJ,EACAgB,GAAA,cAACE,EAAA,CAAa,GAAI,CAAChB,GAAgBG,EAAQ,GAAK,CAACQ,GAC7CG,GAAA,cAAC,UACG,UAAWC,EACP,yOACA,CACI,+CACIV,CACR,EACAC,EAAW,sBACf,EACA,QAAS,IAAMP,EAAgB,EAAI,EACnC,SAAUW,GAAeN,GAEzBU,GAAA,cAACP,EAAA,IAAqB,EAAE,IAAEN,EAAG,OACjC,CACJ,CACJ,CAER,CPjFA,SAASkB,GAAYC,EAAuB,CACxC,GAAIA,IAAU,EAAG,MAAO,MACxB,IAAMC,EAAI,KACJC,EAAQ,CAAC,IAAK,KAAM,KAAM,IAAI,EAC9BC,EAAI,KAAK,MAAM,KAAK,IAAIH,CAAK,EAAI,KAAK,IAAIC,CAAC,CAAC,EAClD,OAAO,YAAYD,EAAQ,KAAK,IAAIC,EAAGE,CAAC,GAAG,QAAQ,CAAC,CAAC,EAAI,IAAMD,EAAMC,CAAC,CAC1E,CAEA,SAASC,GAAUC,EAAyB,CACxC,GAAIA,GAAW,GAAK,CAAC,SAASA,CAAO,EAAG,MAAO,GAC/C,IAAMC,EAAI,KAAK,MAAMD,EAAU,EAAE,EAC3BE,EAAIF,EAAU,GACpB,OAAIC,EAAI,EAAU,GAAGA,CAAC,KAAKC,CAAC,SACrB,GAAGA,CAAC,QACf,CAEA,IAAOC,GAAQC,GAAK,UAAoB,CACpC,GAAM,CACF,aAAAC,EACA,cAAAC,EACA,MAAAC,EACA,aAAcC,EACd,OAAQ,CACJ,cAAAC,EACA,aAAAC,EACA,cAAAC,EACA,YAAAC,EACA,UAAAC,EACA,cAAAC,EACA,WAAAC,CACJ,EACA,MAAO,CAAE,KAAAC,EAAM,WAAAC,EAAY,aAAAC,EAAc,WAAAC,EAAY,UAAAC,CAAU,EAC/D,WAAAC,EACA,aAAAC,EACA,YAAAC,EACA,aAAAC,CACJ,EAAIC,EAAe,EAEnB,OACIC,EAAA,cAAC,OACG,UAAWC,EACP,gFACA,CACI,cAAetB,GAAgBC,GAAiB,CAACC,EAAM,IAC3D,CACJ,GAEAmB,EAAA,cAACE,GAAA,CAAc,aAAcN,EAAc,EAE3CI,EAAA,cAACG,GAAA,KACGH,EAAA,cAACI,GAAO,IAAP,CACG,UAAWH,EACP,8GACA,CAAE,yCAA0CX,CAAK,EACjDC,EAAW,iBACf,GAEAS,EAAA,cAAC,OACG,UAAWC,EAEP,IACIT,GACA,0CACJ,8EACA,CACI,+BAAgCX,EAAM,KAAO,EAC7C,sBAAuBA,EAAM,KAAO,EACpC,cAAeA,EAAM,OAAS,EAC9B,CAACU,EAAW,8BAA+B,EACvCA,EAAW,gCACXV,EAAM,KAAO,EACjB,CAACU,EAAW,4BAA6B,EACrCA,EAAW,8BACXV,EAAM,OAAS,CACvB,CACJ,GAEC,MAAM,KAAKA,EAAM,OAAO,CAAC,EACrB,KAAK,CAACwB,EAAQC,IAAW,CACtB,IAAMC,EACDF,EAAU,cACVA,EAAU,oBACXA,EAAE,KACAG,EACDF,EAAU,cACVA,EAAU,oBACXA,EAAE,KACN,OACIC,EAAG,cAAcC,CAAE,GACnBH,EAAE,KAAK,cAAcC,EAAE,IAAI,CAEnC,CAAC,EACA,IAAIG,GACDT,EAAA,cAACU,GAAA,CAAS,IAAKD,EAAK,GAAI,KAAMA,EAAM,CACvC,CACT,CACJ,CACJ,EACAT,EAAA,cAAC,OACG,UAAWC,EACP,qHACA,CACI,uCAAwCX,CAC5C,EACAC,EAAW,cACf,GAGAS,EAAA,cAACW,EAAA,CACG,GACI3B,IAAiB,cACjBA,IAAiB,UAGrBgB,EAAA,cAAC,UACG,UAAWC,EACP,gJACA,CACI,2CACIX,CACR,EACAC,EAAW,YACf,EACA,QAAS,IAAM,CACXR,EAAc,CAClB,EACA,SACIC,IAAiB,WACjBA,IAAiB,UACjBQ,GAGHoB,EAAEC,GAAO/B,EAAI,cAAeD,EAAM,IAAI,EAAG,CACtC,MAAOA,EAAM,IACjB,CAAC,CACL,CACJ,EACAmB,EAAA,cAACW,EAAA,CACG,GAAI3B,IAAiB,UAAuB,CAACS,GAE7CO,EAAA,cAAC,UACG,UAAWC,EACP,+IACA,CACI,uCAAwCX,CAC5C,EACAC,EAAW,YACf,EACA,QAAS,IAAM,CACXR,EAAc,CAClB,IAECW,GAAA,YAAAA,EAAW,QAAS,YACf,gBACA,cACV,CACJ,EACAM,EAAA,cAACW,EAAA,CAAa,GAAI3B,IAAiB,cAC/BgB,EAAA,cAAC,UACG,UAAWC,EACP,8IACA,CACI,2CACIX,CACR,EACAC,EAAW,gBACf,EACA,QAASI,GAERb,EAAG,IACR,CACJ,EACAkB,EAAA,cAAC,OAAI,UAAU,kDACXA,EAAA,cAAC,OAAI,UAAU,0CACXA,EAAA,cAACW,EAAA,CACG,IACIjB,GAAA,YAAAA,EAAW,QAAS,cACnBV,IAAiB,WACdA,IAAiB,WAGzBgB,EAAA,cAAC,UACG,UAAWC,EACP,wKACA,CACI,0DACIX,CACR,CACJ,EACA,QACIN,IAAiB,SACXc,EACAD,EAEV,MACIb,IAAiB,SACX,gBACA,gBAGTA,IAAiB,SACdgB,EAAA,cAACc,GAAA,CAAmB,KAAM,GAAI,EAE9Bd,EAAA,cAACe,GAAA,CAAoB,KAAM,GAAI,CAEvC,CACJ,EACAf,EAAA,cAACgB,GAAA,CACG,UAAU,cACV,qBAAqB,eACrB,SAAU/B,EACV,UAAS,GACb,CACJ,EACAe,EAAA,cAACW,EAAA,CACG,IACK3B,IAAiB,WACdA,IAAiB,WACrBK,EAAa,GAGjBW,EAAA,cAAC,OACG,UAAWC,EACP,uFACA,CACI,qBAAsBX,CAC1B,CACJ,GAEAU,EAAA,cAAC,YACIhC,GAAYoB,CAAa,EAAE,MAAI,IAC/BpB,GAAYqB,CAAU,EACtBH,EAAc,GACX,SAAMlB,GAAYkB,CAAW,CAAC,IACtC,EACAc,EAAA,cAACW,EAAA,CACG,GACI3B,IAAiB,WACjBG,EAAY,GAGhBa,EAAA,cAAC,YAAM3B,GAAUc,CAAS,CAAE,CAChC,EACAa,EAAA,cAACW,EAAA,CACG,GAAI3B,IAAiB,UAErBgB,EAAA,cAAC,YAAK,QAAM,CAChB,CACJ,CACJ,CACJ,CACJ,CACJ,CAER,CAAC,EnC9Pc,SAARiB,IAA2B,CAC9B,GAAM,CACF,MAAAC,EACA,cAAAC,EACA,aAAAC,EACA,MAAO,CAAE,KAAAC,CAAK,CAClB,EAAIC,EAAe,EACb,CACF,WAAAC,EACA,mBAAAC,EACA,kBAAAC,EACA,eAAAC,EACA,gBAAAC,EACA,WAAAC,CACJ,EAAIC,GAAW,EAEf,OACIC,GAAA,cAACC,GAAA,KACGD,GAAA,cAACE,GAAO,IAAP,CACG,IAAI,mBACJ,UAAWC,EACP,iEACA,CACI,oCAAqCR,EACrC,mDACIA,GAAqBJ,EACzB,qBAAsB,CAACE,EACvB,0CACIC,GAAsB,CAACH,EAC3B,iEACIG,GAAsBH,CAC9B,CACJ,EACA,QAAS,CAAE,QAAS,CAAE,EACtB,QAAS,CAAE,QAAS,CAAE,EACtB,KAAM,CAAE,QAAS,CAAE,EACnB,WAAYK,EACZ,YAAaC,EACb,OAAQC,GAERE,GAAA,cAACI,EAAA,CAAa,GAAI,CAAC,CAACf,GAChBW,GAAA,cAACK,GAAA,IAAY,CACjB,EACAL,GAAA,cAACI,EAAA,CACG,GAAI,CAACf,IAAkBC,GAAgB,CAACF,EAAM,OAE9CY,GAAA,cAACM,GAAA,IAAgB,CACrB,EACAN,GAAA,cAACO,GAAA,IAAS,CACd,CACJ,CAER,C2ChEA,OAAS,eAAAC,GAAa,aAAAC,GAAW,WAAAC,GAAS,UAAAC,GAAQ,YAAAC,OAAgB,QAClE,OACI,kBAAAC,GACA,aAAAC,GACA,YAAAC,GACA,UAAAC,GACA,WAAAC,OACG,iBCPQ,SAARC,GAA+BC,EAAgBC,EAAY,CAAlE,IAAAC,EAAAC,EACI,IAAMC,EAAWH,EAAK,KAEtB,GAAI,CAACD,EAAQ,MAAO,GAEpB,GAAII,EAAU,CACV,GAAM,CAACC,EAAMC,CAAO,EAAIF,EAAS,MAAM,GAAG,EAC1C,GAAIC,GAAQC,EAAS,CACjB,IAAMC,EAAgBP,EAAO,MAAM,GAAG,EAAE,IAAIQ,GAAKA,EAAE,KAAK,CAAC,EAUzD,GARID,EAAc,SAAS,GAAG,GAC1BA,EAAc,KAAKE,GAAQ,CACvB,GAAIA,EAAK,SAAS,IAAI,EAAG,CACrB,GAAM,CAACC,CAAQ,EAAID,EAAK,MAAM,GAAG,EACjC,OAAOL,EAAS,WAAWM,CAAQ,CACvC,CACA,OAAOD,EAAK,YAAY,IAAML,EAAS,YAAY,CACvD,CAAC,EACY,MAAO,EAC5B,CACJ,CAEA,IAAMO,GAAWT,EAAAD,EAAK,OAAL,KAAAC,EAAa,GAC9B,GAAI,CAACS,EACD,MAAO,GAGX,IAAMC,IAAUT,EAAAQ,EAAS,MAAM,GAAG,EAAE,IAAI,IAAxB,YAAAR,EAA2B,gBAAiB,GAC5D,MAAI,GAAAS,GACsBZ,EAAO,MAAM,GAAG,EAAE,IAAIQ,GAAKA,EAAE,KAAK,EAAE,YAAY,CAAC,EAChC,KAAKK,GACpCA,EAAI,WAAW,GAAG,EACXA,EAAI,MAAM,CAAC,IAAMD,EAErB,EACV,EAIT,CC3BA,IAAME,GAAiB,WACjBC,GAAiB,KAAU,GAAK,IAK/B,SAASC,GAAgBC,EAAoB,CAChD,MAAO,GAAGA,EAAK,IAAI,IAAIA,EAAK,IAAI,IAAIA,EAAK,YAAY,IAAIA,EAAK,IAAI,EACtE,CAEA,SAASC,GAAWC,EAA6B,CAC7C,MAAO,GAAGL,EAAc,GAAGK,CAAW,EAC1C,CAKO,SAASC,GACZD,EACAE,EACI,CACJ,GAAI,CACA,aAAa,QAAQH,GAAWC,CAAW,EAAG,KAAK,UAAUE,CAAO,CAAC,CACzE,MAAQ,CAER,CACJ,CAKO,SAASC,GAAYH,EAA8C,CACtE,GAAI,CACA,IAAMI,EAAM,aAAa,QAAQL,GAAWC,CAAW,CAAC,EACxD,GAAI,CAACI,EAAK,OAAO,KAEjB,IAAMF,EAA4B,KAAK,MAAME,CAAG,EAGhD,OAAI,KAAK,IAAI,EAAIF,EAAQ,UAAYN,IACjCS,GAAcL,CAAW,EAClB,MAGJE,CACX,MAAQ,CACJ,OAAO,IACX,CACJ,CAKO,SAASI,GACZN,EACAO,EACI,CACJ,GAAI,CACA,IAAMH,EAAM,aAAa,QAAQL,GAAWC,CAAW,CAAC,EACxD,GAAI,CAACI,EAAK,OACV,IAAMF,EAA4B,KAAK,MAAME,CAAG,EAChDF,EAAQ,cAAgBK,EACxBL,EAAQ,UAAY,KAAK,IAAI,EAC7B,aAAa,QAAQH,GAAWC,CAAW,EAAG,KAAK,UAAUE,CAAO,CAAC,CACzE,MAAQ,CAER,CACJ,CAKO,SAASG,GAAcL,EAA2B,CACrD,GAAI,CACA,aAAa,WAAWD,GAAWC,CAAW,CAAC,CACnD,MAAQ,CAER,CACJ,CCnDO,IAAMQ,GAAN,KAAwC,CAS3C,YAAYC,EAAsB,CANlC,KAAQ,YAAc,EACtB,KAAQ,WAAoC,KAC5C,KAAQ,QAAU,GAClB,KAAQ,cAAqC,KAC7C,KAAQ,cAAsC,KAG1C,KAAK,OAASA,EACd,KAAK,aAAeC,GAAkBC,GAAOF,EAAO,YAAY,EAChE,KAAK,eAAe,EACpB,KAAK,YAAc,CACvB,CAMQ,oBAA8B,CA3D1C,IAAAG,EA4DQ,QACIA,EAAA,KAAK,OAAO,YAAZ,YAAAA,EAAuB,QAAS,aAChC,KAAK,OAAO,WAAa,OAEjC,CAEA,MAAM,OACFC,EACAC,EAAU,CAAC,EACU,CArE7B,IAAAF,EAAAG,EAsEQ,GAAI,CACA,GAAI,GAACH,EAAA,KAAK,OAAO,cAAZ,MAAAA,EAAyB,WAAY,KAAK,YAAc,EACzD,MAAM,IAAII,EACN,KAAK,aAAa,+CAEtB,EAIJ,OAFAD,EAAAD,EAAQ,oBAAR,MAAAC,EAAA,KAAAD,EAA4BD,GAExB,KAAK,mBAAmB,EACjB,MAAM,KAAK,gBAAgBA,EAAMC,CAAO,EAE5C,MAAM,KAAK,aAAaD,EAAMC,CAAO,CAChD,OAASG,EAAO,CACZ,MAAM,KAAK,YAAYA,CAAK,CAChC,CACJ,CAKA,OAAc,CACN,KAAK,aACL,KAAK,WAAW,MAAM,EACtB,KAAK,WAAa,KAE1B,CAKA,OAAc,CACN,KAAK,UACT,KAAK,QAAU,GACf,KAAK,cAAgB,IAAI,QAAcC,GAAW,CAC9C,KAAK,cAAgBA,CACzB,CAAC,EACL,CAKA,QAAe,CAhHnB,IAAAN,EAiHa,KAAK,UACV,KAAK,QAAU,IACfA,EAAA,KAAK,gBAAL,MAAAA,EAAA,WACA,KAAK,cAAgB,KACrB,KAAK,cAAgB,KACzB,CAEA,IAAI,UAAoB,CACpB,OAAO,KAAK,OAChB,CAKA,MAAM,eAAeC,EAAqC,CACtD,IAAMM,EAAcC,GAAgBP,CAAI,EAClCQ,EAAUC,GAAYH,CAAW,EACvC,GAAKE,EAEL,IAAI,CACA,MAAM,KAAK,qBAAqB,CAC5B,OAAQ,kBACR,SAAU,KAAK,OAAO,SACtB,IAAKA,EAAQ,IACb,SAAUA,EAAQ,QACtB,CAAC,CACL,MAAQ,CAER,CACAE,GAAcJ,CAAW,EAC7B,CAIA,MAAc,aACVN,EACAC,EACqB,CAtJ7B,IAAAF,EAAAG,EAwJQ,IAAMS,EAAgB,MAAM,KAAK,gBAAgBX,CAAI,EAGrD,KAAK,cAGL,IAAMY,EAAiB,MAAM,KAAK,mBAC9BD,EAAc,UACdX,EACAC,CACJ,EAEA,GAAI,CAACW,EAAe,GAChB,MAAM,IAAI,MAAM,UAAUA,EAAe,MAAM,EAAE,EAKrD,GAJIX,EAAQ,aACRF,EAAAE,EAAQ,uBAAR,MAAAF,EAAA,KAAAE,EAA+BD,EAAMW,EAAc,MAEvDX,EAAK,IAAMW,EAAc,KACrBT,EAAAF,EAAK,YAAL,MAAAE,EAAgB,KAAM,CACtB,IAAMW,EAAyB,MAAM,KAAK,gBACtCb,EAAK,UAAU,KACf,EACJ,EACMc,EAA0B,MAAM,KAAK,mBACvCD,EAAuB,UACvBb,EAAK,UAAU,KACfC,EACA,EACJ,EACA,GAAI,CAACa,EAAwB,GACzB,MAAM,IAAI,MAAM,UAAUA,EAAwB,MAAM,EAAE,EAE9Dd,EAAK,UAAU,IAAMa,EAAuB,GAChD,CACA,MAAO,CACH,IAAKF,EAAc,IACnB,KAAAX,EACA,WAAYY,EAAe,MAC/B,CACJ,CAIA,MAAc,gBACVZ,EACAC,EACqB,CAtM7B,IAAAF,EAAAG,EAAAa,EAAAC,EAAAC,EAuMQ,IAAMX,EAAcC,GAAgBP,CAAI,EAClCkB,IACFnB,EAAA,KAAK,OAAO,YAAZ,YAAAA,EAAuB,QAAS,eAC/BG,EAAA,KAAK,OAAO,UAAU,UAAtB,KAAAA,EAAiC,IAElCiB,EACAC,EACAC,EACAC,EAAiC,CAAC,EAClCC,EAAY,GAGVC,EAAkBN,EAAUT,GAAYH,CAAW,EAAI,KAE7D,GAAIkB,EAAiB,CACjBL,EAAMK,EAAgB,IACtBJ,EAAWI,EAAgB,SAC3BH,EAAWG,EAAgB,SAG3B,GAAI,CAUAF,GARI,MAAM,KAAK,qBACP,CACI,OAAQ,sBACR,SAAU,KAAK,OAAO,SACtB,IAAAH,EACA,SAAAC,CACJ,CACJ,GACyB,MAC7BG,EAAY,EAChB,MAAQ,CAEJ,QAAQ,KACJ,4DACJ,EACAb,GAAcJ,CAAW,CAC7B,CACJ,CAEA,GAAIiB,EAAW,CACX,IAAME,IACFV,EAAA,KAAK,OAAO,YAAZ,YAAAA,EAAuB,QAAS,YAC1B,KAAK,OAAO,UAAU,eACtB,OAEJW,EACF,MAAM,KAAK,qBAA4C,CACnD,OAAQ,iBACR,KAAM1B,EAAK,KACX,KAAMA,EAAK,KACX,KAAMA,EAAK,KACX,SAAU,KAAK,OAAO,SACtB,YAAa,KAAK,OAAO,YACzB,qBAAsB,KAAK,OAAO,qBAClC,GAAG,KAAK,OAAO,YACf,eAAAyB,CACJ,CAAC,EAELN,EAAMO,EAAa,IACnBN,EAAWM,EAAa,SACxBL,EAAWK,EAAa,SAEpBR,GACAS,GAAYrB,EAAa,CACrB,SAAU,KAAK,OAAO,SACtB,IAAAa,EACA,SAAAC,EACA,SAAAC,EACA,UAAW,KAAK,IAAI,EACpB,cAAe,CACnB,CAAC,CAET,CAGA,IAAMO,EAAa,KAAK,KAAK5B,EAAK,KAAOqB,CAAQ,EAC3CQ,EAAsB,IAAI,IAC5BP,EAAc,IAAIQ,GAAKA,EAAE,UAAU,CACvC,EACMC,EAAgBT,EAAc,OAAO,CAACU,EAAKF,IAAM,CACnD,IAAMG,GAASH,EAAE,WAAa,GAAKT,EAC7Ba,EAAM,KAAK,IAAID,EAAQZ,EAAUrB,EAAK,IAAI,EAChD,OAAOgC,GAAOE,EAAMD,EACxB,EAAG,CAAC,EAEAE,EAAgBJ,EAEpB,KAAK,cAGDA,EAAgB,GAAK9B,EAAQ,sBAC7BA,EAAQ,qBAAqBD,EAAM,CAC/B,OAAQ+B,EACR,MAAO/B,EAAK,KACZ,WAAa+B,EAAgB/B,EAAK,KAAQ,GAC9C,CAAC,EAGL,QAASoC,EAAa,EAAGA,GAAcR,EAAYQ,IAAc,CAC7D,GAAIP,EAAoB,IAAIO,CAAU,EAAG,SAGrC,KAAK,SAAW,KAAK,eACrB,MAAM,KAAK,cAGf,IAAMH,GAASG,EAAa,GAAKf,EAC3Ba,EAAM,KAAK,IAAID,EAAQZ,EAAUrB,EAAK,IAAI,EAC1CqC,EAAWrC,EAAK,MAAMiC,EAAOC,CAAG,EAGhCI,EACF,MAAM,KAAK,qBAAgD,CACvD,OAAQ,qBACR,SAAU,KAAK,OAAO,SACtB,IAAAnB,EACA,SAAAC,EACA,WAAAgB,EACA,cAAeC,EAAS,IAC5B,CAAC,EAGCE,EAAe,MAAM,KAAK,uBAC5BD,EAAa,UACbD,EACArC,EACAC,EACAkC,EACAnC,EAAK,IACT,EAEA,GAAI,CAACuC,EAAa,GACd,MAAM,IAAI,MACN,QAAQH,CAAU,8BAA8BG,EAAa,MAAM,EACvE,EAGJJ,GAAiBE,EAAS,KAGtBnB,GACAsB,GAAsBlC,EAAa6B,CAAa,CAExD,CAGA,IAAMM,EACF,MAAM,KAAK,qBAAiD,CACxD,OAAQ,sBACR,SAAU,KAAK,OAAO,SACtB,IAAAtB,EACA,SAAAC,CACJ,CAAC,EAECsB,EACF,MAAM,KAAK,qBAAgD,CACvD,OAAQ,qBACR,SAAU,KAAK,OAAO,SACtB,IAAAvB,EACA,SAAAC,EACA,MAAOqB,EAAkB,KAC7B,CAAC,EAYL,GATA/B,GAAcJ,CAAW,EAErBL,EAAQ,aACRe,EAAAf,EAAQ,uBAAR,MAAAe,EAAA,KAAAf,EAA+BD,EAAM0C,EAAiB,MAG1D1C,EAAK,IAAM0C,EAAiB,KAGxBzB,EAAAjB,EAAK,YAAL,MAAAiB,EAAgB,KAAM,CACtB,IAAMJ,EAAyB,MAAM,KAAK,gBACtCb,EAAK,UAAU,KACf,EACJ,EACMc,EAA0B,MAAM,KAAK,mBACvCD,EAAuB,UACvBb,EAAK,UAAU,KACfC,EACA,EACJ,EACA,GAAI,CAACa,EAAwB,GACzB,MAAM,IAAI,MAAM,UAAUA,EAAwB,MAAM,EAAE,EAE9Dd,EAAK,UAAU,IAAMa,EAAuB,GAChD,CAEA,MAAO,CACH,IAAK6B,EAAiB,IACtB,KAAA1C,EACA,WAAY,GAChB,CACJ,CAKQ,uBACJ2C,EACAN,EACArC,EACA,CAAE,qBAAA4C,EAAsB,sBAAAC,CAAsB,EAC9CC,EACAC,EACiB,CACjB,OAAO,IAAI,QAAQ,CAAC1C,EAAS2C,IAAW,CACpC,IAAMC,EAAM,IAAI,eAChB,KAAK,WAAaA,EAElBA,EAAI,OAAO,iBAAiB,WAAYC,GAAS,CAC7C,GAAIA,EAAM,kBAAoBN,EAAsB,CAChD,IAAMO,EAASL,EAA0BI,EAAM,OAC/CN,EAAqB5C,EAAM,CACvB,OAAAmD,EACA,MAAOJ,EACP,WAAaI,EAASJ,EAAiB,GAC3C,CAAC,CACL,CACIG,EAAM,kBAAoBL,GAC1BA,EAAsB,KAAK,WAAW,CAE9C,CAAC,EAEDI,EAAI,iBAAiB,OAAQ,IAAM,CA3a/C,IAAAlD,EA4agB,KAAK,WAAa,KACIkD,EAAI,QAAU,KAAOA,EAAI,OAAS,IAEpD5C,EACI,IAAI,SAAS4C,EAAI,SAAU,CACvB,OAAQA,EAAI,OACZ,QAAS,IAAI,QAAQ,CACjB,MAAMlD,EAAAkD,EAAI,kBAAkB,MAAM,IAA5B,KAAAlD,EAAiC,EAC3C,CAAC,CACL,CAAC,CACL,EAEAiD,EACI,IAAI,MACA,WAAWC,EAAI,MAAM,KAAKA,EAAI,UAAU,eAAeA,EAAI,YAAY,EAC3E,CACJ,CAER,CAAC,EAEDA,EAAI,iBAAiB,QAAS,IAAM,CAChC,KAAK,WAAa,KAClBD,EACI,IAAI,MACA,8CAA8CC,EAAI,MAAM,KAAKA,EAAI,UAAU,GAC/E,CACJ,CACJ,CAAC,EAEDA,EAAI,KAAK,MAAON,CAAG,EACnBM,EAAI,KAAKZ,CAAQ,CACrB,CAAC,CACL,CAOA,MAAc,qBACVe,EACU,CACV,IAAMC,EAAW,MAAM,MAAM,KAAK,OAAO,cAAe,CACpD,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAUD,CAAI,CAC7B,CAAC,EAED,GAAI,CAACC,EAAS,GAAI,CACd,IAAMC,EAAY,MAAMD,EAAS,KAAK,EACtC,MAAM,IAAI,MACNC,EAAU,SAAW,yBAAyBD,EAAS,MAAM,EACjE,CACJ,CAEA,OAAOA,EAAS,KAAK,CACzB,CAEA,MAAc,gBACVrD,EACAuD,EAC6B,CAC7B,IAAMC,EAAc,CAChB,KAAMxD,EAAK,KACX,KAAMA,EAAK,KACX,KAAMA,EAAK,KACX,YAAauD,EACb,SAAU,KAAK,OAAO,SACtB,YAAa,KAAK,OAAO,YACzB,qBAAsB,KAAK,OAAO,qBAClC,GAAG,KAAK,OAAO,WACnB,EAEMF,EAAW,MAAM,MAAM,KAAK,OAAO,cAAe,CACpD,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAUG,CAAW,CACpC,CAAC,EAED,GAAI,CAACH,EAAS,GAAI,CACd,IAAMC,EAAY,MAAMD,EAAS,KAAK,EACtC,MAAM,IAAIlD,EACNmD,EAAU,SAAW,KAAK,aAAa,0CAE3C,CACJ,CAIA,OAFa,MAAMD,EAAS,KAAK,CAGrC,CAEA,MAAc,mBACVV,EACA3C,EACA,CAAE,qBAAA4C,EAAsB,sBAAAC,CAAsB,EAC9CU,EACiB,CACjB,OAAO,IAAI,QAAQ,CAAClD,EAAS2C,IAAW,CACpC,IAAMC,EAAM,IAAI,eAEhBA,EAAI,OAAO,iBAAiB,WAAYC,GAAS,CAEzCA,EAAM,kBACNN,GACA,CAACW,GAEDX,EAAqB5C,EAAwB,CACzC,OAAQkD,EAAM,OACd,MAAOA,EAAM,MACb,WAAaA,EAAM,OAASA,EAAM,MAAS,GAC/C,CAAC,EAGDA,EAAM,kBACNL,GACA,CAACU,GAEDV,EAAsB,KAAK,WAAW,CAE9C,CAAC,EAEDI,EAAI,iBAAiB,OAAQ,IAAM,CAtiB/C,IAAAlD,EAAAG,EAAAa,EAuiBsCkC,EAAI,QAAU,KAAOA,EAAI,OAAS,IAGpD5C,EACI,IAAI,SAAS4C,EAAI,SAAU,CACvB,OAAQA,EAAI,OACZ,QACI,KAAK,OAAO,WAAa,QACnB,IAAI,QAAQ,CACR,MACIlD,EAAAkD,EAAI,kBAAkB,MAAM,IAA5B,KAAAlD,EACA,EACR,CAAC,EACD,MACd,CAAC,CACL,EAEAiD,EACI,IAAI7C,EACAsD,EAAE,KAAK,aAAa,YAAa,CAC7B,OAAQ,OAAOR,EAAI,MAAM,EACzB,YAAY/C,EAAA+C,EAAI,aAAJ,KAAA/C,EAAkB,GAC9B,SAASa,EAAAkC,EAAI,eAAJ,KAAAlC,EAAoB,EACjC,CAAC,wBAEL,CACJ,CAER,CAAC,EAEDkC,EAAI,iBAAiB,QAAS,IAAG,CArkB7C,IAAAlD,EAskBgB,OAAAiD,EACI,IAAI7C,EACAsD,EAAE,KAAK,aAAa,yBAA0B,CAC1C,OAAQ,OAAOR,EAAI,MAAM,EACzB,YAAYlD,EAAAkD,EAAI,aAAJ,KAAAlD,EAAkB,EAClC,CAAC,wBAEL,CACJ,EACJ,EAEAkD,EAAI,KAAK,MAAON,CAAG,EACf,KAAK,OAAO,WAAa,SACzBM,EAAI,iBAAiB,iBAAkB,WAAW,EACtDA,EAAI,KAAKjD,CAAI,CACjB,CAAC,CACL,CAEA,gBAA0B,CAxlB9B,IAAAD,EA0lBQ,IAAM2D,EADW,CAAC,gBAAiB,UAAU,EACpB,OAAOvC,GAAO,CAAC,KAAK,OAAOA,CAAG,CAAC,EAGxD,GAAIuC,EAAQ,OAAS,EACjB,MAAM,IAAIvD,EACNsD,EAAE,KAAK,aAAa,6BAA8B,CAC9C,QAASC,EAAQ,KAAK,IAAI,CAC9B,CAAC,yBAEL,EAIJ,GAAI,CAAC,OAAO,OAAOC,EAAY,EAAE,SAAS,KAAK,OAAO,QAAQ,EAC1D,MAAM,IAAIxD,EACNsD,EAAE,KAAK,aAAa,gBAAiB,CACjC,SAAU,OAAO,KAAK,OAAO,QAAQ,EACrC,aAAc,OAAO,OAAOE,EAAY,EAAE,KAAK,IAAI,CACvD,CAAC,qBAEL,EAIJ,GAAI,CACA,IAAI,IAAI,KAAK,OAAO,aAAa,CACrC,OAASC,EAAG,CACR,MAAM,IAAIzD,EACNsD,EAAE,KAAK,aAAa,qBAAsB,CACtC,cAAe,OAAO,KAAK,OAAO,aAAa,EAC/C,MAAO,OAAOG,CAAC,CACnB,CAAC,qBAEL,CACJ,CAGA,KAAI7D,EAAA,KAAK,OAAO,YAAZ,YAAAA,EAAuB,QAAS,MAChC,MAAM,IAAII,EACN,6FAEJ,EAIJ,GAAI,KAAK,OAAO,YAAa,CACzB,GAAM,CAAE,YAAA0D,EAAa,OAAAC,CAAO,EAAI,KAAK,OAAO,YAE5C,GAAID,IAAgB,QAAaA,GAAe,EAC5C,MAAM,IAAI1D,EACN,KAAK,aAAa,gDAEtB,EAGJ,GACI2D,GACA,CAAC,wGAAwG,KACrGA,CACJ,EAEA,MAAM,IAAI3D,EACNsD,EAAE,KAAK,aAAa,oBAAqB,CACrC,OAAQ,OAAOK,CAAM,CACzB,CAAC,yBAEL,CAER,CAEA,MAAO,EACX,CAEQ,YAAY1D,EAAuB,CAEvC,GAAIA,aAAiBD,EAAa,MAAMC,EAGxC,GAAIA,aAAiB,OAAS,SAAUA,EAAO,CAC3C,IAAM2D,EAAa3D,EAAc,KACjC,OAAQ2D,EAAW,CAEf,IAAK,eACL,IAAK,YACL,IAAK,wBACD,MAAM,IAAI5D,EACN,KAAK,aAAa,qCAEtB,EAGJ,IAAK,cACL,IAAK,wBACD,MAAM,IAAIA,EACN,KAAK,aAAa,kCAElB,EACJ,EAEJ,IAAK,gCACD,MAAM,IAAIA,EACN,KAAK,aAAa,0DAElB,EACJ,EAGJ,IAAK,qBACL,IAAK,qBACD,MAAM,IAAIA,EACN,KAAK,aAAa,qCAEtB,EAGJ,IAAK,iBACD,MAAM,IAAIA,EACN,KAAK,aAAa,oCAEtB,EAEJ,IAAK,oBACD,MAAM,IAAIA,EACN,KAAK,aAAa,uCAEtB,EAGJ,IAAK,gBACL,IAAK,qBACD,MAAM,IAAIA,EACN,KAAK,aAAa,gDAElB,EACJ,EAEJ,IAAK,yBACD,MAAM,IAAIA,EACN,KAAK,aAAa,uCAEtB,EAEJ,IAAK,+BACD,MAAM,IAAIA,EACN,KAAK,aAAa,6CAElB,EACJ,EAGJ,QACI,MAAM,IAAIA,EACNsD,EAAE,KAAK,aAAa,qBAAsB,CACtC,KAAM,OAAOM,CAAS,CAC1B,CAAC,yBAED,EACJ,CACR,CACJ,CAGA,MAAM,IAAI5D,EACNsD,EAAE,KAAK,aAAa,aAAc,CAC9B,QAAUrD,EAAgB,OAC9B,CAAC,yBAED,EACJ,CACJ,CACJ,EHxtBA,eAAe4D,GACXC,EACAC,EACqB,CACrB,QAASC,EAAU,EAAGA,GAAWD,EAAYC,IACzC,GAAI,CACA,OAAO,MAAMF,EAAG,CACpB,OAASG,EAAO,CACZ,GAAID,IAAYD,EAAY,MAAME,CACtC,CAEJ,MAAM,IAAI,MAAM,6BAA6B,CACjD,CAEe,SAARC,GAAiC,CACpC,OAAAC,EAAS,IACT,KAAAC,EAAO,GACP,KAAAC,EAAO,GACP,MAAOC,EAAY,EACnB,aAAAC,EAAe,GACf,aAAAC,EAAe,GACf,uBAAAC,EAAyB,GACzB,YAAAC,EACA,eAAAC,EAAiB,GACjB,eAAAC,EAAiB,kBAA2C,EAC5D,QAASC,EACT,OAAQC,EACR,MAAAC,EAAQ,CAAC,EACT,WAAAC,EAAa,CAAC,EACd,WAAAC,EACA,aAAcC,EACd,mBAAAC,EAAqB,IAAM,CAAC,EAC5B,YAAAC,EAAc,IAAM,CAAC,EACrB,aAAAC,EAAe,IAAM,CAAC,EACtB,gBAAAC,EAAkB,IAAM,CAAC,EACzB,iBAAAC,EAAmB,IAAM,CAAC,EAC1B,YAAAC,EAAc,IAAM,CAAC,EACrB,mBAAAC,EAAqB,IAAM,CAAC,EAC5B,YAAaC,EACb,kBAAAC,EAAoB,IAAM,CAAC,EAC3B,qBAAAC,EAAuB,IAAM,CAAC,EAC9B,sBAAAC,EAAwB,IAAM,CAAC,EAC/B,qBAAAC,EAAuB,IAAM,CAAC,EAC9B,sBAAAC,EAAwB,IAAM,CAAC,EAC/B,gBAAAC,EAAkB,IAAM,CAAC,EACzB,cAAAC,EAAgB,IAAM,CAAC,EACvB,eAAAC,EACA,SAAAC,GACA,cAAAC,GACA,aAAAC,GACA,YAAAC,GACA,qBAAAC,GAAuB,GACvB,WAAAxC,GACA,UAAAyC,CACJ,EAAoC,CAChC,IAAMC,GAAWC,GAAyB,IAAI,EACxC,CAACC,GAAcC,EAAe,EAAIC,GAAS,EAAK,EAChD,CAACC,GAAkBC,EAAmB,EAAIF,GAE9C,IAAI,GAAK,EACL,CAACG,GAAeC,EAAgB,EAAIJ,GAAwB,EAC5D,CAACK,GAAcC,EAAe,EAAIN,YAA6B,EAC/D,CAACO,GAAkBC,EAAmB,EAAIR,GAC5C,CAAC,CACL,EACM,CAACS,GAAaC,EAAc,EAAIV,GAAS,EAAE,EAC3C,CAACW,GAAaC,EAAc,EAAIZ,GAAS,CAAC,EAC1C,CAACa,GAAWC,EAAY,EAAId,GAAS,CAAC,EACtC,CAACe,GAAeC,EAAgB,EAAIhB,GAAS,CAAC,EAC9C,CAACiB,GAAYC,EAAa,EAAIlB,GAAS,CAAC,EAGxCmB,GAAStB,GAA2B,IAAI,EAExCuB,GAAkBvB,GAA0C,CAAC,CAAC,EAE9DwB,GAAgBxB,GAAO,CAAC,EACxB,CAACyB,GAAaC,EAAc,EAAIvB,GAAgC,IAAI,EACpE,CAACwB,GAAaC,EAAc,EAAIzB,GAA2B,CAAC,CAAC,EAG7D0B,GAAsB7B,GAAOI,EAAgB,EACnD0B,GAAU,IAAM,CACZD,GAAoB,QAAUzB,EAClC,EAAG,CAACA,EAAgB,CAAC,EAGrB0B,GAAU,IACC,IAAM,CACTD,GAAoB,QAAQ,QAAQE,GAAQC,GAAcD,CAAI,CAAC,CACnE,EACD,CAAC,CAAC,EAEL,IAAME,GAAQC,GACV,IAAOxE,EAAO,EAAI,KAAK,IAAIE,EAAW,CAAC,EACvC,CAACF,EAAME,CAAS,CACpB,EACMuE,GAAWD,GAAQ,IAAOxE,EAAO,GAAQuE,GAAQ,EAAI,CAACA,GAAOvE,CAAI,CAAC,EAElE0E,GAAeF,GACjB,IAAMG,GAAkB9D,GAAA,KAAAA,EAAc+D,GAAO9D,CAAoB,EACjE,CAACD,EAAYC,CAAoB,CACrC,EAEM+D,GAAgBL,GAAQ,IAAM,CAChC,IAAMM,EAAyB,OAAO,OAAO9B,EAAgB,EAC7D,GAAI,CAAC8B,EAAuB,OAAQ,MAAO,GAE3C,IAAMC,EAAeD,EAAuB,OACxC,CAACE,EAAGC,IAAMD,EAAKC,EAAE,OAASA,EAAE,MAAS,IACrC,CACJ,EACA,OAAO,KAAK,MAAMF,EAAeD,EAAuB,MAAM,CAClE,EAAG,CAAC9B,EAAgB,CAAC,EAEfkC,EAAsBV,GAAoC,IAAM,CA/J1E,IAAAW,EAAAC,EAAAC,EAgKQ,OAAI/D,IAAoB,GACb,CAAE,QAAS,GAAM,SAAU,QAAS,QAAS,QAAS,EAE7D,OAAOA,GAAoB,UAAYA,IAAoB,KACpD,CACH,GAAGA,EACH,SAAS6D,EAAA7D,EAAgB,UAAhB,KAAA6D,EAA2B,GACpC,UAAUC,EAAA9D,EAAgB,WAAhB,KAAA8D,EAA4B,QACtC,SAASC,EAAA/D,EAAgB,UAAhB,KAAA+D,EAA2B,QACxC,EAEG,CAAE,QAAS,GAAO,SAAU,QAAS,QAAS,QAAS,CAClE,EAAG,CAAC/D,CAAe,CAAC,EAEdgE,GAAkBC,GACnBlB,GAAyB,CA/KlC,IAAAc,EAgLYnB,GAAeK,CAAI,GACnBc,EAAAD,EAAoB,SAApB,MAAAC,EAAA,KAAAD,EAA6Bb,EACjC,EACA,CAACa,CAAmB,CACxB,EAEMM,GAAqBD,GAAY,IAAM,CACzCrB,GAAeuB,GAAQ,CACnB,GAAIA,EAAK,SAAW,EAAG,OAAOA,EAC9B,GAAM,CAACC,EAAM,GAAGC,CAAI,EAAIF,EACxB,kBAAW,IAAMH,GAAgBI,CAAI,EAAG,CAAC,EAClCC,CACX,CAAC,CACL,EAAG,CAACL,EAAe,CAAC,EAEdM,GAAmBL,GAAY,IAAM,CA/L/C,IAAAJ,EAgMQ,IAAMU,EAAU9B,GAChBC,GAAe,IAAI,EACnBwB,GAAmB,EACfK,KAASV,EAAAD,EAAoB,WAApB,MAAAC,EAAA,KAAAD,EAA+BW,GAChD,EAAG,CAAC9B,GAAayB,GAAoBN,CAAmB,CAAC,EAEnDY,GAAgBP,GAClB,CAACQ,EAAyBC,IAAsB,CAvMxD,IAAAb,GAAAC,GAAAC,GAwMY,GAAI,CAACtB,GAAa,OAElB,IAAMkC,EAAWlC,GACXmC,EACFF,KACAb,GAAAD,EAAoB,SAApB,YAAAC,GAA4B,WAC5Bc,EAAS,KACPE,GAAUf,GAAAF,EAAoB,SAApB,YAAAE,GAA4B,QAKxCgB,EACJ,IACKD,IAAY,QAAaD,IAAeD,EAAS,OAClDF,EAAgB,WAAW,OAAO,EACpC,CAEE,IAAMM,GAAMC,GAAcP,CAAe,EACzCK,EAAO,IAAI,KAAK,CAACC,EAAG,EAAG,CAAE,KAAMH,CAAW,CAAC,CAC/C,MACIE,EAAOE,GAAcP,CAAe,EAGxC,IAAMQ,GAAUC,GACZJ,EACAH,EACAf,EAAoB,MACxB,EAGAvC,GAAoB8C,IAChBgB,GAAiBhB,GAAMQ,EAAS,GAAIM,EAAO,CAC/C,GAEAlB,GAAAH,EAAoB,SAApB,MAAAG,GAAA,KAAAH,EAA6BqB,GAASN,GAEtCjC,GAAe,IAAI,EACnBwB,GAAmB,CACvB,EACA,CAACzB,GAAamB,EAAqBM,EAAkB,CACzD,EAEMkB,GAAcnB,GAChB,CAACoB,EAAgBJ,IAA4B,CACzC5D,GAAoB8C,GAAQ,CACxB,IAAMC,EAAO,IAAI,IAAID,CAAI,EACzB,OAAAC,EAAK,IAAIiB,EAAQJ,CAAO,EACjBb,CACX,CAAC,CACL,EACA,CAAC,CACL,EAIAtB,GAAU,IAAM,CACZ,GAAIL,IAAeE,GAAY,SAAW,EAAG,OAC7C,GAAM,CAACyB,EAAM,GAAGC,CAAI,EAAI1B,GACxBC,GAAeyB,CAAI,EACnBL,GAAgBI,CAAI,CACxB,EAAG,CAAC3B,GAAaE,GAAaqB,EAAe,CAAC,EAE9C,IAAMsB,GAAUrB,GACXsB,GAAoB,CACjB1D,GAAe0D,CAAO,EAElBpG,GAAcA,EAAaoG,CAAO,CAC1C,EACA,CAACpG,CAAY,CACjB,EAEMqG,GAASvB,GACVsB,GAAoB,CACbnG,GAAgBA,EAAemG,CAAO,CAC9C,EACA,CAACnG,CAAc,CACnB,EACA,SAASqG,GACLC,EACyB,CACzB,OAAOA,EAAM,OAAS,GAAK,OAAQA,EAAM,CAAC,CAC9C,CACA,eAAeC,IAAa,CACxBzE,GAAgB,EAAK,EACrB0E,GAAW,CACf,CACA,eAAeC,GAAcH,EAAkC,CAC3D,IAAMI,EAAgBL,GAAsBC,CAAK,EAC3CA,EACAA,EAAM,IAAI3C,GAAQgD,GAAiBhD,CAAI,CAAC,EAC9C,OAAO,MAAMiD,GAAcF,CAAa,CAC5C,CACA,SAASG,GAAwBP,EAAkC,CAE/DtE,GAAiB,QAAQ2B,GAAQC,GAAcD,CAAI,CAAC,EAEpD,IAAMmD,EAAW,IAAI,IACrB,GAAIT,GAAsBC,CAAK,EAC3B,QAAWS,KAAKT,EACZQ,EAAS,IAAIC,EAAE,GAAIA,CAAC,MAGxB,SAAWA,KAAKT,EAAO,CACnB,IAAMU,EAAiBL,GAAiBI,CAAC,EACzCD,EAAS,IAAIE,EAAe,GAAIA,CAAc,CAClD,CAEJ/E,GAAoB6E,CAAQ,CAChC,CACA,IAAMG,GAA0BC,GAAqB,CAEjD,IAAMC,EAAc,IAAI,IAAInF,EAAgB,EAEtCoF,EAAe,IAAI,IACrB,MAAM,KAAKD,EAAY,OAAO,CAAC,EAC1B,IAAIE,GAAMA,EAAU,GAAG,EACvB,OAAO,OAAO,CACvB,EAGMC,EAAmC,CAAC,EAE1C,QAAW3D,KAAQuD,EAAU,CAEzB,GAAIC,EAAY,MAAQtD,GAAO,CAC3BuC,GAAOpC,GAAa,qBAAqB,EACzC,KACJ,CAEA,IAAMgD,EAAiBL,GAAiBhD,CAAI,EAE5C,GAAI,CAAC4D,GAAclI,EAAQsE,CAAI,EAAG,CAC9BuC,GACIsB,EAAExD,GAAa,oBAAqB,CAAE,KAAML,EAAK,IAAK,CAAC,CAC3D,EACAhD,EAAmBgD,EAAMtE,CAAM,EAC/BuE,GAAcoD,CAAc,EAC5B,QACJ,CAEA,GACIpH,GAAA,MAAAA,EAAa,OACbA,GAAA,MAAAA,EAAa,OACb,CAAC6H,GAAc9D,EAAM/D,CAAW,EAClC,CACEsG,GACIsB,EAAExD,GAAa,iBAAkB,CAC7B,KAAML,EAAK,KACX,KAAM,OAAO/D,EAAY,IAAI,EAC7B,KAAM,OAAOA,EAAY,IAAI,CACjC,CAAC,CACL,EACAgE,GAAcoD,CAAc,EAC5B,QACJ,CAEA,GAAIG,EAAY,IAAIH,EAAe,EAAE,EAAG,CACpCZ,GACIoB,EAAExD,GAAa,uBAAwB,CAAE,KAAML,EAAK,IAAK,CAAC,CAC9D,EACAC,GAAcoD,CAAc,EAC5B,QACJ,CAEA,IAAMU,GAAW/D,EAAa,IAC9B,GAAI+D,IAAWN,EAAa,IAAIM,EAAO,EAAG,CACtCtB,GACIoB,EAAExD,GAAa,8BAA+B,CAC1C,IAAK0D,EACT,CAAC,CACL,EACA9D,GAAcoD,CAAc,EAC5B,QACJ,CAEAG,EAAY,IAAIH,EAAe,GAAIA,CAAc,EACjDM,EAAe,KAAKN,CAAc,EAC9BU,IAASN,EAAa,IAAIM,EAAO,CACzC,CASA,GANAzF,GAAoBkF,CAAW,EAG3BG,EAAe,QAAQpG,EAAgBoG,CAAc,EAGrD9C,EAAoB,SAAW8C,EAAe,OAAQ,CACtD,IAAMK,EAAYL,EAAe,OAAOP,GACpCA,EAAE,KAAK,WAAW,QAAQ,CAC9B,EAEA,GAAIY,EAAU,OAAS,GACnB,GACInD,EAAoB,WAAa,UACjCmD,EAAU,SAAW,EAErB/C,GAAgB+C,EAAU,CAAC,CAAC,UACrBnD,EAAoB,WAAa,SAAU,CAElD,GAAM,CAACoD,EAAO,GAAG3C,EAAI,EAAI0C,EACzB/C,GAAgBgD,CAAK,EACjB3C,GAAK,QACLzB,GAAeuB,IAAQ,CAAC,GAAGA,GAAM,GAAGE,EAAI,CAAC,CAEjD,EAER,CAEAnD,GAAgB,EAAK,CACzB,EAEM+F,GAAmBhD,GACpBoB,GAAmB,CAChB,IAAMtC,EAAO3B,GAAiB,IAAIiE,CAAM,EACxC,GAAI,CAACtC,EAAM,OAGXC,GAAcD,CAAI,EAElB,IAAMmE,EAAuB,IAAI,IAAI9F,EAAgB,EACrD8F,EAAqB,OAAO7B,CAAM,EAElChE,GAAoB6F,CAAoB,EACxCvH,EAAaoD,CAAI,CACrB,EACA,CAACpD,EAAcyB,EAAgB,CACnC,EAEM+F,GAAgBlD,GAClB,MAAOyB,GAA4B,CAC/B,GAAI,CACA,OAAO,MAAM,QAAQ,IACjBA,EAAM,IAAI,MAAM0B,GACL,MAAMC,GAAaD,CAAO,CACpC,CACL,CACJ,OAAS7I,EAAO,CACZ,MAAAmH,EAAM,QAAQ3C,GACVuC,GACIsB,EAAExD,GAAa,qBAAsB,CACjC,KAAML,EAAK,IACf,CAAC,CACL,CACJ,EACMxE,CACV,CACJ,EACA,CAAC+G,EAAO,CACZ,EAEMgC,GAAqBrD,GACvB,MAAOyB,GAA4B,CAE/B,IAAM6B,EAAc7B,EAAM,OAAO,CAAChC,EAAGC,IAAM,CACvC,IAAI6D,GAAgB,EACpB,IAAI1G,GAAA,YAAAA,EAAW,QAAS,YAAa,CACjC,IAAM2G,GAAKC,GAAgB/D,CAAC,EACtBgE,GAAUC,GAAYH,EAAE,EAC1BE,IAAA,MAAAA,GAAS,gBACTH,GAAgBG,GAAQ,cAEhC,CACA,OAAAjE,EAAEC,EAAE,EAAE,EAAI,CACN,GAAIA,EAAE,GACN,OAAQ6D,GACR,MAAO7D,EAAE,IACb,EACOD,CACX,EAAG,CAAC,CAAqB,EACzB/B,GAAoB4F,CAAW,EAG/B,IAAMM,EAAQnC,EAAM,OAAO,CAACoC,EAAK3B,IAAM2B,EAAM3B,EAAE,KAAM,CAAC,EACtD9D,GAAcwF,CAAK,EACnBrF,GAAc,QAAUqF,EACxB,IAAME,EAAkB,OAAO,OAAOR,CAAW,EAAE,OAC/C,CAACO,EAAaL,IAAqBK,EAAML,EAAG,OAC5C,CACJ,EACA,OAAAtF,GAAiB4F,CAAe,EAChChG,GAAe,CAAC,EAChBE,GAAa,CAAC,EACdM,GAAgB,QAAU,CAAC,EAEpB/B,EAAiB,MAAMA,EAAekF,CAAK,EAAIA,CAC1D,EACA,CAAClF,EAAgBM,CAAS,CAC9B,EACMkF,GAAgB/B,GAClB,MAAO+D,EAA6C,SAAc,CAC9D,GAAI,CAAC5G,GAAiB,MAAQ,CAAC4G,EAAc,OAC7CvG,YAAoC,EACpCI,GAAe,EAAE,EACjB,IAAMoG,EAAY,CAACD,EACbE,EAAgBF,GAEhB,MAAM,KAAK5G,GAAiB,OAAO,CAAC,EAC1C,GAAI,CACA,IAAM+G,EAAkBlJ,EAClB,MAAMkI,GAAce,CAAa,EACjCA,EACAE,EAAiB,MAAMd,GAAmBa,CAAe,EAEzDE,EAAM,IAAIC,GAAY,CACxB,SAAA7H,GACA,cAAAC,GACA,YAAa,CACT,SAAAyC,GACA,OAAA1E,EACA,YACIO,GAAA,MAAAA,EAAa,OAAQA,GAAA,MAAAA,EAAa,MAC5BuJ,GACIvJ,EAAY,KACZA,EAAY,IAChB,EACA,MACd,EACA,YAAA4B,GACA,qBAAAC,GACA,UAAAC,EACA,aAAcsC,EAClB,CAAC,EAGDd,GAAO,QAAU+F,EACjB9F,GAAgB,QAAU,CAAC,CAAE,KAAM,KAAK,IAAI,EAAG,MAAO,CAAE,CAAC,EAGzD,IAAMuD,IACFhF,GAAA,YAAAA,EAAW,QAAS,YACdsH,EAAe,OAAOjC,IAAK,CAACA,GAAE,GAAG,EACjCiC,EAGJI,GAAgB,CAClB,kBAAAvI,EACA,qBAAsB,CAClB8C,GACA0F,KAKC,CAjiBzB,IAAA5E,IAmiB4BA,GAAAvB,GAAO,UAAP,MAAAuB,GAAgB,WAEpBlC,GAAqBwC,KAA4B,CAC7C,GAAGA,GACH,CAACpB,GAAK,EAAE,EAAG,CACP,GAAGoB,GAAKpB,GAAK,EAAE,EACf,OAAQ0F,GAAS,MACrB,CACJ,EAAE,EAGF9G,GAAqBwC,IAA2B,CAC5C,IAAMuE,GAAc,OAAO,OAAOvE,EAAI,EAAE,OACpC,CAAC2D,GAAaL,KACVK,GAAML,GAAG,OACb,CACJ,EACAtF,GAAiBuG,EAAW,EAG5B,IAAMC,GAAM,KAAK,IAAI,EACrBpG,GAAgB,QAAQ,KAAK,CACzB,KAAMoG,GACN,MAAOD,EACX,CAAC,EAED,IAAME,GAASD,GAAM,IAOrB,GANApG,GAAgB,QACZA,GAAgB,QAAQ,OACnBsG,IACGA,GAAE,MAAQD,EAClB,EAEArG,GAAgB,QAAQ,QAAU,EAAG,CACrC,IAAMuG,GAASvG,GAAgB,QAAQ,CAAC,EAClCwG,GACFxG,GAAgB,QACZA,GAAgB,QAAQ,OAAS,CACrC,EACEyG,IACDD,GAAO,KAAOD,GAAO,MAAQ,IAClC,GAAIE,GAAU,EAAG,CACb,IAAMC,IACDF,GAAO,MAAQD,GAAO,OAASE,GACpCjH,GAAe,KAAK,IAAI,EAAGkH,EAAK,CAAC,EAEjC,IAAMC,GACF1G,GAAc,QAAUkG,GACxBO,GAAQ,GACRhH,GACI,KAAK,KAAKiH,GAAYD,EAAK,CAC/B,CAER,CACJ,CAEA,OAAO9E,EACX,CAAC,EAEDjE,EAAqB6C,GAAM0F,EAAQ,EACvC,EACA,qBAAArI,EACA,UAAA6H,EACA,QAAA3C,GACA,sBAAwB6D,IACpBhJ,EACIgJ,GACAf,EAAe,MACnB,CACR,EAWMgB,IAVgB,MAAM,QAAQ,IAChCtD,GAAc,IAAI/C,IACd1E,GACMF,GACI,IAAMkK,EAAI,OAAOtF,GAAMyF,EAAa,EACpCnK,EACJ,EACAgK,EAAI,OAAOtF,GAAMyF,EAAa,CACxC,CACJ,GACiC,IAAIa,IAAUA,GAAO,IAAI,EAC1D,OAAIpB,GAAW5H,EAAsB+I,EAAU,EAE/C9G,GAAO,QAAU,KACjBb,eAAuC,EAChC2H,EACX,OAAS7K,EAAO,CACZ+G,GAAS/G,EAAgB,OAAO,EAChC+D,GAAO,QAAU,KACjBb,WAAmC,EAEnC,MACJ,CACJ,EACA,CACIL,GACAnC,EACAkI,GACAG,GACA7G,GACAC,GACAyC,GACA1E,EACAO,GAAA,YAAAA,EAAa,KACbA,GAAA,YAAAA,EAAa,KACb4B,GACAC,GACAC,EACAT,EACAJ,EACAG,EACAkF,GACApF,EACAC,EACA9B,EACJ,CACJ,EACMiL,GAAerF,GAAY,IAAM,CAxpB3C,IAAAJ,GA0pBQA,EAAAvB,GAAO,UAAP,MAAAuB,EAAgB,QAGZvB,GAAO,UAAWxB,GAAA,YAAAA,EAAW,QAAS,aACtCM,GAAiB,QAAQ2B,GAAQ,CA9pB7C,IAAAc,GA+pBqBA,EAAAvB,GAAO,UAAP,MAAAuB,EAAgB,eAAed,EACxC,CAAC,EAGLT,GAAO,QAAU,KAGjBlB,GAAiB,QAAQ2B,GAAQC,GAAcD,CAAI,CAAC,EAEpDtB,YAAoC,EACpCJ,GAAoB,IAAI,GAAK,EAC7BM,GAAoB,CAAC,CAAC,EACtBI,GAAe,CAAC,EAChBE,GAAa,CAAC,EACdE,GAAiB,CAAC,EAClBE,GAAc,CAAC,CACnB,EAAG,CAACvB,GAAA,YAAAA,EAAW,KAAMM,EAAgB,CAAC,EAEhCmI,GAActF,GAAY,IAAM,CAjrB1C,IAAAJ,GAkrBQA,EAAAvB,GAAO,UAAP,MAAAuB,EAAgB,QAChBpC,WAAmC,CACvC,EAAG,CAAC,CAAC,EAEC+H,GAAevF,GAAY,IAAM,CAtrB3C,IAAAJ,GAurBQA,EAAAvB,GAAO,UAAP,MAAAuB,EAAgB,SAEhBtB,GAAgB,QAAU,CAAC,CAAE,KAAM,KAAK,IAAI,EAAG,MAAOL,EAAc,CAAC,EACrET,YAAoC,CACxC,EAAG,CAACS,EAAa,CAAC,EAEZ0D,GAAa3B,GAAY,IAAM,CACjC1D,EAAc,EACd+I,GAAa,CACjB,EAAG,CAACA,GAAc/I,CAAa,CAAC,EAEhC,MAAO,CACH,SAAAQ,GACA,cAAAO,GACA,iBAAAC,GACA,aAAAN,GACA,gBAAAC,GACA,aAAAkC,GACA,MAAOhC,GACP,SAAUiF,GACV,cAAAR,GACA,WAAAF,GACA,wBAAAM,GACA,WAAAL,GACA,aAAA0D,GACA,YAAAC,GACA,aAAAC,GACA,iBAAAvC,GACA,YAAAxE,GACA,gBAAAuB,GACA,iBAAAM,GACA,cAAAE,GACA,YAAAY,GACA,gBAAiBzE,IAAA,YAAAA,GAAc,SAC/B,mBAAoBA,IAAA,YAAAA,GAAc,YAClC,eAAgBA,IAAA,YAAAA,GAAc,QAC9B,OAAQ,CACJ,cAAA4C,GACA,iBAAA7B,GACA,cAAAsE,GACA,aAAAxE,GACA,gBAAAC,GACA,YAAAG,GACA,YAAAE,GACA,UAAAE,GACA,cAAAE,GACA,WAAAE,EACJ,EACA,MAAO,CACH,KAAA1D,EACA,KAAAC,EACA,WAAAN,GACA,UAAAyC,EACA,QAAAwE,GACA,mBAAA7F,EACA,YAAAC,EACA,gBAAAE,EACA,iBAAAC,EACA,YAAAC,EACA,eAAAZ,EACA,OAAAT,EACA,YAAAO,EACA,MAAAiE,GACA,aAAApE,EACA,aAAAC,EACA,uBAAAC,EACA,SAAAoE,GACA,MAAO,CACH,qBAAsB9D,EAAM,sBAAwBoK,GACpD,eAAgBpK,EAAM,gBAAkBqK,GACxC,kBAAmBrK,EAAM,mBAAqBsK,GAC9C,iBAAkBtK,EAAM,kBAAoBuK,GAC5C,iBAAkBvK,EAAM,kBAAoBqK,GAC5C,WAAYrK,EAAM,YAAcwK,EACpC,EACA,WAAAvK,EACA,YAAasE,CACjB,CACJ,CACJ,CIpwBe,SAARkG,GAA2B,CAC9B,OAAAC,EACA,MAAAC,EACA,SAAAC,EACA,wBAAAC,EACA,cAAAC,EACA,WAAAC,CACJ,EAQG,CACC,GAAM,CAAE,cAAAC,EAAe,aAAAC,EAAc,YAAAC,EAAa,cAAAC,CAAc,EAC5DT,GAAU,CAAC,EAEf,MAAO,CACH,OAAQM,EACR,QAASC,IAAiB,UAC1B,MAAOC,EACP,SAAUC,EACV,MAAO,MAAM,KAAKR,EAAM,OAAO,CAAC,EAAE,IAAIS,GAC3BA,CACV,EACD,SAAAR,EACA,wBAAAC,EACA,cAAAC,EACA,WAAAC,CACJ,CACJ,C3DDA,IAAOM,GAAQC,GACX,SAAsBC,EAAOC,EAAK,CAC9B,IAAMC,EAAiBC,GAAgB,CACnC,GAAGH,EACH,MAAO,CACH,GAAGA,EAAM,MACT,WAAYI,EAChB,CACJ,CAAC,EACKC,EAAYC,GAAU,CACxB,OAAQJ,EAAe,OACvB,MAAOA,EAAe,MACtB,SAAUA,EAAe,SACzB,cAAeA,EAAe,cAC9B,WAAYA,EAAe,WAC3B,wBAAyBA,EAAe,uBAC5C,CAAC,EAED,OAAAK,GAAoBN,EAAK,KAAO,CAC5B,UAAW,IAAMI,CACrB,EAAE,EAGEG,EAAA,cAACC,GAAY,SAAZ,CAAqB,MAAOP,GACzBM,EAAA,cAAC,OAAI,UAAU,sCACXA,EAAA,cAAC,OACG,UAAWE,EAAG,cAAe,CACzB,oCACI,CAACR,EAAe,MAAM,KAC1B,iCACIA,EAAe,MAAM,IAC7B,CAAC,EACD,MACIA,EAAe,MAAM,KACf,CAAE,YAAa,OAAQ,EACvB,QAGVM,EAAA,cAAC,WACG,kBAAgB,oBAChB,UAAWE,EACP,qCACIR,EAAe,MAAM,KACf,oBACA,eACV,yIACA,CACI,CAACA,EAAe,MAAM,WACjB,aAAc,EACfA,EAAe,MAAM,WAChB,eACL,CAACA,EAAe,MAAM,KAE1B,CAACA,EAAe,MAAM,WACjB,aAAc,EACfA,EAAe,MAAM,WAChB,eACLA,EAAe,MAAM,IAC7B,CACJ,GAEAM,EAAA,cAACG,EAAA,CACG,GAAIT,EAAe,MAAM,cAEzBM,EAAA,cAACI,GAAA,CACG,UAAWF,EACP,4HACA,CACI,+CACIR,EAAe,MAAM,IAC7B,CACJ,EACJ,CACJ,EACAM,EAAA,cAACG,EAAA,CAAa,GAAIT,EAAe,MAAM,MAAQ,GAC3CM,EAAA,cAAC,KACG,GAAG,oBACH,UAAWE,EACP,kEACA,CACI,6CACIR,EAAe,MAAM,IAC7B,CACJ,GAECW,EACGX,EAAe,aACV,iBACL,CACI,MAAOA,EAAe,MAAM,KAChC,CACJ,CACJ,CACJ,EACAM,EAAA,cAACM,GAAA,IAAQ,EAGRZ,EAAe,aACZA,EAAe,MAAM,YAAY,UAC7B,UACAM,EAAA,cAACO,GAAA,CACG,KAAMb,EAAe,YACrB,QACIA,EAAe,iBAEnB,OAAQA,EAAe,cAC3B,EAGRM,EAAA,cAACG,EAAA,CAAa,GAAI,CAACT,EAAe,MAAM,MACpCM,EAAA,cAAC,OACG,UAAWE,EACP,wGACJ,GAEAF,EAAA,cAAC,KACG,KAAM,uBACN,OAAQ,SACR,IAAI,sBACJ,UAAU,8CAEVA,EAAA,cAACG,EAAA,CACG,GAAIT,EAAe,MAAM,MAEzBM,EAAA,cAAC,OACG,IAAKQ,GACL,MAAO,GACP,OAAQ,GACR,IAAI,YACR,CACJ,EACAR,EAAA,cAACG,EAAA,CACG,GAAI,CAACT,EAAe,MAAM,MAE1BM,EAAA,cAAC,OACG,IAAKS,GACL,MAAO,GACP,OAAQ,GACR,IAAI,aACR,CACJ,CACJ,EACAT,EAAA,cAAC,KACG,KAAM,qBACN,OAAQ,SACR,IAAI,sBACJ,UAAU,yEAEVA,EAAA,cAAC,QACG,UAAWE,EACP,8EACA,CACI,6CACIR,EAAe,MACV,IACb,CACJ,GAGIA,EAAe,aACV,QACP,GACN,EACAM,EAAA,cAACG,EAAA,CACG,GAAIT,EAAe,MAAM,MAEzBM,EAAA,cAAC,OACG,IAAKU,GACL,MAAO,GACP,OAAQ,GACR,IAAI,YACR,CACJ,EACAV,EAAA,cAACG,EAAA,CACG,GAAI,CAACT,EAAe,MAAM,MAE1BM,EAAA,cAAC,OACG,IAAKW,GACL,MAAO,GACP,OAAQ,GACR,IAAI,aACR,CACJ,CACJ,CACJ,CACJ,CACJ,CACJ,CACJ,EACCjB,EAAe,aACZA,EAAe,MAAM,YAAY,UAAY,SACzCM,EAAA,cAACY,GAAA,CACG,KAAMlB,EAAe,YACrB,QAASA,EAAe,iBACxB,OAAQA,EAAe,cAC3B,CAEZ,CAER,CACJ","names":["React","forwardRef","useImperativeHandle","TbLoader","devinoDark","devinoLight","logoDark","logoLight","en_US","t","template","values","_","key","_a","plural","translations","baseKey","count","_b","mergeTranslations","base","overrides","React","TbLoader","DefaultLoaderIcon","React","memo","useCallback","useEffect","useMemo","useRef","useState","createContext","useContext","RootContext","createContext","useRootContext","useContext","RootContext_default","pako","b64EncodeUnicode","str","_","p1","sizeToBytes","size","unit","i","checkFileSize","file","maxFileSize","maxBytes","fileAppendParams","rel","b64EncodeUnicode","revokeFileUrl","_a","compressFile","oldFile","buffer","compressed","pako","newFileWithParams","searchDriveFiles","files","searchTerm","options","caseSensitive","exactMatch","maxResults","searchString","fileNames","_file","index","fileGetIsImage","fileType","PREVIEW_MAX_TEXT_SIZE","PREVIEW_TEXT_TRUNCATE_LENGTH","fileGetIsText","fileName","lower","fileCanPreviewText","fileSize","fileGetExtension","_b","typeSplit","nameSplit","lastNamePart","fileIs3D","ext","dataURLtoBlob","dataURL","_a","_b","header","base64Data","mime","binary","bytes","i","blobToFileWithParams","blob","original","output","fileName","file","fileWithParams","revokeAndReplace","map","fileId","newFile","oldFile","revokeFileUrl","next","getFilerobotTheme","dark","getImageEditorCssOverrides","clsx","twMerge","cn","inputs","ImageEditorInline_default","memo","props","_a","file","onClose","onSave","dark","editorConfig","useRootContext","containerRef","useRef","EditorComponent","setEditorComponent","useState","editorConstants","setEditorConstants","loadError","setLoadError","StyleSheetMgr","setStyleSheetMgr","useEffect","cancelled","mod","scMod","handleKeyDown","useCallback","e","handleEditorSave","imageData","dataURL","shouldForwardProp","prop","FILEROBOT_CUSTOM_PROPS","resolvedTabs","tab","filerobotTheme","useMemo","getFilerobotTheme","editorCssOverrides","getImageEditorCssOverrides","React","cn","EditorWrapper","children","React","memo","useCallback","useEffect","useMemo","useRef","useState","createPortal","ImageEditorModal_default","memo","props","_a","file","onClose","onSave","dark","editorConfig","useRootContext","overlayRef","useRef","previousFocusRef","EditorComponent","setEditorComponent","useState","editorConstants","setEditorConstants","loadError","setLoadError","StyleSheetMgr","setStyleSheetMgr","useEffect","cancelled","mod","scMod","handleKeyDown","useCallback","e","focusable","first","last","handleContentClick","handleEditorSave","imageData","dataURL","shouldForwardProp","prop","FILEROBOT_CUSTOM_PROPS","resolvedTabs","tab","filerobotTheme","useMemo","getFilerobotTheme","editorCssOverrides","getImageEditorCssOverrides","createPortal","React","cn","EditorWrapper","children","motion","React","useCallback","useMemo","useState","useMainBox","files","activeAdapter","isAddingMore","uploadStatus","onFilesDragOver","onFilesDragLeave","onFilesDrop","isProcessing","setFiles","useRootContext","isDragging","setIsDragging","useState","absoluteIsDragging","useMemo","absoluteHasBorder","disableDragAction","handleDragOver","useCallback","e","handleDragLeave","handleDrop","_a","dt","items","droppedFiles","traverse","entry","resolve","reject","file","path","reader","entries","it","traverseHandle","h","out","name","child","handles","React","useCallback","TbUpload","useCallback","useMemo","UploadAdapter","UpupProvider","UploadError","message","type","retryable","status","React","Webcam","useRef","useState","useCallback","useState","uuid","useFetchFileByUrl","onError","useRootContext","loading","setLoading","useState","fetchImage","useCallback","url","blob","extension","uuid","error","useCameraUploader","setFiles","setActiveAdapter","translations","props","useRootContext","fetchImage","useFetchFileByUrl","webcamRef","useRef","url","setUrl","useState","facingMode","setFacingMode","_a","file","prevState","React","AdapterViewContainer","children","isLoading","dark","classNames","useRootContext","React","cn","React","ShouldRender","children","condition","isLoading","LoaderIcon","useRootContext","React","CameraUploader","capture","handleFetchImage","clearUrl","handleCameraSwitch","newCameraSide","url","webcamRef","facingMode","tr","dark","classNames","CameraCaptureIcon","CameraDeleteIcon","CameraRotateIcon","useCameraUploader","React","AdapterViewContainer","ShouldRender","cn","Webcam","t","React","useEffect","useCallback","useEffect","useState","Dropbox","useCallback","useEffect","useRef","useState","instance","createSecureStorage","encode","str","decode","keyFor","rawKey","wrap","value","isExpired","ts","key","storeKey","encrypted","err","stored","decrypted","timestamp","keys","k","TOKEN_KEY","REFRESH_KEY","USER_KEY","WIN_NAME","secure","createSecureStorage","addBusyOverlay","w","doc","overlay","spinner","style","rand","n","b","sha256","txt","b64url","ab","useDropboxAuth","cfg","onError","translations","useRootContext","token","setTok","useState","rtok","setRtok","user","setUser","busy","setBusy","ready","setReady","winRef","useRef","pollRef","verifierRef","clientId","redirectUri","useEffect","t","rt","u","finalizeAuth","useCallback","access","refresh","info","Dropbox","dbxUser","e","authenticate","_a","verifier","challenge","url","_b","href","code","body","res","j","refreshAccessToken","r","logout","formatFileItem","entry","useDropbox","onError","dropboxConfigs","translations","useRootContext","isAuthenticated","token","refreshToken","isLoading","authenticate","logout","refreshAccessToken","useDropboxAuth","user","setUser","useState","dropboxFiles","setDropboxFiles","needsReauth","fetchDropbox","useCallback","url","method","body","isRetry","headers","requestOptions","response","errorText","errorMessage","error","getUserInfo","data","fetchRootContents","files","useEffect","useCallback","useState","formatFileItem","entry","getDownloadUrl","file","token","response","data","useDropboxUploader","onError","accept","setActiveAdapter","setFiles","translations","useRootContext","path","setPath","useState","selectedFiles","setSelectedFiles","showLoader","setShowLoader","downloadProgress","setDownloadProgress","isClickLoading","setIsClickLoading","fetchFolderContents","useCallback","files","prevPath","error","handleClick","prevFiles","f","downloadFile","url","downloadResponse","blob","downloadFiles","promises","index","downloadedFile","handleSubmit","_a","_b","downloadedFiles","t","handleCancelDownload","handleSubmitWithFiles","filtered","ext","onSelectCurrentFolder","current","collectAllFiles","folderPath","initial","entries","cont","e","startPath","motion","React","useEffect","useMemo","useState","GOOGLE_WORKSPACE_EXPORTS","id","getWorkspaceExportInfo","mimeType","getDriveEffectiveExtension","file","exportInfo","isDriveFileAccepted","accept","effectiveExt","effectiveMime","t","token","mainType","React","TbSearch","TbUser","DriveBrowserHeader","path","setPath","user","handleSignOut","showSearch","onSearch","searchTerm","setActiveAdapter","tr","dark","classNames","useRootContext","React","cn","ShouldRender","p","i","prev","TbUser","e","TbSearch","motion","React","React","TbFile","TbFolder","handleImgError","svg","b64EncodeUnicode","DriveBrowserIcon","file","_a","dark","useRootContext","isFolder","src","React","TbFolder","cn","TbFile","AnimatePresence","React","AnimatePresenceTypeFixed","MyAnimatePresence","children","DriveBrowserItem","file","selectedFiles","handleClick","index","dark","classNames","useRootContext","isFolder","isFileSelected","f","transition","React","MyAnimatePresence","motion","cn","DriveBrowserIcon","filterItems","item","accept","isDriveFileAccepted","DriveBrowser","isClickLoading","driveFiles","path","setPath","handleClick","selectedFiles","showLoader","handleSubmit","handleCancelDownload","onSelectCurrentFolder","rest","_a","_b","dark","classNames","tr","useRootContext","searchTerm","setSearchTerm","useState","items","displayedItems","useMemo","searchDriveFiles","isLoading","useEffect","React","AdapterViewContainer","ShouldRender","DriveBrowserHeader","cn","file","index","DriveBrowserItem","MyAnimatePresence","motion","t","plural","DropboxUploader","user","driveFiles","logout","token","isAuthenticated","authenticate","isLoading","useDropbox","handleSignOut","useEffect","props","useDropboxUploader","React","DriveBrowser","React","useCallback","useEffect","useRef","useState","load","useEffect","useState","useLoadGAPI","gisLoaded","setGisLoaded","err","secureStorage","createSecureStorage","useGoogleDrive","googleConfigs","google_client_id","google_api_key","onError","translations","useRootContext","user","setUser","useState","googleFiles","setGoogleFiles","rawFiles","setRawFiles","token","setToken","authCancelled","setAuthCancelled","tokenClientRef","useRef","fetchDrive","useCallback","url","gisLoaded","useLoadGAPI","getFilesList","data","getUserName","handleSignOut","organizeFiles","fileIds","f","organizedFiles","parentIdToChildrenMap","file","parentId","recurse","children","useEffect","storedTokenStr","storedToken","client","tokenResponse","_a","t","error","retryAuth","useState","handleSelectedFilesUpdate","prevFiles","file","f","useGoogleDriveUploader","token","onError","accept","googleDriveConfigs","setActiveAdapter","setFiles","translations","useRootContext","path","setPath","useState","selectedFiles","setSelectedFiles","showLoader","setShowLoader","downloadProgress","setDownloadProgress","handleClick","prevPath","downloadFiles","files","promises","index","downloadedFile","downloadFile","exportInfo","getWorkspaceExportInfo","url","fileName","fileType","response","body","blob","error","handleSubmit","_a","downloadedFiles","t","submitFiles","filtered","isDriveFileAccepted","current","walk","node","child","React","DriveAuthFallback","providerName","onRetry","dark","classNames","useRootContext","React","AdapterViewContainer","cn","GoogleDriveUploader","googleDriveConfigs","useRootContext","user","driveFiles","handleSignOut","token","authCancelled","retryAuth","useGoogleDrive","props","useGoogleDriveUploader","React","DriveAuthFallback","DriveBrowser","React","MyDeviceIcon","DropBoxIcon","React","GoogleDriveIcon","React","OneDriveIcon","React","LinkIcon","React","CameraIcon","React","InteractionType","Client","AuthCodeMSALBrowserAuthenticationProvider","useEffect","useState","useCallback","useEffect","useState","secureStorage","createSecureStorage","useOneDriveAuth","msalInstance","setUser","setOneDriveFiles","onError","translations","useRootContext","token","setToken","useState","isInitialized","setIsInitialized","isAuthenticating","setIsAuthenticating","isAuthInProgress","setIsAuthInProgress","authCancelled","setAuthCancelled","useEffect","_a","_b","accounts","silentRequest","response","error","t","signIn","useCallback","loginRequest","loginResponse","handleSignIn","newToken","handleSignOut","autoLoginTimeout","hasRecentlyLoggedOut","isAuthenticated","retryAuth","PublicClientApplication","useEffect","useState","usePCAInstance","clientId","onError","translations","useRootContext","msalInstance","setMsalInstance","useState","isInitializing","setIsInitializing","useEffect","mounted","instance","PublicClientApplication","error","usePCAInstance_default","useOneDrive","clientId","onError","useRootContext","user","setUser","useState","oneDriveFiles","setOneDriveFiles","graphClient","setGraphClient","msalInstance","usePCAInstance_default","token","signOut","isInitialized","isAuthenticating","authCancelled","retryAuth","useOneDriveAuth","useEffect","accounts","authProvider","AuthCodeMSALBrowserAuthenticationProvider","InteractionType","client","Client","error","profile","files","item","_a","useState","formatFileItem","item","_a","getDownloadUrl","file","graphClient","fileInfo","shareId","useOneDriveUploader","setFiles","setActiveAdapter","onError","accept","translations","useRootContext","isClickLoading","setIsClickLoading","useState","path","setPath","selectedFiles","setSelectedFiles","showLoader","setShowLoader","downloadProgress","setDownloadProgress","fetchFolderContents","files","prevPath","error","t","fetchChildren","folderId","getAllFilesRecursively","rootFolderId","queue","children","child","handleClick","prevFiles","f","downloadFiles","promises","index","_b","downloadedFile","downloadFile","url","response","blob","handleSubmit","downloadedFiles","submitFiles","filtered","ext","current","OneDriveUploader","oneDriveConfigs","useRootContext","user","driveFiles","handleSignOut","graphClient","token","authCancelled","retryAuth","useOneDrive","props","useOneDriveUploader","React","DriveAuthFallback","DriveBrowser","React","useState","UrlUploader","setFiles","setActiveAdapter","tr","LoaderIcon","dark","classNames","useRootContext","url","setUrl","useState","loading","fetchImage","useFetchFileByUrl","React","AdapterViewContainer","e","file","cn","adapterNameKeys","uploadAdapterObject","MyDeviceIcon","GoogleDriveIcon","GoogleDriveUploader","OneDriveIcon","OneDriveUploader","DropBoxIcon","DropboxUploader","LinkIcon","UrlUploader","CameraIcon","CameraUploader","useAdapterSelector","inputRef","setActiveAdapter","setFiles","translations","uploadAdapters","onIntegrationClick","useRootContext","chosenAdapters","useMemo","uploadAdapterObject","item","handleAdapterClick","useCallback","adapterId","_a","handleInputFileChange","e","AdapterSelector","mini","accept","multiple","limit","maxFileSize","dark","classNames","showSelectFolderButton","tr","isAddingMore","setIsAddingMore","inputRef","setFiles","useRootContext","chosenAdapters","handleAdapterClick","handleInputFileChange","useAdapterSelector","handleBrowseFilesClick","useCallback","handleSelectFolderClick","anyWindow","directoryHandle","files","getFiles","dirHandle","path","entry","newPath","file","React","cn","ShouldRender","Icon","id","name","e","TbUpload","t","plural","motion","React","AdapterView","activeAdapter","setActiveAdapter","tr","mini","dark","classNames","useRootContext","UploadComponent","uploadAdapterObject","Icon","React","MyAnimatePresence","motion","cn","motion","React","memo","TbPlayerPauseFilled","TbPlayerPlayFilled","React","memo","useCallback","useState","React","memo","useEffect","useMemo","React","memo","useMemo","React","forwardRef","memo","TbFile","TbFileTypeBmp","TbFileTypeCss","TbFileTypeCsv","TbFileTypeDocx","TbFileTypeHtml","TbFileTypeJpg","TbFileTypeJs","TbFileTypeJsx","TbFileTypePdf","TbFileTypePhp","TbFileTypePng","TbFileTypePpt","TbFileTypeRs","TbFileTypeSql","TbFileTypeSvg","TbFileTypeTs","TbFileTypeTsx","TbFileTypeTxt","TbFileTypeVue","TbFileTypeXls","TbFileTypeXml","TbFileTypeZip","fileTypes","TbFileTypeBmp","TbFileTypeCss","TbFileTypeCsv","TbFileTypeDocx","TbFileTypeHtml","TbFileTypeJpg","TbFileTypeJs","TbFileTypeJsx","TbFileTypePdf","TbFileTypePng","TbFileTypePhp","TbFileTypePpt","TbFileTypeRs","TbFileTypeSql","TbFileTypeSvg","TbFileTypeTs","TbFileTypeTsx","TbFileTypeTxt","TbFileTypeVue","TbFileTypeXls","TbFileTypeXml","TbFileTypeZip","FileIcon_default","memo","forwardRef","extension","className","restProps","ref","dark","useRootContext","IconComponent","TbFile","React","cn","FilePreviewThumbnail_default","memo","canPreview","setCanPreview","fileUrl","fileName","fileType","fileSize","classNames","allowPreview","tr","extension","useMemo","fileGetExtension","is3D","fileIs3D","isOversizedText","fileGetIsText","fileCanPreviewText","React","FileIcon_default","ShouldRender","cn","prev","next","React","forwardRef","ProgressBar_default","forwardRef","progress","className","progressBarClassName","showValue","rest","ref","classNames","dark","useRootContext","React","ShouldRender","cn","FilePreview_default","memo","props","fileType","fileId","fileName","fileUrl","fileSize","canPreview","setCanPreview","onRequestPreview","restProps","handleFileRemove","tr","openImageEditor","filesProgressMap","classNames","FileDeleteIcon","allowPreview","imageEditor","files","useRootContext","isImage","useMemo","fileGetIsImage","isText","fileGetIsText","canPreviewText","fileCanPreviewText","progress","_a","_b","useEffect","onHandleFileRemove","e","onHandleEditImage","file","formatFileSize","bytes","k","sizes","i","React","cn","ShouldRender","FilePreviewThumbnail_default","ProgressBar_default","React","forwardRef","memo","useEffect","useMemo","useState","createPortal","FilePreviewPortal_default","memo","forwardRef","onStopPropagation","fileUrl","fileName","fileType","fileSize","restProps","ref","dark","classNames","tr","useRootContext","isImage","useMemo","fileGetIsImage","isText","fileGetIsText","isOversizedText","PREVIEW_MAX_TEXT_SIZE","textContent","setTextContent","useState","textLoading","setTextLoading","textError","setTextError","isTruncated","setIsTruncated","useEffect","cancelled","_a","reader","decoder","result","done","PREVIEW_TEXT_TRUNCATE_LENGTH","value","streamDone","wasTruncated","txt","e","createPortal","React","cn","ShouldRender","t","FileItem_default","memo","file","files","classNames","onFileClick","useRootContext","showPreviewPortal","setShowPreviewPortal","useState","canPreview","setCanPreview","handleStopPropagation","useCallback","e","openPreviewPortal","React","cn","FilePreview_default","FilePreviewPortal_default","React","useMemo","MainBoxHeader","handleCancel","files","setIsAddingMore","isAddingMore","tr","mini","limit","isProcessing","dark","classNames","ContainerAddMoreIcon","uploadStatus","useRootContext","isUploading","isLimitReached","cancelText","useMemo","React","cn","ShouldRender","t","plural","formatBytes","bytes","k","sizes","i","formatEta","seconds","m","s","FileList_default","memo","isAddingMore","activeAdapter","files","tr","proceedUpload","uploadStatus","totalProgress","uploadSpeed","uploadEta","uploadedBytes","totalBytes","dark","classNames","isProcessing","maxRetries","resumable","handleDone","handleCancel","handlePause","handleResume","useRootContext","React","cn","MainBoxHeader","MyAnimatePresence","motion","a","b","pa","pb","file","FileItem_default","ShouldRender","t","plural","TbPlayerPlayFilled","TbPlayerPauseFilled","ProgressBar_default","MainBox","files","activeAdapter","isAddingMore","dark","useRootContext","isDragging","absoluteIsDragging","absoluteHasBorder","handleDragOver","handleDragLeave","handleDrop","useMainBox","React","MyAnimatePresence","motion","cn","ShouldRender","AdapterView","AdapterSelector","FileList_default","useCallback","useEffect","useMemo","useRef","useState","TbCameraRotate","TbCapture","TbLoader","TbPlus","TbTrash","checkFileType","accept","file","_a","_b","fileType","type","subtype","acceptedTypes","t","item","mainType","fileName","fileExt","ext","STORAGE_PREFIX","SESSION_TTL_MS","fileFingerprint","file","storageKey","fingerprint","saveSession","session","loadSession","raw","removeSession","updateSessionProgress","uploadedBytes","ProviderSDK","config","mergeTranslations","en_US","_a","file","options","_b","UploadError","error","resolve","fingerprint","fileFingerprint","session","loadSession","removeSession","presignedData","uploadResponse","thumbnailPresignedData","thumbnailUploadResponse","_c","_d","_e","persist","key","uploadId","partSize","existingParts","needsInit","existingSession","chunkSizeBytes","initResponse","saveSession","totalParts","uploadedPartNumbers","p","uploadedBytes","sum","start","end","bytesUploaded","partNumber","partBlob","signResponse","partResponse","updateSessionProgress","finalListResponse","completeResponse","url","onFileUploadProgress","onFilesUploadProgress","previouslyUploadedBytes","totalFileSize","reject","xhr","event","loaded","body","response","errorData","isThumbnail","requestBody","t","missing","UpupProvider","e","maxFileSize","accept","errorCode","uploadWithRetry","fn","maxRetries","attempt","error","useRootProvider","accept","mini","dark","propLimit","isProcessing","allowPreview","showSelectFolderButton","maxFileSize","shouldCompress","uploadAdapters","errorHandler","warningHandler","icons","classNames","localePack","translationOverrides","onIntegrationClick","onFileClick","onFileRemove","onFilesDragOver","onFilesDragLeave","onFilesDrop","onFileTypeMismatch","imageEditorProp","onFileUploadStart","onFileUploadProgress","onFilesUploadProgress","onFileUploadComplete","onFilesUploadComplete","onFilesSelected","onDoneClicked","onPrepareFiles","provider","tokenEndpoint","driveConfigs","customProps","enableAutoCorsConfig","resumable","inputRef","useRef","isAddingMore","setIsAddingMore","useState","selectedFilesMap","setSelectedFilesMap","activeAdapter","setActiveAdapter","uploadStatus","setUploadStatus","filesProgressMap","setFilesProgressMap","uploadError","setUploadError","uploadSpeed","setUploadSpeed","uploadEta","setUploadEta","uploadedBytes","setUploadedBytes","totalBytes","setTotalBytes","sdkRef","speedSamplesRef","totalBytesRef","editingFile","setEditingFile","editorQueue","setEditorQueue","selectedFilesMapRef","useEffect","file","revokeFileUrl","limit","useMemo","multiple","translations","mergeTranslations","en_US","totalProgress","filesProgressMapValues","loadedValues","a","b","resolvedImageEditor","_a","_b","_c","openImageEditor","useCallback","advanceEditorQueue","prev","next","rest","closeImageEditor","current","saveImageEdit","editedImageData","mimeType","original","outputMime","quality","blob","raw","dataURLtoBlob","newFile","blobToFileWithParams","revokeAndReplace","replaceFile","fileId","onError","message","onWarn","isFileWithParamsArray","files","resetState","handleDone","dynamicUpload","filesToUpload","fileAppendParams","proceedUpload","dynamicallyReplaceFiles","filesMap","f","fileWithParams","handleSetSelectedFiles","newFiles","newFilesMap","existingUrls","v","addedThisBatch","checkFileType","t","checkFileSize","fileUrl","newImages","first","handleFileRemove","selectedFilesMapCopy","compressFiles","oldFile","compressFile","handlePrepareFiles","progressMap","initialLoaded","fp","fileFingerprint","session","loadSession","total","sum","initialUploaded","dynamicFiles","sendEvent","selectedFiles","compressedFiles","processedFiles","sdk","ProviderSDK","sizeToBytes","uploadOptions","progress","totalLoaded","now","cutoff","s","oldest","newest","elapsed","speed","remaining","completedFiles","finalFiles","result","handleCancel","handlePause","handleResume","TbPlus","TbTrash","TbCapture","TbCameraRotate","TbLoader","useUpload","upload","files","setFiles","dynamicallyReplaceFiles","dynamicUpload","resetState","proceedUpload","uploadStatus","uploadError","totalProgress","file","UpupUploader_default","forwardRef","props","ref","providerValues","useRootProvider","DefaultLoaderIcon","uploadApi","useUpload","useImperativeHandle","React","RootContext_default","cn","ShouldRender","TbLoader","t","MainBox","ImageEditorInline_default","logoDark","logoLight","devinoDark","devinoLight","ImageEditorModal_default"]}