{
  "version": 3,
  "sources": ["../../src/store/private-actions.ts"],
  "sourcesContent": ["/**\n * External dependencies\n */\nimport { v4 as uuidv4 } from 'uuid';\n\n/**\n * WordPress dependencies\n */\nimport { createBlobURL, isBlobURL, revokeBlobURL } from '@wordpress/blob';\nimport type { createRegistry } from '@wordpress/data';\nimport { __ } from '@wordpress/i18n';\ntype WPDataRegistry = ReturnType< typeof createRegistry >;\n\n/**\n * Internal dependencies\n */\nimport {\n\tcloneFile,\n\tconvertBlobToFile,\n\tisAnimatedGif,\n\trenameFile,\n} from '../utils';\nimport { canvasConvertToJpeg } from '../canvas-utils';\nimport { getUnappliedExifOrientation } from '../heic-parser';\nimport {\n\tisClientSideMediaSupported,\n\texceedsClientProcessingMemory,\n} from '../feature-detection';\nimport { getImageDimensions } from '../get-image-dimensions';\nimport { CLIENT_SIDE_SUPPORTED_MIME_TYPES, HEIC_MIME_TYPES } from './constants';\nimport { StubFile } from '../stub-file';\nimport { ErrorCode, UploadError } from '../upload-error';\nimport { measure } from './utils/debug-logger';\nimport {\n\tvipsResizeImage,\n\tvipsRotateImage,\n\tvipsConvertImageFormat,\n\tvipsHasTransparency,\n\tvipsGetUltraHdrInfo,\n\tterminateVipsWorker,\n\tmaybeRecycleVipsWorker,\n} from './utils';\nimport {\n\tconvertGifToVideo,\n\tisUnsupportedConversionError,\n\tterminateVideoConversionWorker,\n} from './utils/video-conversion';\nimport type {\n\tAccumulateSubSizeAction,\n\tAddAction,\n\tAdditionalData,\n\tAddOperationsAction,\n\tAttachment,\n\tBatchId,\n\tCacheBlobUrlAction,\n\tImageFormat,\n\tOnBatchSuccessHandler,\n\tOnChangeHandler,\n\tOnErrorHandler,\n\tOnSuccessHandler,\n\tOperation,\n\tOperationArgs,\n\tOperationFinishAction,\n\tOperationStartAction,\n\tPauseItemAction,\n\tPauseQueueAction,\n\tQueueItem,\n\tQueueItemId,\n\tResumeQueueAction,\n\tRevokeBlobUrlsAction,\n\tSideloadAdditionalData,\n\tSettings,\n\tState,\n\tSubSizeData,\n\tUpdateProgressAction,\n\tUpdateSettingsAction,\n} from './types';\nimport { ItemStatus, OperationType, Type } from './types';\nimport type { cancelItem, executeRetry } from './actions';\nimport { clearRetryTimer } from './utils/retry';\n\nconst DEFAULT_OUTPUT_QUALITY = 0.82;\n\n/**\n * Tracks parent item IDs whose source file is an UltraHDR JPEG so that\n * sub-size resize operations can route through libvips's uhdrload/uhdrsave\n * to preserve the gain map. Entries are cleared in `removeItem` when the\n * parent item leaves the queue, covering both successful completion and\n * cancellation.\n */\nconst ultraHdrItems = new Set< QueueItemId >();\n\ntype ActionCreators = {\n\tcancelItem: typeof cancelItem;\n\texecuteRetry: typeof executeRetry;\n\taddItem: typeof addItem;\n\taddSideloadItem: typeof addSideloadItem;\n\tremoveItem: typeof removeItem;\n\tpauseItem: typeof pauseItem;\n\tprepareItem: typeof prepareItem;\n\tprocessItem: typeof processItem;\n\tfinishOperation: typeof finishOperation;\n\tuploadItem: typeof uploadItem;\n\tsideloadItem: typeof sideloadItem;\n\tresizeCropItem: typeof resizeCropItem;\n\trotateItem: typeof rotateItem;\n\ttranscodeImageItem: typeof transcodeImageItem;\n\ttranscodeGifItem: typeof transcodeGifItem;\n\tgenerateThumbnails: typeof generateThumbnails;\n\tfinalizeItem: typeof finalizeItem;\n\tupdateItemProgress: typeof updateItemProgress;\n\trevokeBlobUrls: typeof revokeBlobUrls;\n\tdetectUltraHdr: typeof detectUltraHdr;\n\t< T = Record< string, unknown > >( args: T ): void;\n};\n\ntype AllSelectors = typeof import('./selectors') &\n\ttypeof import('./private-selectors');\ntype CurriedState< F > = F extends ( state: State, ...args: infer P ) => infer R\n\t? ( ...args: P ) => R\n\t: F;\ntype Selectors = {\n\t[ key in keyof AllSelectors ]: CurriedState< AllSelectors[ key ] >;\n};\n\ntype ThunkArgs = {\n\tselect: Selectors;\n\tdispatch: ActionCreators;\n\tregistry: WPDataRegistry;\n};\n\ninterface AddItemArgs {\n\t// It should always be a File, but some consumers might still pass Blobs only.\n\tfile: File | Blob;\n\tbatchId?: BatchId;\n\tonChange?: OnChangeHandler;\n\tonSuccess?: OnSuccessHandler;\n\tonError?: OnErrorHandler;\n\tonBatchSuccess?: OnBatchSuccessHandler;\n\tadditionalData?: AdditionalData;\n\tsourceUrl?: string;\n\tsourceAttachmentId?: number;\n\tabortController?: AbortController;\n\toperations?: Operation[];\n}\n\n/**\n * Adds a new item to the upload queue.\n *\n * @param $0\n * @param $0.file                 File\n * @param [$0.batchId]            Batch ID.\n * @param [$0.onChange]           Function called each time a file or a temporary representation of the file is available.\n * @param [$0.onSuccess]          Function called after the file is uploaded.\n * @param [$0.onBatchSuccess]     Function called after a batch of files is uploaded.\n * @param [$0.onError]            Function called when an error happens.\n * @param [$0.additionalData]     Additional data to include in the request.\n * @param [$0.sourceUrl]          Source URL. Used when importing a file from a URL or optimizing an existing file.\n * @param [$0.sourceAttachmentId] Source attachment ID. Used when optimizing an existing file for example.\n * @param [$0.abortController]    Abort controller for upload cancellation.\n * @param [$0.operations]         List of operations to perform. Defaults to automatically determined list, based on the file.\n */\nexport function addItem( {\n\tfile: fileOrBlob,\n\tbatchId,\n\tonChange,\n\tonSuccess,\n\tonBatchSuccess,\n\tonError,\n\tadditionalData = {} as AdditionalData,\n\tsourceUrl,\n\tsourceAttachmentId,\n\tabortController,\n\toperations,\n}: AddItemArgs ) {\n\treturn async ( { dispatch }: ThunkArgs ) => {\n\t\tconst itemId = uuidv4();\n\n\t\t// Hardening in case a Blob is passed instead of a File.\n\t\t// See https://github.com/WordPress/gutenberg/pull/65693 for an example.\n\t\tconst file = convertBlobToFile( fileOrBlob );\n\n\t\tlet blobUrl;\n\n\t\t// StubFile could be coming from addItemFromUrl().\n\t\tif ( ! ( file instanceof StubFile ) ) {\n\t\t\tblobUrl = createBlobURL( file );\n\t\t\tdispatch< CacheBlobUrlAction >( {\n\t\t\t\ttype: Type.CacheBlobUrl,\n\t\t\t\tid: itemId,\n\t\t\t\tblobUrl,\n\t\t\t} );\n\t\t}\n\n\t\tdispatch< AddAction >( {\n\t\t\ttype: Type.Add,\n\t\t\titem: {\n\t\t\t\tid: itemId,\n\t\t\t\tbatchId,\n\t\t\t\tstatus: ItemStatus.Processing,\n\t\t\t\tsourceFile: cloneFile( file ),\n\t\t\t\tfile,\n\t\t\t\tattachment: {\n\t\t\t\t\turl: blobUrl,\n\t\t\t\t},\n\t\t\t\tadditionalData: {\n\t\t\t\t\tgenerate_sub_sizes: false,\n\t\t\t\t\t...additionalData,\n\t\t\t\t},\n\t\t\t\tonChange,\n\t\t\t\tonSuccess,\n\t\t\t\tonBatchSuccess,\n\t\t\t\tonError,\n\t\t\t\tsourceUrl,\n\t\t\t\tsourceAttachmentId,\n\t\t\t\tabortController: abortController || new AbortController(),\n\t\t\t\toperations: Array.isArray( operations )\n\t\t\t\t\t? operations\n\t\t\t\t\t: [ OperationType.Prepare ],\n\t\t\t},\n\t\t} );\n\n\t\tdispatch.processItem( itemId );\n\t};\n}\n\ninterface AddSideloadItemArgs {\n\tfile: File;\n\tonChange?: OnChangeHandler;\n\tadditionalData?: AdditionalData;\n\toperations?: Operation[];\n\tbatchId?: BatchId;\n\tparentId?: QueueItemId;\n}\n\n/**\n * Adds a new item to the upload queue for sideloading.\n *\n * This is typically a client-side generated thumbnail.\n *\n * @param $0\n * @param $0.file             File\n * @param [$0.batchId]        Batch ID.\n * @param [$0.parentId]       Parent ID.\n * @param [$0.onChange]       Function called each time a file or a temporary representation of the file is available.\n * @param [$0.additionalData] Additional data to include in the request.\n * @param [$0.operations]     List of operations to perform. Defaults to automatically determined list, based on the file.\n */\nexport function addSideloadItem( {\n\tfile,\n\tonChange,\n\tadditionalData,\n\toperations,\n\tbatchId,\n\tparentId,\n}: AddSideloadItemArgs ) {\n\treturn ( { dispatch }: ThunkArgs ) => {\n\t\tconst itemId = uuidv4();\n\t\tdispatch< AddAction >( {\n\t\t\ttype: Type.Add,\n\t\t\titem: {\n\t\t\t\tid: itemId,\n\t\t\t\tbatchId,\n\t\t\t\tstatus: ItemStatus.Processing,\n\t\t\t\tsourceFile: cloneFile( file ),\n\t\t\t\tfile,\n\t\t\t\tonChange,\n\t\t\t\tadditionalData: {\n\t\t\t\t\t...additionalData,\n\t\t\t\t},\n\t\t\t\tparentId,\n\t\t\t\toperations: Array.isArray( operations )\n\t\t\t\t\t? operations\n\t\t\t\t\t: [ OperationType.Prepare ],\n\t\t\t\tabortController: new AbortController(),\n\t\t\t},\n\t\t} );\n\n\t\tdispatch.processItem( itemId );\n\t};\n}\n\n/**\n * Processes a single item in the queue.\n *\n * Runs the next operation in line and invokes any callbacks.\n *\n * @param id Item ID.\n */\nexport function processItem( id: QueueItemId ) {\n\treturn async ( { select, dispatch }: ThunkArgs ) => {\n\t\tif ( select.isPaused() ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst item = select.getItem( id );\n\t\tif ( ! item ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst {\n\t\t\tattachment,\n\t\t\tonChange,\n\t\t\tonSuccess,\n\t\t\tonBatchSuccess,\n\t\t\tbatchId,\n\t\t\tparentId,\n\t\t} = item;\n\n\t\tconst operation = Array.isArray( item.operations?.[ 0 ] )\n\t\t\t? item.operations[ 0 ][ 0 ]\n\t\t\t: item.operations?.[ 0 ];\n\t\tconst operationArgs = Array.isArray( item.operations?.[ 0 ] )\n\t\t\t? item.operations[ 0 ][ 1 ]\n\t\t\t: undefined;\n\n\t\t/*\n\t\t * If the next operation is an upload, check concurrency limit.\n\t\t * If at capacity, the item remains queued and will be processed\n\t\t * when another upload completes.\n\t\t */\n\t\tif ( operation === OperationType.Upload ) {\n\t\t\tconst settings = select.getSettings();\n\t\t\tconst activeCount = select.getActiveUploadCount();\n\t\t\tif ( activeCount >= settings.maxConcurrentUploads ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t * If the next operation is image processing (resize/crop/rotate),\n\t\t * check the image processing concurrency limit.\n\t\t * If at capacity, the item remains queued and will be processed\n\t\t * when another image processing operation completes.\n\t\t */\n\t\tif (\n\t\t\toperation === OperationType.ResizeCrop ||\n\t\t\toperation === OperationType.Rotate\n\t\t) {\n\t\t\tconst settings = select.getSettings();\n\t\t\tconst activeCount = select.getActiveImageProcessingCount();\n\t\t\tif ( activeCount >= settings.maxConcurrentImageProcessing ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t * GIF-to-video conversion is memory-intensive (WebCodecs encode).\n\t\t * Limit to 1 concurrent transcoding operation.\n\t\t */\n\t\tif ( operation === OperationType.TranscodeGif ) {\n\t\t\tconst activeCount = select.getActiveVideoProcessingCount();\n\t\t\tif ( activeCount >= 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif ( attachment ) {\n\t\t\t// Don't update the block with a HEIC URL — the browser can't\n\t\t\t// display it.  The scaled JPEG sideload will call onChange\n\t\t\t// with a usable URL once the client-side conversion completes.\n\t\t\tconst isHeicUrl =\n\t\t\t\tattachment.url && /\\.hei[cf]$/i.test( attachment.url );\n\t\t\tif ( ! isHeicUrl ) {\n\t\t\t\tonChange?.( [ attachment ] );\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t If there are no more operations, the item can be removed from the queue,\n\t\t but only if there are no thumbnails still being side-loaded,\n\t\t or if itself is a side-loaded item.\n\t\t*/\n\n\t\tif ( ! operation ) {\n\t\t\tif (\n\t\t\t\tparentId ||\n\t\t\t\t( ! parentId && ! select.hasPendingItemsByParentId( id ) )\n\t\t\t) {\n\t\t\t\tif ( attachment ) {\n\t\t\t\t\tonSuccess?.( [ attachment ] );\n\t\t\t\t}\n\n\t\t\t\tdispatch.removeItem( id );\n\t\t\t\tdispatch.revokeBlobUrls( id );\n\n\t\t\t\tif ( batchId && select.isBatchUploaded( batchId ) ) {\n\t\t\t\t\tonBatchSuccess?.();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// All other side-loaded items have been removed, so remove the parent too.\n\t\t\tif ( parentId && batchId && select.isBatchUploaded( batchId ) ) {\n\t\t\t\tconst parentItem = select.getItem( parentId ) as QueueItem;\n\t\t\t\tif ( ! parentItem ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// If parent has pending operations (like Finalize), trigger them.\n\t\t\t\tif (\n\t\t\t\t\tparentItem.operations &&\n\t\t\t\t\tparentItem.operations.length > 0\n\t\t\t\t) {\n\t\t\t\t\tdispatch.processItem( parentId );\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( attachment ) {\n\t\t\t\t\tparentItem.onSuccess?.( [ attachment ] );\n\t\t\t\t}\n\n\t\t\t\tdispatch.removeItem( parentId );\n\t\t\t\tdispatch.revokeBlobUrls( parentId );\n\n\t\t\t\tif (\n\t\t\t\t\tparentItem.batchId &&\n\t\t\t\t\tselect.isBatchUploaded( parentItem.batchId )\n\t\t\t\t) {\n\t\t\t\t\tparentItem.onBatchSuccess?.();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t At this point we are dealing with a parent whose children haven't fully uploaded yet.\n\t\t\t Do nothing and let the removal happen once the last side-loaded item finishes.\n\t\t\t */\n\n\t\t\treturn;\n\t\t}\n\n\t\t// For Finalize, wait until all child sideloads are complete.\n\t\tif (\n\t\t\toperation === OperationType.Finalize &&\n\t\t\tselect.hasPendingItemsByParentId( id )\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tdispatch< OperationStartAction >( {\n\t\t\ttype: Type.OperationStart,\n\t\t\tid,\n\t\t\toperation,\n\t\t} );\n\n\t\tswitch ( operation ) {\n\t\t\tcase OperationType.Prepare:\n\t\t\t\tdispatch.prepareItem( item.id );\n\t\t\t\tbreak;\n\n\t\t\tcase OperationType.ResizeCrop:\n\t\t\t\tdispatch.resizeCropItem(\n\t\t\t\t\titem.id,\n\t\t\t\t\toperationArgs as OperationArgs[ OperationType.ResizeCrop ]\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase OperationType.Rotate:\n\t\t\t\tdispatch.rotateItem(\n\t\t\t\t\titem.id,\n\t\t\t\t\toperationArgs as OperationArgs[ OperationType.Rotate ]\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase OperationType.TranscodeImage:\n\t\t\t\tdispatch.transcodeImageItem(\n\t\t\t\t\titem.id,\n\t\t\t\t\toperationArgs as OperationArgs[ OperationType.TranscodeImage ]\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase OperationType.TranscodeGif:\n\t\t\t\tdispatch.transcodeGifItem(\n\t\t\t\t\titem.id,\n\t\t\t\t\toperationArgs as OperationArgs[ OperationType.TranscodeGif ]\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase OperationType.Upload:\n\t\t\t\tif ( item.parentId ) {\n\t\t\t\t\tdispatch.sideloadItem( id );\n\t\t\t\t} else {\n\t\t\t\t\tdispatch.uploadItem( id );\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase OperationType.ThumbnailGeneration:\n\t\t\t\tdispatch.generateThumbnails( id );\n\t\t\t\tbreak;\n\n\t\t\tcase OperationType.Finalize:\n\t\t\t\tdispatch.finalizeItem( id );\n\t\t\t\tbreak;\n\n\t\t\tcase OperationType.DetectUltraHdr:\n\t\t\t\tdispatch.detectUltraHdr( id );\n\t\t\t\tbreak;\n\t\t}\n\t};\n}\n\n/**\n * Returns an action object that pauses all processing in the queue.\n *\n * Useful for testing purposes.\n *\n * @return Action object.\n */\nexport function pauseQueue(): PauseQueueAction {\n\treturn {\n\t\ttype: Type.PauseQueue,\n\t};\n}\n\n/**\n * Resumes all processing in the queue.\n *\n * Dispatches an action object for resuming the queue itself,\n * and triggers processing for each remaining item in the queue individually.\n */\nexport function resumeQueue() {\n\treturn async ( { select, dispatch }: ThunkArgs ) => {\n\t\tdispatch< ResumeQueueAction >( {\n\t\t\ttype: Type.ResumeQueue,\n\t\t} );\n\n\t\tfor ( const item of select.getAllItems() ) {\n\t\t\t// Items left in PendingRetry while paused had their timers\n\t\t\t// cleared when the timer fired during pause. Re-trigger the\n\t\t\t// retry now that the queue is active again.\n\t\t\tif ( item.status === ItemStatus.PendingRetry ) {\n\t\t\t\tdispatch.executeRetry( item.id );\n\t\t\t} else {\n\t\t\t\tdispatch.processItem( item.id );\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * Pauses a specific item in the queue.\n *\n * @param id Item ID.\n */\nexport function pauseItem( id: QueueItemId ) {\n\treturn async ( { dispatch }: ThunkArgs ) => {\n\t\tdispatch< PauseItemAction >( {\n\t\t\ttype: Type.PauseItem,\n\t\t\tid,\n\t\t} );\n\t};\n}\n\n/**\n * Removes a specific item from the queue.\n *\n * @param id Item ID.\n */\nexport function removeItem( id: QueueItemId ) {\n\treturn async ( { select, dispatch }: ThunkArgs ) => {\n\t\tconst item = select.getItem( id );\n\t\tif ( ! item ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Clear any UltraHDR tracking for this item. removeItem runs on both\n\t\t// successful completion and cancellation, so this prevents the set\n\t\t// from growing unbounded over a long editing session.\n\t\tultraHdrItems.delete( id );\n\n\t\t// Clear any pending retry timer for this item.\n\t\tclearRetryTimer( id );\n\n\t\tdispatch( {\n\t\t\ttype: Type.Remove,\n\t\t\tid,\n\t\t} );\n\n\t\t/*\n\t\t * If the queue is now empty, terminate the background workers to free\n\t\t * their memory (WASM for VIPS, the WebCodecs encoder for video\n\t\t * conversion). Both are lazily re-created if needed.\n\t\t */\n\t\tif ( select.getAllItems().length === 0 ) {\n\t\t\tterminateVipsWorker();\n\t\t\tterminateVideoConversionWorker();\n\t\t}\n\t};\n}\n\n/**\n * Finishes an operation for a given item ID and immediately triggers processing the next one.\n *\n * @param id      Item ID.\n * @param updates Updated item data.\n */\nexport function finishOperation(\n\tid: QueueItemId,\n\tupdates: Partial< QueueItem >\n) {\n\treturn async ( { select, dispatch }: ThunkArgs ) => {\n\t\tconst item = select.getItem( id );\n\t\tconst previousOperation = item?.currentOperation;\n\n\t\tdispatch< OperationFinishAction >( {\n\t\t\ttype: Type.OperationFinish,\n\t\t\tid,\n\t\t\titem: updates,\n\t\t} );\n\n\t\tdispatch.processItem( id );\n\n\t\t/*\n\t\t * If an upload just finished, there may be items waiting in the queue\n\t\t * due to concurrency limits. Trigger processing for them.\n\t\t */\n\t\tif ( previousOperation === OperationType.Upload ) {\n\t\t\tconst pendingUploads = select.getPendingUploads();\n\t\t\tfor ( const pendingItem of pendingUploads ) {\n\t\t\t\tdispatch.processItem( pendingItem.id );\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t * If an image processing operation just finished, there may be items\n\t\t * waiting in the queue due to the image processing concurrency limit.\n\t\t * Trigger processing for them.\n\t\t */\n\t\tif (\n\t\t\tpreviousOperation === OperationType.ResizeCrop ||\n\t\t\tpreviousOperation === OperationType.Rotate\n\t\t) {\n\t\t\tconst pendingItems = select.getPendingImageProcessing();\n\t\t\tfor ( const pendingItem of pendingItems ) {\n\t\t\t\tdispatch.processItem( pendingItem.id );\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t * If a video processing operation just finished, there may be items\n\t\t * waiting due to the video processing concurrency limit.\n\t\t */\n\t\tif ( previousOperation === OperationType.TranscodeGif ) {\n\t\t\tconst pendingItems = select.getPendingVideoProcessing();\n\t\t\tfor ( const pendingItem of pendingItems ) {\n\t\t\t\tdispatch.processItem( pendingItem.id );\n\t\t\t}\n\t\t}\n\n\t\t// Track vips operations across success and failure paths so a\n\t\t// burst of failures can't bypass the recycle budget; the cancel\n\t\t// path calls the same helper.\n\t\tif (\n\t\t\tpreviousOperation === OperationType.ResizeCrop ||\n\t\t\tpreviousOperation === OperationType.Rotate ||\n\t\t\tpreviousOperation === OperationType.TranscodeImage\n\t\t) {\n\t\t\tmaybeRecycleVipsWorker( select.getActiveImageProcessingCount() );\n\t\t}\n\t};\n}\n\nconst VALID_IMAGE_FORMATS = [ 'jpeg', 'webp', 'avif', 'png', 'gif' ] as const;\n\n/**\n * Checks if a format string is a valid ImageFormat.\n *\n * @param format The format string to validate.\n * @return Whether the format is valid.\n */\nfunction isValidImageFormat( format: string ): format is ImageFormat {\n\treturn VALID_IMAGE_FORMATS.includes( format as ImageFormat );\n}\n\n/**\n * Determines if an image should be transcoded to a different format.\n *\n * Handles PNG to JPEG conversion carefully by checking for transparency\n * to preserve the alpha channel when needed.\n *\n * @param file           The image file.\n * @param outputMimeType The target output MIME type.\n * @param interlaced     Whether to use interlaced encoding.\n * @param quality        Re-encode quality (0-1). Defaults to DEFAULT_OUTPUT_QUALITY.\n * @return The transcode operation tuple if transcoding is needed, null otherwise.\n */\nexport async function getTranscodeImageOperation(\n\tfile: File,\n\toutputMimeType: string,\n\tinterlaced: boolean = false,\n\tquality: number = DEFAULT_OUTPUT_QUALITY\n): Promise<\n\t| [\n\t\t\tOperationType.TranscodeImage,\n\t\t\tOperationArgs[ OperationType.TranscodeImage ],\n\t  ]\n\t| null\n> {\n\t// For PNG -> JPEG conversion, check if the image has transparency.\n\t// If it does, skip transcoding to preserve the alpha channel.\n\tif ( file.type === 'image/png' && outputMimeType === 'image/jpeg' ) {\n\t\tconst blobUrl = createBlobURL( file );\n\t\ttry {\n\t\t\tconst hasAlpha = await vipsHasTransparency( blobUrl );\n\t\t\tif ( hasAlpha ) {\n\t\t\t\t// Image has transparency, skip conversion to JPEG.\n\t\t\t\treturn null;\n\t\t\t}\n\t\t} catch {\n\t\t\t// If transparency check fails, err on the side of caution.\n\t\t\treturn null;\n\t\t} finally {\n\t\t\trevokeBlobURL( blobUrl );\n\t\t}\n\t}\n\n\tconst formatPart = outputMimeType.split( '/' )[ 1 ];\n\tif ( ! isValidImageFormat( formatPart ) ) {\n\t\t// Unknown format, skip transcoding.\n\t\treturn null;\n\t}\n\n\treturn [\n\t\tOperationType.TranscodeImage,\n\t\t{\n\t\t\toutputFormat: formatPart,\n\t\t\toutputQuality: quality,\n\t\t\tinterlaced,\n\t\t},\n\t];\n}\n\n/**\n * Prepares an item for initial processing.\n *\n * Determines the list of operations to perform for a given image,\n * depending on its media type.\n *\n * For example, HEIF images first need to be converted, resized,\n * compressed, and then uploaded.\n *\n * Or videos need to be compressed, and then need poster generation\n * before upload.\n *\n * UltraHDR JPEG images are detected and uploaded unmodified — they are\n * already backwards compatible (SDR displays use the embedded base image).\n *\n * @param id Item ID.\n */\nexport function prepareItem( id: QueueItemId ) {\n\treturn async ( { select, dispatch }: ThunkArgs ) => {\n\t\tconst item = select.getItem( id );\n\t\tif ( ! item ) {\n\t\t\treturn;\n\t\t}\n\t\tconst { file } = item;\n\n\t\tconst operations: Operation[] = [];\n\t\tconst settings = select.getSettings();\n\n\t\t// Animated GIF → video. WebCodecs is required; client-side media\n\t\t// already runs only under cross-origin isolation, so this is a\n\t\t// capability check, not a browser-support fallback path.\n\t\t//\n\t\t// The GIF uploads through the normal image pipeline so the block\n\t\t// starts as a valid core/image. The converted video is sideloaded as\n\t\t// a companion file of this same attachment after upload (see\n\t\t// generateThumbnails) — like the HEIC original — not as a separate\n\t\t// media library attachment. It is recorded in attachment metadata; the\n\t\t// editor offers switching the block to the Video block's GIF variation\n\t\t// playing that companion via a block transform (see\n\t\t// packages/block-library/src/image/transforms.js).\n\t\tif (\n\t\t\tfile.type === 'image/gif' &&\n\t\t\tsettings.gifConvert !== false &&\n\t\t\ttypeof ImageDecoder !== 'undefined' &&\n\t\t\ttypeof VideoEncoder !== 'undefined'\n\t\t) {\n\t\t\tlet isAnimated = false;\n\t\t\ttry {\n\t\t\t\tisAnimated = isAnimatedGif( await file.arrayBuffer() );\n\t\t\t} catch {\n\t\t\t\t// If the GIF cannot be read/inspected, fall through to the\n\t\t\t\t// normal image pipeline rather than failing the upload.\n\t\t\t\tisAnimated = false;\n\t\t\t}\n\t\t\tif ( isAnimated ) {\n\t\t\t\t// Skip the conversion for transparent GIFs: a <video> cannot\n\t\t\t\t// reproduce GIF transparency, so converting would visibly\n\t\t\t\t// change the image (e.g. small decorative or emoji-like GIFs\n\t\t\t\t// over a colored background). Such GIFs upload as a normal\n\t\t\t\t// image instead. Mirrors the PNG → JPEG transparency check in\n\t\t\t\t// getTranscodeImageOperation().\n\t\t\t\tlet hasTransparency = false;\n\t\t\t\tconst blobUrl = createBlobURL( file );\n\t\t\t\ttry {\n\t\t\t\t\thasTransparency = await vipsHasTransparency( blobUrl );\n\t\t\t\t} catch {\n\t\t\t\t\t// If the check fails, err on the side of caution and keep\n\t\t\t\t\t// the GIF rather than risk a lossy conversion.\n\t\t\t\t\thasTransparency = true;\n\t\t\t\t} finally {\n\t\t\t\t\trevokeBlobURL( blobUrl );\n\t\t\t\t}\n\n\t\t\t\tif ( ! hasTransparency ) {\n\t\t\t\t\toperations.push(\n\t\t\t\t\t\tOperationType.Upload,\n\t\t\t\t\t\tOperationType.ThumbnailGeneration,\n\t\t\t\t\t\tOperationType.Finalize\n\t\t\t\t\t);\n\n\t\t\t\t\tdispatch< AddOperationsAction >( {\n\t\t\t\t\t\ttype: Type.AddOperations,\n\t\t\t\t\t\tid,\n\t\t\t\t\t\toperations,\n\t\t\t\t\t} );\n\n\t\t\t\t\t// Keep the original GIF so generateThumbnails can\n\t\t\t\t\t// transcode and sideload it once the attachment exists.\n\t\t\t\t\tdispatch.finishOperation( id, {\n\t\t\t\t\t\tanimatedGifFile: item.file,\n\t\t\t\t\t} );\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlet heicJpeg: File | null = null;\n\n\t\tconst isImage = file.type.startsWith( 'image/' );\n\t\tconst isVipsSupported = CLIENT_SIDE_SUPPORTED_MIME_TYPES.includes(\n\t\t\tfile.type\n\t\t);\n\t\tconst isHeic = HEIC_MIME_TYPES.includes( file.type );\n\n\t\t// Gate very large images out of client-side processing. wasm-vips is\n\t\t// capped at 1 GiB of memory, so high-megapixel images, especially\n\t\t// interlaced/progressive ones, which can't be decoded with\n\t\t// shrink-on-load, can exhaust it and fail. These are routed to the\n\t\t// server, which has no comparable per-image ceiling. If dimensions\n\t\t// can't be determined, the image stays on the client-side path.\n\t\tlet tooLargeForClient = false;\n\t\tif ( isImage && isVipsSupported ) {\n\t\t\tconst dimensions = await getImageDimensions( file );\n\t\t\tif ( dimensions && exceedsClientProcessingMemory( dimensions ) ) {\n\t\t\t\ttooLargeForClient = true;\n\t\t\t}\n\t\t}\n\n\t\t// Check for UltraHDR in JPEG files before other operations. Skipped for\n\t\t// images routed to the server: the gain map is only preserved by the\n\t\t// client-side resize path, and the probe runs wasm-vips, which the\n\t\t// large-image gate above is specifically meant to avoid.\n\t\tif ( file.type === 'image/jpeg' && ! tooLargeForClient ) {\n\t\t\toperations.push( OperationType.DetectUltraHdr );\n\t\t}\n\n\t\t// For images that can be processed by vips, upload the original and\n\t\t// let generateThumbnails() handle threshold scaling as a sideload.\n\t\t//\n\t\t// Uploading the original (rather than a pre-scaled copy) preserves\n\t\t// the un-suffixed basename in attachment.filename, so sub-size\n\t\t// names are derived from the original — matching WordPress core's\n\t\t// wp_create_image_subsizes() naming convention where only the\n\t\t// scaled-down full-size copy carries the `-scaled` suffix and the\n\t\t// original is kept alongside it as `original_image`.\n\t\t//\n\t\t// Main-file format conversion is handled server-side via the\n\t\t// image_editor_output_format filter during create_item.\n\t\t// The response carries image_output_format so generateThumbnails\n\t\t// can transcode sub-sizes to the same target format.\n\t\tif ( isImage && isVipsSupported && ! tooLargeForClient ) {\n\t\t\toperations.push(\n\t\t\t\tOperationType.Upload,\n\t\t\t\tOperationType.ThumbnailGeneration,\n\t\t\t\tOperationType.Finalize\n\t\t\t);\n\t\t} else if ( isImage && isHeic ) {\n\t\t\t// HEIC/HEIF: convert to JPEG client-side before upload.\n\t\t\t// The server may not support HEIC, so decode it using the\n\t\t\t// browser's native HEVC codec (createImageBitmap or VideoDecoder)\n\t\t\t// and upload the resulting JPEG. The server then handles it like\n\t\t\t// any normal JPEG (threshold scaling, sub-sizes, etc.).\n\t\t\t// This matches iOS behavior where HEIC is converted on the fly.\n\t\t\ttry {\n\t\t\t\theicJpeg = await canvasConvertToJpeg(\n\t\t\t\t\tfile,\n\t\t\t\t\tsettings.imageQuality ?? DEFAULT_OUTPUT_QUALITY\n\t\t\t\t);\n\t\t\t} catch {\n\t\t\t\tdispatch.cancelItem(\n\t\t\t\t\tid,\n\t\t\t\t\tnew UploadError( {\n\t\t\t\t\t\tcode: ErrorCode.HEIC_DECODE_ERROR,\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t'This browser cannot decode HEIC images and the server does not support them either. Please convert to JPEG before uploading.',\n\t\t\t\t\t\tfile,\n\t\t\t\t\t} )\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\toperations.push(\n\t\t\t\tOperationType.Upload,\n\t\t\t\tOperationType.ThumbnailGeneration,\n\t\t\t\tOperationType.Finalize\n\t\t\t);\n\t\t} else {\n\t\t\toperations.push( OperationType.Upload );\n\t\t}\n\n\t\tdispatch< AddOperationsAction >( {\n\t\t\ttype: Type.AddOperations,\n\t\t\tid,\n\t\t\toperations,\n\t\t} );\n\n\t\t// Tell the server whether to generate sub-sizes.\n\t\t// When vips handles processing client-side, set generate_sub_sizes\n\t\t// to false so the server skips the image-type support check\n\t\t// (allowing formats like AVIF that the server can't process).\n\t\tlet updates: Partial< QueueItem >;\n\t\tif ( isHeic && heicJpeg ) {\n\t\t\t// HEIC was converted to JPEG client-side. Upload the JPEG\n\t\t\t// and let the server handle it normally (threshold scaling,\n\t\t\t// sub-sizes, format conversion). Keep the original HEIC in\n\t\t\t// a separate field so it can be sideloaded as the \"original\"\n\t\t\t// after upload, preserving the user's file without leaking it\n\t\t\t// into paths that expect an editor-supported image.\n\t\t\tconst vipsAvailable = isClientSideMediaSupported();\n\t\t\tupdates = {\n\t\t\t\tfile: heicJpeg,\n\t\t\t\tsourceFile: heicJpeg,\n\t\t\t\toriginalHeicFile: item.file,\n\t\t\t\tadditionalData: {\n\t\t\t\t\t...item.additionalData,\n\t\t\t\t\tgenerate_sub_sizes: ! vipsAvailable,\n\t\t\t\t\tconvert_format: true,\n\t\t\t\t},\n\t\t\t};\n\t\t} else if ( ! isVipsSupported || ! isImage || tooLargeForClient ) {\n\t\t\t// Either the format isn't vips-processable, it isn't an image, or\n\t\t\t// it's too large for client-side processing. Let the server\n\t\t\t// generate sub-sizes and handle format conversion.\n\t\t\tupdates = {\n\t\t\t\tadditionalData: {\n\t\t\t\t\t...item.additionalData,\n\t\t\t\t\tgenerate_sub_sizes: true,\n\t\t\t\t\tconvert_format: true,\n\t\t\t\t},\n\t\t\t};\n\t\t} else {\n\t\t\tupdates = {\n\t\t\t\tadditionalData: {\n\t\t\t\t\t...item.additionalData,\n\t\t\t\t\tgenerate_sub_sizes: false,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tdispatch.finishOperation( id, updates );\n\t};\n}\n\n/**\n * Detects whether a JPEG is an UltraHDR image and records the parent item\n * ID so that downstream resize operations route through libvips's\n * uhdrload/uhdrsave pipeline (which preserves the gain map).\n *\n * @param id Item ID.\n */\nexport function detectUltraHdr( id: QueueItemId ) {\n\treturn async ( { select, dispatch }: ThunkArgs ) => {\n\t\tconst item = select.getItem( id );\n\t\tif ( ! item ) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet info;\n\t\ttry {\n\t\t\tconst buffer = await item.file.arrayBuffer();\n\t\t\tinfo = await vipsGetUltraHdrInfo( buffer );\n\t\t} catch {\n\t\t\t// If UltraHDR detection fails, continue with regular upload.\n\t\t}\n\n\t\t// Track the item so downstream resize operations preserve the gain\n\t\t// map and skip format transcoding. The original file is uploaded\n\t\t// unmodified — UltraHDR JPEGs are already backwards compatible (SDR\n\t\t// displays use the embedded base image).\n\t\tif ( info ) {\n\t\t\tultraHdrItems.add( id );\n\t\t}\n\n\t\tdispatch.finishOperation( id, {} );\n\t};\n}\n\n/**\n * Uploads an item to the server.\n *\n * @param id Item ID.\n */\nexport function uploadItem( id: QueueItemId ) {\n\treturn async ( { select, dispatch }: ThunkArgs ) => {\n\t\tconst item = select.getItem( id );\n\t\tif ( ! item ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst startTime = performance.now();\n\t\tlet finished = false;\n\n\t\tconst finishUpload = ( attachment: Partial< Attachment > ) => {\n\t\t\tif ( finished ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfinished = true;\n\n\t\t\tmeasure( {\n\t\t\t\tmeasureName: `Upload ${ item.file.name }`,\n\t\t\t\tstartTime,\n\t\t\t\ttooltipText: item.file.name,\n\t\t\t\tproperties: [\n\t\t\t\t\t[ 'Item ID', item.id ],\n\t\t\t\t\t[ 'File name', item.file.name ],\n\t\t\t\t],\n\t\t\t} );\n\n\t\t\tdispatch.finishOperation( id, { attachment } );\n\t\t};\n\n\t\tselect.getSettings().mediaUpload( {\n\t\t\tfilesList: [ item.file ],\n\t\t\tadditionalData: item.additionalData,\n\t\t\tsignal: item.abortController?.signal,\n\t\t\tonFileChange: ( [ attachment ] ) => {\n\t\t\t\tif ( attachment && ! isBlobURL( attachment.url ) ) {\n\t\t\t\t\tfinishUpload( attachment );\n\t\t\t\t}\n\t\t\t},\n\t\t\tonSuccess: ( [ attachment ] ) => {\n\t\t\t\tfinishUpload( attachment );\n\t\t\t},\n\t\t\tonError: ( error ) => {\n\t\t\t\tdispatch.cancelItem( id, error );\n\t\t\t},\n\t\t} );\n\t};\n}\n\n/**\n * Sideloads an item to the server.\n *\n * @param id Item ID.\n */\nexport function sideloadItem( id: QueueItemId ) {\n\treturn async ( { select, dispatch }: ThunkArgs ) => {\n\t\tconst item = select.getItem( id );\n\t\tif ( ! item ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { post, ...additionalData } =\n\t\t\titem.additionalData as SideloadAdditionalData;\n\n\t\tconst mediaSideload = select.getSettings().mediaSideload;\n\t\tif ( ! mediaSideload ) {\n\t\t\t// If sideloading is not supported, skip this operation.\n\t\t\tdispatch.finishOperation( id, {} );\n\t\t\treturn;\n\t\t}\n\n\t\tconst startTime = performance.now();\n\n\t\tmediaSideload( {\n\t\t\tfile: item.file,\n\t\t\tattachmentId: post as number,\n\t\t\tadditionalData,\n\t\t\tsignal: item.abortController?.signal,\n\t\t\tonSuccess: ( subSize: SubSizeData ) => {\n\t\t\t\tmeasure( {\n\t\t\t\t\tmeasureName: `Sideload ${ item.file.name }`,\n\t\t\t\t\tstartTime,\n\t\t\t\t\ttooltipText: item.file.name,\n\t\t\t\t\tproperties: [\n\t\t\t\t\t\t[ 'Item ID', item.id ],\n\t\t\t\t\t\t[ 'File name', item.file.name ],\n\t\t\t\t\t],\n\t\t\t\t} );\n\n\t\t\t\t// Accumulate sub-size data on the parent item for finalize.\n\t\t\t\tif ( item.parentId ) {\n\t\t\t\t\tdispatch< AccumulateSubSizeAction >( {\n\t\t\t\t\t\ttype: Type.AccumulateSubSize,\n\t\t\t\t\t\tid: item.parentId,\n\t\t\t\t\t\tsubSize,\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t\tdispatch.finishOperation( id, {} );\n\t\t\t},\n\t\t\tonError: ( error ) => {\n\t\t\t\tdispatch.cancelItem( id, error );\n\t\t\t},\n\t\t} );\n\t};\n}\n\ntype ResizeCropItemArgs = OperationArgs[ OperationType.ResizeCrop ];\n\n/**\n * Resizes and crops an existing image item.\n *\n * @param id     Item ID.\n * @param [args] Additional arguments for the operation.\n */\nexport function resizeCropItem( id: QueueItemId, args?: ResizeCropItemArgs ) {\n\treturn async ( { select, dispatch }: ThunkArgs ) => {\n\t\tconst item = select.getItem( id );\n\t\tif ( ! item ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( ! args?.resize ) {\n\t\t\tdispatch.finishOperation( id, {\n\t\t\t\tfile: item.file,\n\t\t\t} );\n\t\t\treturn;\n\t\t}\n\n\t\tconst startTime = performance.now();\n\n\t\t// Add dimension suffix for sub-sizes (thumbnails).\n\t\tconst addSuffix = Boolean( item.parentId );\n\t\t// Add '-scaled' suffix for big image threshold resizing.\n\t\tconst scaledSuffix = Boolean( args.isThresholdResize );\n\n\t\ttry {\n\t\t\tconst file = await vipsResizeImage(\n\t\t\t\titem.id,\n\t\t\t\titem.file,\n\t\t\t\targs.resize,\n\t\t\t\tfalse, // smartCrop\n\t\t\t\taddSuffix,\n\t\t\t\titem.abortController?.signal,\n\t\t\t\tscaledSuffix,\n\t\t\t\targs.quality\n\t\t\t);\n\n\t\t\tmeasure( {\n\t\t\t\tmeasureName: `ResizeCrop ${ item.file.name }`,\n\t\t\t\tstartTime,\n\t\t\t\ttooltipText: item.file.name,\n\t\t\t\tproperties: [\n\t\t\t\t\t[ 'Item ID', item.id ],\n\t\t\t\t\t[ 'File name', item.file.name ],\n\t\t\t\t],\n\t\t\t} );\n\n\t\t\tconst blobUrl = createBlobURL( file );\n\t\t\tdispatch< CacheBlobUrlAction >( {\n\t\t\t\ttype: Type.CacheBlobUrl,\n\t\t\t\tid,\n\t\t\t\tblobUrl,\n\t\t\t} );\n\n\t\t\tdispatch.finishOperation( id, {\n\t\t\t\tfile,\n\t\t\t\tattachment: {\n\t\t\t\t\turl: blobUrl,\n\t\t\t\t},\n\t\t\t} );\n\t\t} catch ( error ) {\n\t\t\tdispatch.cancelItem(\n\t\t\t\tid,\n\t\t\t\tnew UploadError( {\n\t\t\t\t\tcode: ErrorCode.IMAGE_TRANSCODING_ERROR,\n\t\t\t\t\tmessage: __(\n\t\t\t\t\t\t'The web server cannot generate responsive image sizes for this image. Convert it to JPEG or PNG before uploading.'\n\t\t\t\t\t),\n\t\t\t\t\tfile: item.file,\n\t\t\t\t\tcause: error instanceof Error ? error : undefined,\n\t\t\t\t} )\n\t\t\t);\n\t\t}\n\t};\n}\n\ntype RotateItemArgs = OperationArgs[ OperationType.Rotate ];\n\n/**\n * Rotates an image based on EXIF orientation.\n *\n * This is used for images that need rotation but don't need resizing\n * (i.e., smaller than the big image size threshold).\n * Matches WordPress core's behavior of creating a '-rotated' version.\n *\n * @param id     Item ID.\n * @param [args] Rotation arguments including EXIF orientation value.\n */\nexport function rotateItem( id: QueueItemId, args?: RotateItemArgs ) {\n\treturn async ( { select, dispatch }: ThunkArgs ) => {\n\t\tconst item = select.getItem( id );\n\t\tif ( ! item ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If no orientation provided or orientation is 1 (normal), skip rotation.\n\t\tif ( ! args?.orientation || args.orientation === 1 ) {\n\t\t\tdispatch.finishOperation( id, {\n\t\t\t\tfile: item.file,\n\t\t\t} );\n\t\t\treturn;\n\t\t}\n\n\t\tconst startTime = performance.now();\n\n\t\ttry {\n\t\t\tconst file = await vipsRotateImage(\n\t\t\t\titem.id,\n\t\t\t\titem.file,\n\t\t\t\targs.orientation,\n\t\t\t\titem.abortController?.signal\n\t\t\t);\n\n\t\t\tmeasure( {\n\t\t\t\tmeasureName: `Rotate ${ item.file.name }`,\n\t\t\t\tstartTime,\n\t\t\t\ttooltipText: item.file.name,\n\t\t\t\tproperties: [\n\t\t\t\t\t[ 'Item ID', item.id ],\n\t\t\t\t\t[ 'File name', item.file.name ],\n\t\t\t\t],\n\t\t\t} );\n\n\t\t\tconst blobUrl = createBlobURL( file );\n\t\t\tdispatch< CacheBlobUrlAction >( {\n\t\t\t\ttype: Type.CacheBlobUrl,\n\t\t\t\tid,\n\t\t\t\tblobUrl,\n\t\t\t} );\n\n\t\t\tdispatch.finishOperation( id, {\n\t\t\t\tfile,\n\t\t\t\tattachment: {\n\t\t\t\t\turl: blobUrl,\n\t\t\t\t},\n\t\t\t} );\n\t\t} catch ( error ) {\n\t\t\tdispatch.cancelItem(\n\t\t\t\tid,\n\t\t\t\tnew UploadError( {\n\t\t\t\t\tcode: ErrorCode.IMAGE_ROTATION_ERROR,\n\t\t\t\t\tmessage: __(\n\t\t\t\t\t\t'The web server cannot generate responsive image sizes for this image. Convert it to JPEG or PNG before uploading.'\n\t\t\t\t\t),\n\t\t\t\t\tfile: item.file,\n\t\t\t\t\tcause: error instanceof Error ? error : undefined,\n\t\t\t\t} )\n\t\t\t);\n\t\t}\n\t};\n}\n\ntype TranscodeImageItemArgs = OperationArgs[ OperationType.TranscodeImage ];\n\n/**\n * Transcodes an image to a different format.\n *\n * This operation converts images between formats (e.g., PNG to WebP, JPEG to AVIF)\n * based on the WordPress image_editor_output_format filter settings.\n *\n * @param id     Item ID.\n * @param [args] Transcode arguments including output format, quality, and interlace settings.\n */\nexport function transcodeImageItem(\n\tid: QueueItemId,\n\targs?: TranscodeImageItemArgs\n) {\n\treturn async ( { select, dispatch }: ThunkArgs ) => {\n\t\tconst item = select.getItem( id );\n\t\tif ( ! item ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If no output format specified, skip transcoding.\n\t\tif ( ! args?.outputFormat ) {\n\t\t\tdispatch.finishOperation( id, {\n\t\t\t\tfile: item.file,\n\t\t\t} );\n\t\t\treturn;\n\t\t}\n\n\t\tconst startTime = performance.now();\n\n\t\tconst outputMimeType = `image/${ args.outputFormat }` as\n\t\t\t| 'image/jpeg'\n\t\t\t| 'image/png'\n\t\t\t| 'image/webp'\n\t\t\t| 'image/avif'\n\t\t\t| 'image/gif';\n\t\tconst quality = args.outputQuality ?? DEFAULT_OUTPUT_QUALITY;\n\t\tconst interlaced = args.interlaced ?? false;\n\n\t\ttry {\n\t\t\tconst file = await vipsConvertImageFormat(\n\t\t\t\titem.id,\n\t\t\t\titem.file,\n\t\t\t\toutputMimeType,\n\t\t\t\tquality,\n\t\t\t\tinterlaced\n\t\t\t);\n\n\t\t\tmeasure( {\n\t\t\t\tmeasureName: `Transcode ${ item.file.name }`,\n\t\t\t\tstartTime,\n\t\t\t\ttooltipText: item.file.name,\n\t\t\t\tproperties: [\n\t\t\t\t\t[ 'Item ID', item.id ],\n\t\t\t\t\t[ 'File name', item.file.name ],\n\t\t\t\t],\n\t\t\t} );\n\n\t\t\tconst blobUrl = createBlobURL( file );\n\t\t\tdispatch< CacheBlobUrlAction >( {\n\t\t\t\ttype: Type.CacheBlobUrl,\n\t\t\t\tid,\n\t\t\t\tblobUrl,\n\t\t\t} );\n\n\t\t\tdispatch.finishOperation( id, {\n\t\t\t\tfile,\n\t\t\t\tattachment: {\n\t\t\t\t\turl: blobUrl,\n\t\t\t\t},\n\t\t\t} );\n\t\t} catch ( error ) {\n\t\t\tdispatch.cancelItem(\n\t\t\t\tid,\n\t\t\t\tnew UploadError( {\n\t\t\t\t\tcode: ErrorCode.MEDIA_TRANSCODING_ERROR,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t'Image could not be transcoded to the target format',\n\t\t\t\t\tfile: item.file,\n\t\t\t\t\tcause: error instanceof Error ? error : undefined,\n\t\t\t\t} )\n\t\t\t);\n\t\t}\n\t};\n}\n\ntype TranscodeGifItemArgs = OperationArgs[ OperationType.TranscodeGif ];\n\n/**\n * Converts an animated GIF to a video file (MP4 or WebM).\n *\n * Runs inside a sideload item whose parent is the GIF's image attachment\n * (see generateThumbnails). The next Upload op then sideloads the\n * transcoded video as a companion of that attachment under the\n * `animated_video` image size; the GIF stays the primary attachment and\n * the editor block stays `core/image`.\n *\n * @param id     Item ID.\n * @param [args] Transcode arguments including output format.\n */\nexport function transcodeGifItem(\n\tid: QueueItemId,\n\targs?: TranscodeGifItemArgs\n) {\n\treturn async ( { select, dispatch }: ThunkArgs ) => {\n\t\tconst item = select.getItem( id );\n\t\tif ( ! item ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst outputFormat = args?.outputFormat ?? 'mp4';\n\t\tconst outputMimeType = `video/${ outputFormat }`;\n\n\t\t/*\n\t\t * item.file is the original GIF until finishOperation swaps in the\n\t\t * transcoded video below; capture it for the poster sideload.\n\t\t */\n\t\tconst gifFile = item.file;\n\n\t\ttry {\n\t\t\tconst file = await convertGifToVideo(\n\t\t\t\titem.id,\n\t\t\t\tgifFile,\n\t\t\t\toutputMimeType\n\t\t\t);\n\n\t\t\t// Hand the transcoded video to the next Upload op as the\n\t\t\t// sideload's payload. The parent attachment (the GIF) is\n\t\t\t// already uploaded; no blob URL is needed for any block.\n\t\t\tdispatch.finishOperation( id, { file } );\n\n\t\t\t/*\n\t\t\t * Only now that the video exists, sideload a static first-frame\n\t\t\t * poster as a companion (vips decodes just the first GIF frame).\n\t\t\t * Queued here rather than alongside the video in\n\t\t\t * generateThumbnails so an unsupported/failed conversion never\n\t\t\t * leaves an orphaned `animated_video_poster` with no matching\n\t\t\t * `animated_video`. This sibling is registered while the video's\n\t\t\t * own Upload op is still pending, so the parent's finalize gate\n\t\t\t * stays closed until both companions finish. Stored under\n\t\t\t * metadata `animated_video_poster`.\n\t\t\t */\n\t\t\tdispatch.addSideloadItem( {\n\t\t\t\tfile: gifFile,\n\t\t\t\tbatchId: uuidv4(),\n\t\t\t\tparentId: item.parentId,\n\t\t\t\tadditionalData: {\n\t\t\t\t\tpost: item.additionalData?.post,\n\t\t\t\t\timage_size: 'animated_video_poster',\n\t\t\t\t\tconvert_format: false,\n\t\t\t\t},\n\t\t\t\toperations: [\n\t\t\t\t\t[\n\t\t\t\t\t\tOperationType.TranscodeImage,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toutputFormat: 'jpeg',\n\t\t\t\t\t\t\toutputQuality: DEFAULT_OUTPUT_QUALITY,\n\t\t\t\t\t\t\tinterlaced: false,\n\t\t\t\t\t\t} as OperationArgs[ OperationType.TranscodeImage ],\n\t\t\t\t\t],\n\t\t\t\t\tOperationType.Upload,\n\t\t\t\t],\n\t\t\t} );\n\t\t} catch ( error ) {\n\t\t\t// An \"Unsupported\" outcome is a graceful skip, not a failure:\n\t\t\t// the parent GIF attachment already exists and stays as-is, so\n\t\t\t// we silently cancel this sideload (no companion video, no\n\t\t\t// user-facing error). Uploading the original GIF here would\n\t\t\t// create an `animated_video` meta entry pointing at the GIF\n\t\t\t// itself — meaningless.\n\t\t\tif ( isUnsupportedConversionError( error ) ) {\n\t\t\t\tdispatch.cancelItem(\n\t\t\t\t\tid,\n\t\t\t\t\tnew Error( 'Animated GIF conversion unsupported' ),\n\t\t\t\t\ttrue\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Real engine failure. The parent GIF attachment is fine —\n\t\t\t// the user just won't get a companion video. Log the cause\n\t\t\t// for debuggability and silently cancel the sideload; we do\n\t\t\t// not surface a \"could not be converted to video\" toast on\n\t\t\t// what the user thinks of as an image upload.\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.error(\n\t\t\t\t'[video-conversion] GIF to video conversion failed:',\n\t\t\t\terror\n\t\t\t);\n\t\t\tdispatch.cancelItem(\n\t\t\t\tid,\n\t\t\t\tnew UploadError( {\n\t\t\t\t\tcode: ErrorCode.GIF_TRANSCODING_ERROR,\n\t\t\t\t\tmessage: 'Animated GIF could not be converted to video',\n\t\t\t\t\tfile: item.file,\n\t\t\t\t\tcause: error instanceof Error ? error : undefined,\n\t\t\t\t} ),\n\t\t\t\ttrue\n\t\t\t);\n\t\t}\n\t};\n}\n\n/**\n * Adds thumbnail versions to the queue for sideloading.\n *\n * Also handles image rotation for images that need EXIF-based rotation\n * but weren't scaled down (and thus weren't auto-rotated by vips).\n *\n * @param id Item ID.\n */\nexport function generateThumbnails( id: QueueItemId ) {\n\treturn async ( { select, dispatch }: ThunkArgs ) => {\n\t\tconst item = select.getItem( id );\n\t\tif ( ! item ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( ! item.attachment ) {\n\t\t\tdispatch.finishOperation( id, {} );\n\t\t\treturn;\n\t\t}\n\t\tconst attachment = item.attachment;\n\t\tconst settings = select.getSettings();\n\n\t\t// HEIC/HEIF: preserve the original file under a dedicated metadata\n\t\t// key so it never collides with `original_image`, which the scaled\n\t\t// sideload flow owns. The HEIC was kept on item.originalHeicFile;\n\t\t// the uploaded file is a JPEG conversion. parentId guarantees\n\t\t// processItem routes this to the sideload endpoint, never the main\n\t\t// create endpoint. The `source_original` image_size token is\n\t\t// format-agnostic (it also covers HEIF) and matches the server-side\n\t\t// WP_REST_Attachments_Controller::IMAGE_SIZE_SOURCE_ORIGINAL constant.\n\t\tif ( item.originalHeicFile && attachment.id ) {\n\t\t\tdispatch.addSideloadItem( {\n\t\t\t\tfile: item.originalHeicFile,\n\t\t\t\tbatchId: uuidv4(),\n\t\t\t\tparentId: item.id,\n\t\t\t\tadditionalData: {\n\t\t\t\t\tpost: attachment.id,\n\t\t\t\t\timage_size: 'source_original',\n\t\t\t\t\tconvert_format: false,\n\t\t\t\t},\n\t\t\t\toperations: [ OperationType.Upload ],\n\t\t\t} );\n\t\t}\n\n\t\t// Animated GIF: transcode the original to a video and sideload it\n\t\t// as a companion file of this attachment (recorded in metadata as\n\t\t// `animated_video`), mirroring the HEIC original flow. The\n\t\t// TranscodeGif step keeps the WebCodecs concurrency limit;\n\t\t// parentId routes the result to the sideload endpoint, so no\n\t\t// separate attachment is created.\n\t\tif ( item.animatedGifFile && attachment.id ) {\n\t\t\tconst outputFormat =\n\t\t\t\tsettings.videoOutputFormat === 'video/webm' ? 'webm' : 'mp4';\n\n\t\t\tdispatch.addSideloadItem( {\n\t\t\t\tfile: item.animatedGifFile,\n\t\t\t\tbatchId: uuidv4(),\n\t\t\t\tparentId: item.id,\n\t\t\t\tadditionalData: {\n\t\t\t\t\tpost: attachment.id,\n\t\t\t\t\timage_size: 'animated_video',\n\t\t\t\t\tconvert_format: false,\n\t\t\t\t},\n\t\t\t\toperations: [\n\t\t\t\t\t[\n\t\t\t\t\t\tOperationType.TranscodeGif,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toutputFormat,\n\t\t\t\t\t\t} as OperationArgs[ OperationType.TranscodeGif ],\n\t\t\t\t\t],\n\t\t\t\t\tOperationType.Upload,\n\t\t\t\t],\n\t\t\t} );\n\n\t\t\t/*\n\t\t\t * The static first-frame poster companion is sideloaded by the\n\t\t\t * TranscodeGif operation once the video conversion succeeds (see\n\t\t\t * transcodeGifItem), so a failed conversion leaves no orphaned\n\t\t\t * poster.\n\t\t\t */\n\t\t}\n\n\t\t// Determine the EXIF orientation. For JPEG/TIFF the server reads it and\n\t\t// libvips auto-rotates the sub-sizes from EXIF. For AVIF/HEIF libheif/\n\t\t// libvips only auto-rotate from a native `irot` transform, never from\n\t\t// EXIF, so those sub-sizes must be rotated explicitly. Read the EXIF\n\t\t// orientation on the client for those formats and treat it as the\n\t\t// source of truth: `getUnappliedExifOrientation` returns 1 when an\n\t\t// `irot` transform is present (already handled on decode), otherwise\n\t\t// the EXIF orientation that nothing else applies.\n\t\t// See https://github.com/WordPress/gutenberg/issues/79383.\n\t\tlet exifOrientation = attachment.exif_orientation || 1;\n\t\tconst sourceType = item.sourceFile.type;\n\t\tconst isHeifFamily =\n\t\t\tsourceType === 'image/avif' || sourceType === 'image/heif';\n\n\t\tlet needsClientRotation = false;\n\t\tif ( isHeifFamily ) {\n\t\t\texifOrientation = getUnappliedExifOrientation(\n\t\t\t\tawait item.sourceFile.arrayBuffer()\n\t\t\t);\n\t\t\t// libvips will not auto-rotate these sub-sizes, so they must be\n\t\t\t// generated from an explicitly rotated source rather than the\n\t\t\t// original file.\n\t\t\tneedsClientRotation = exifOrientation !== 1;\n\t\t}\n\n\t\t// Rotate the source once and reuse it for the sideloaded \"original\"\n\t\t// (original_image metadata) and, for the client-rotation case, as the\n\t\t// thumbnail/scaled source. Images that were scaled\n\t\t// (bigImageSizeThreshold) are already rotated by vips, so the original\n\t\t// is skipped for them, matching WordPress core.\n\t\tlet rotatedSource: File | undefined;\n\t\t{\n\t\t\tconst needsRotation =\n\t\t\t\texifOrientation !== 1 && ! item.file.name.includes( '-scaled' );\n\n\t\t\tif ( ( needsRotation || needsClientRotation ) && attachment.id ) {\n\t\t\t\ttry {\n\t\t\t\t\trotatedSource = await vipsRotateImage(\n\t\t\t\t\t\titem.id,\n\t\t\t\t\t\titem.sourceFile,\n\t\t\t\t\t\texifOrientation,\n\t\t\t\t\t\titem.abortController?.signal\n\t\t\t\t\t);\n\t\t\t\t} catch {\n\t\t\t\t\t// If rotation fails, continue with thumbnail generation.\n\t\t\t\t\t// Thumbnails will still be rotated correctly by vips for\n\t\t\t\t\t// server-readable formats.\n\t\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t'Failed to rotate image, continuing with thumbnails'\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Sideload the rotated file as the \"original\" to set\n\t\t\t// original_image metadata; the server stores it in\n\t\t\t// $metadata['original_image'].\n\t\t\tif ( needsRotation && rotatedSource && attachment.id ) {\n\t\t\t\tdispatch.addSideloadItem( {\n\t\t\t\t\tfile: rotatedSource,\n\t\t\t\t\tbatchId: uuidv4(),\n\t\t\t\t\tparentId: item.id,\n\t\t\t\t\tadditionalData: {\n\t\t\t\t\t\tpost: attachment.id,\n\t\t\t\t\t\timage_size: 'original',\n\t\t\t\t\t\tconvert_format: false,\n\t\t\t\t\t},\n\t\t\t\t\toperations: [ OperationType.Upload ],\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\n\t\t// Client-side thumbnail generation for images.\n\t\tif (\n\t\t\t! item.parentId &&\n\t\t\tattachment.missing_image_sizes &&\n\t\t\tattachment.missing_image_sizes.length > 0\n\t\t) {\n\t\t\tconst allImageSizes = settings.allImageSizes || {};\n\t\t\tconst sizesToGenerate: string[] =\n\t\t\t\tattachment.missing_image_sizes as string[];\n\n\t\t\tconst thumbnailSource =\n\t\t\t\tneedsClientRotation && rotatedSource\n\t\t\t\t\t? rotatedSource\n\t\t\t\t\t: item.sourceFile;\n\t\t\tconst file = attachment.filename\n\t\t\t\t? renameFile( thumbnailSource, attachment.filename )\n\t\t\t\t: thumbnailSource;\n\t\t\tconst batchId = uuidv4();\n\n\t\t\t// Sub-sizes inherit the parent's UltraHDR status so that the\n\t\t\t// resize step routes through libvips's uhdrload/uhdrsave pipeline\n\t\t\t// (which preserves the gain map). Format transcoding is skipped\n\t\t\t// for UltraHDR sources because converting to a different codec\n\t\t\t// would strip the ISO 21496-1 gain map data.\n\t\t\tconst isUltraHdr = ultraHdrItems.has( item.id );\n\n\t\t\t// Read per-file format conversion data from the attachment response.\n\t\t\tconst outputMimeType = attachment.image_output_format;\n\t\t\tconst interlaced = attachment.image_save_progressive ?? false;\n\n\t\t\t// Resolve the size-aware encode quality from the\n\t\t\t// wp_editor_set_quality filter, carried in the upload response.\n\t\t\t// Quality is reported as 1-100 (WordPress scale); the vips worker\n\t\t\t// expects 0-1. Fall back to the generic setting, then the\n\t\t\t// hardcoded default, when the response predates this field.\n\t\t\tconst imageQuality = attachment.image_quality;\n\t\t\tconst fallbackQuality =\n\t\t\t\tsettings.imageQuality ?? DEFAULT_OUTPUT_QUALITY;\n\t\t\tconst defaultQuality =\n\t\t\t\ttypeof imageQuality?.default === 'number'\n\t\t\t\t\t? imageQuality.default / 100\n\t\t\t\t\t: fallbackQuality;\n\t\t\tconst qualityForSize = ( sizeName: string ): number => {\n\t\t\t\tconst sized = imageQuality?.sizes?.[ sizeName ];\n\t\t\t\tif ( typeof sized === 'number' ) {\n\t\t\t\t\treturn sized / 100;\n\t\t\t\t}\n\t\t\t\treturn defaultQuality;\n\t\t\t};\n\n\t\t\t// Check if thumbnails should be transcoded to a different format.\n\t\t\t// Uses the same transparency-aware logic as the main image\n\t\t\t// to avoid converting transparent PNGs to JPEG.\n\t\t\tlet thumbnailTranscodeOperation:\n\t\t\t\t| [\n\t\t\t\t\t\tOperationType.TranscodeImage,\n\t\t\t\t\t\tOperationArgs[ OperationType.TranscodeImage ],\n\t\t\t\t  ]\n\t\t\t\t| null = null;\n\n\t\t\tif ( ! isUltraHdr && outputMimeType ) {\n\t\t\t\tthumbnailTranscodeOperation = await getTranscodeImageOperation(\n\t\t\t\t\tthumbnailSource,\n\t\t\t\t\toutputMimeType,\n\t\t\t\t\tinterlaced,\n\t\t\t\t\tdefaultQuality\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Group sizes by dimensions to avoid creating duplicate files.\n\t\t\t// When multiple size names have the same width/height/crop,\n\t\t\t// only one physical file is generated and registered under\n\t\t\t// all matching size names via a single sideload request.\n\t\t\tconst dimensionGroups = new Map< string, string[] >();\n\t\t\tfor ( const name of sizesToGenerate ) {\n\t\t\t\tconst imageSize = allImageSizes[ name ];\n\t\t\t\tif ( ! imageSize ) {\n\t\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`Image size \"${ name }\" not found in configuration`\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst key = `${ imageSize.width }x${ imageSize.height }x${ imageSize.crop }`;\n\t\t\t\tconst group = dimensionGroups.get( key );\n\t\t\t\tif ( group ) {\n\t\t\t\t\tgroup.push( name );\n\t\t\t\t} else {\n\t\t\t\t\tdimensionGroups.set( key, [ name ] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( const [ , names ] of dimensionGroups ) {\n\t\t\t\tconst imageSize = allImageSizes[ names[ 0 ] ];\n\n\t\t\t\t// Sizes grouped here share dimensions, so wp_editor_set_quality\n\t\t\t\t// (which is dimension-aware) resolves to the same value for\n\t\t\t\t// every name in the group.\n\t\t\t\tconst sizeQuality = qualityForSize( names[ 0 ] );\n\n\t\t\t\t// Build operations list for this thumbnail. The resize step\n\t\t\t\t// is UltraHDR-aware and will preserve the gain map automatically.\n\t\t\t\tconst thumbnailOperations: Operation[] = [\n\t\t\t\t\t[\n\t\t\t\t\t\tOperationType.ResizeCrop,\n\t\t\t\t\t\t{ resize: imageSize, quality: sizeQuality },\n\t\t\t\t\t],\n\t\t\t\t];\n\n\t\t\t\t// Add transcoding if format conversion is configured and\n\t\t\t\t// the transparency check passed. For UltraHDR sources the\n\t\t\t\t// transcode is skipped so the gain map survives the resize.\n\t\t\t\t// Otherwise override the template's quality with this size's\n\t\t\t\t// resolved value.\n\t\t\t\tif ( ! isUltraHdr && thumbnailTranscodeOperation ) {\n\t\t\t\t\tthumbnailOperations.push( [\n\t\t\t\t\t\tthumbnailTranscodeOperation[ 0 ],\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t...thumbnailTranscodeOperation[ 1 ],\n\t\t\t\t\t\t\toutputQuality: sizeQuality,\n\t\t\t\t\t\t},\n\t\t\t\t\t] );\n\t\t\t\t}\n\n\t\t\t\tthumbnailOperations.push( OperationType.Upload );\n\n\t\t\t\t// Pass all size names so the server registers the same\n\t\t\t\t// file under every matching size name in metadata.\n\t\t\t\tconst imageSizeParam = names.length === 1 ? names[ 0 ] : names;\n\n\t\t\t\tdispatch.addSideloadItem( {\n\t\t\t\t\tfile,\n\t\t\t\t\tbatchId,\n\t\t\t\t\tparentId: item.id,\n\t\t\t\t\tadditionalData: {\n\t\t\t\t\t\t// Sideloading does not use the parent post ID but the\n\t\t\t\t\t\t// attachment ID as the image sizes need to be added to it.\n\t\t\t\t\t\tpost: attachment.id,\n\t\t\t\t\t\timage_size: imageSizeParam,\n\t\t\t\t\t\tconvert_format: false,\n\t\t\t\t\t},\n\t\t\t\t\toperations: thumbnailOperations,\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t// Create and sideload the scaled version if it exceeds the threshold.\n\t\t\t{\n\t\t\t\tconst { bigImageSizeThreshold } = settings;\n\t\t\t\tif ( bigImageSizeThreshold && attachment.id ) {\n\t\t\t\t\t// Check if the image actually exceeds the threshold.\n\t\t\t\t\t// Only create a scaled version for images larger than the threshold,\n\t\t\t\t\t// matching WordPress core's wp_create_image_subsizes() behavior.\n\t\t\t\t\tconst bitmap = await createImageBitmap( thumbnailSource );\n\t\t\t\t\tconst needsScaling =\n\t\t\t\t\t\tbitmap.width > bigImageSizeThreshold ||\n\t\t\t\t\t\tbitmap.height > bigImageSizeThreshold;\n\t\t\t\t\tbitmap.close();\n\n\t\t\t\t\tif ( needsScaling ) {\n\t\t\t\t\t\t// Rename sourceFile to match the server attachment filename.\n\t\t\t\t\t\tconst sourceForScaled = attachment.filename\n\t\t\t\t\t\t\t? renameFile( thumbnailSource, attachment.filename )\n\t\t\t\t\t\t\t: thumbnailSource;\n\n\t\t\t\t\t\t// Add scaling to queue. The resize step is UltraHDR-aware\n\t\t\t\t\t\t// and will preserve the gain map automatically.\n\t\t\t\t\t\tconst scaledOperations: Operation[] = [\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\tOperationType.ResizeCrop,\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tresize: {\n\t\t\t\t\t\t\t\t\t\twidth: bigImageSizeThreshold,\n\t\t\t\t\t\t\t\t\t\theight: bigImageSizeThreshold,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tisThresholdResize: true,\n\t\t\t\t\t\t\t\t\tquality: defaultQuality,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t];\n\n\t\t\t\t\t\tif ( ! isUltraHdr && thumbnailTranscodeOperation ) {\n\t\t\t\t\t\t\t// Add transcoding if format conversion is configured.\n\t\t\t\t\t\t\tscaledOperations.push(\n\t\t\t\t\t\t\t\tthumbnailTranscodeOperation\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tscaledOperations.push( OperationType.Upload );\n\n\t\t\t\t\t\tdispatch.addSideloadItem( {\n\t\t\t\t\t\t\tfile: sourceForScaled,\n\t\t\t\t\t\t\tbatchId,\n\t\t\t\t\t\t\tparentId: item.id,\n\t\t\t\t\t\t\tadditionalData: {\n\t\t\t\t\t\t\t\tpost: attachment.id,\n\t\t\t\t\t\t\t\timage_size: 'scaled',\n\t\t\t\t\t\t\t\tconvert_format: false,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\toperations: scaledOperations,\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tdispatch.finishOperation( id, {} );\n\t};\n}\n\n/**\n * Finalizes an uploaded item by calling the server's finalize endpoint.\n *\n * This triggers the wp_generate_attachment_metadata filter so that PHP\n * plugins can process the attachment after all client-side operations\n * (including thumbnail sideloads) are complete.\n *\n * @param id Item ID.\n */\nexport function finalizeItem( id: QueueItemId ) {\n\treturn async ( { select, dispatch }: ThunkArgs ) => {\n\t\tconst item = select.getItem( id );\n\t\tif ( ! item ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst attachment = item.attachment;\n\t\tconst { mediaFinalize } = select.getSettings();\n\t\tconst updates: Partial< QueueItem > = {};\n\n\t\t// Only finalize if we have an attachment ID and a mediaFinalize callback.\n\t\tif ( attachment?.id && mediaFinalize ) {\n\t\t\ttry {\n\t\t\t\t// Pass the post-finalize attachment through so the reducer\n\t\t\t\t// merges the updated URL (now pointing at the `-scaled` file)\n\t\t\t\t// into item.attachment. The next processItem pass fires\n\t\t\t\t// onChange with that URL, which is what the block stores —\n\t\t\t\t// and what `wp_calculate_image_srcset()` needs in order to\n\t\t\t\t// match a known size and emit srcset on the front end.\n\t\t\t\tconst updatedAttachment = await mediaFinalize(\n\t\t\t\t\tattachment.id,\n\t\t\t\t\titem.subSizes || []\n\t\t\t\t);\n\t\t\t\tif ( updatedAttachment ) {\n\t\t\t\t\tupdates.attachment = updatedAttachment;\n\t\t\t\t}\n\t\t\t} catch ( error ) {\n\t\t\t\t// Log but don't fail the upload if finalization fails.\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn( 'Media finalization failed:', error );\n\t\t\t}\n\t\t}\n\n\t\tdispatch.finishOperation( id, updates );\n\t};\n}\n\n/**\n * Revokes all blob URLs for a given item, freeing up memory.\n *\n * @param id Item ID.\n */\nexport function revokeBlobUrls( id: QueueItemId ) {\n\treturn async ( { select, dispatch }: ThunkArgs ) => {\n\t\tconst blobUrls = select.getBlobUrls( id );\n\n\t\tfor ( const blobUrl of blobUrls ) {\n\t\t\trevokeBlobURL( blobUrl );\n\t\t}\n\n\t\tdispatch< RevokeBlobUrlsAction >( {\n\t\t\ttype: Type.RevokeBlobUrls,\n\t\t\tid,\n\t\t} );\n\t};\n}\n\n/**\n * Updates the progress of an item.\n *\n * @param id       Item ID.\n * @param progress Progress value (0-100).\n */\nexport function updateItemProgress( id: QueueItemId, progress: number ) {\n\treturn async ( { dispatch }: ThunkArgs ) => {\n\t\tdispatch< UpdateProgressAction >( {\n\t\t\ttype: Type.UpdateProgress,\n\t\t\tid,\n\t\t\tprogress,\n\t\t} );\n\t};\n}\n\n/**\n * Returns an action object that updates the store settings.\n *\n * Useful for testing purposes.\n *\n * @param settings\n * @return Action object.\n */\nexport function updateSettings(\n\tsettings: Partial< Settings >\n): UpdateSettingsAction {\n\treturn {\n\t\ttype: Type.UpdateSettings,\n\t\tsettings,\n\t};\n}\n"],
  "mappings": ";AAGA,SAAS,MAAM,cAAc;AAK7B,SAAS,eAAe,WAAW,qBAAqB;AAExD,SAAS,UAAU;AAMnB;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,2BAA2B;AACpC,SAAS,mCAAmC;AAC5C;AAAA,EACC;AAAA,EACA;AAAA,OACM;AACP,SAAS,0BAA0B;AACnC,SAAS,kCAAkC,uBAAuB;AAClE,SAAS,gBAAgB;AACzB,SAAS,WAAW,mBAAmB;AACvC,SAAS,eAAe;AACxB;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,OACM;AA+BP,SAAS,YAAY,eAAe,YAAY;AAEhD,SAAS,uBAAuB;AAEhC,IAAM,yBAAyB;AAS/B,IAAM,gBAAgB,oBAAI,IAAmB;AAwEtC,SAAS,QAAS;AAAA,EACxB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB,CAAC;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAiB;AAChB,SAAO,OAAQ,EAAE,SAAS,MAAkB;AAC3C,UAAM,SAAS,OAAO;AAItB,UAAM,OAAO,kBAAmB,UAAW;AAE3C,QAAI;AAGJ,QAAK,EAAI,gBAAgB,WAAa;AACrC,gBAAU,cAAe,IAAK;AAC9B,eAAgC;AAAA,QAC/B,MAAM,KAAK;AAAA,QACX,IAAI;AAAA,QACJ;AAAA,MACD,CAAE;AAAA,IACH;AAEA,aAAuB;AAAA,MACtB,MAAM,KAAK;AAAA,MACX,MAAM;AAAA,QACL,IAAI;AAAA,QACJ;AAAA,QACA,QAAQ,WAAW;AAAA,QACnB,YAAY,UAAW,IAAK;AAAA,QAC5B;AAAA,QACA,YAAY;AAAA,UACX,KAAK;AAAA,QACN;AAAA,QACA,gBAAgB;AAAA,UACf,oBAAoB;AAAA,UACpB,GAAG;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,iBAAiB,mBAAmB,IAAI,gBAAgB;AAAA,QACxD,YAAY,MAAM,QAAS,UAAW,IACnC,aACA,CAAE,cAAc,OAAQ;AAAA,MAC5B;AAAA,IACD,CAAE;AAEF,aAAS,YAAa,MAAO;AAAA,EAC9B;AACD;AAwBO,SAAS,gBAAiB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAyB;AACxB,SAAO,CAAE,EAAE,SAAS,MAAkB;AACrC,UAAM,SAAS,OAAO;AACtB,aAAuB;AAAA,MACtB,MAAM,KAAK;AAAA,MACX,MAAM;AAAA,QACL,IAAI;AAAA,QACJ;AAAA,QACA,QAAQ,WAAW;AAAA,QACnB,YAAY,UAAW,IAAK;AAAA,QAC5B;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,UACf,GAAG;AAAA,QACJ;AAAA,QACA;AAAA,QACA,YAAY,MAAM,QAAS,UAAW,IACnC,aACA,CAAE,cAAc,OAAQ;AAAA,QAC3B,iBAAiB,IAAI,gBAAgB;AAAA,MACtC;AAAA,IACD,CAAE;AAEF,aAAS,YAAa,MAAO;AAAA,EAC9B;AACD;AASO,SAAS,YAAa,IAAkB;AAC9C,SAAO,OAAQ,EAAE,QAAQ,SAAS,MAAkB;AACnD,QAAK,OAAO,SAAS,GAAI;AACxB;AAAA,IACD;AAEA,UAAM,OAAO,OAAO,QAAS,EAAG;AAChC,QAAK,CAAE,MAAO;AACb;AAAA,IACD;AAEA,UAAM;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD,IAAI;AAEJ,UAAM,YAAY,MAAM,QAAS,KAAK,aAAc,CAAE,CAAE,IACrD,KAAK,WAAY,CAAE,EAAG,CAAE,IACxB,KAAK,aAAc,CAAE;AACxB,UAAM,gBAAgB,MAAM,QAAS,KAAK,aAAc,CAAE,CAAE,IACzD,KAAK,WAAY,CAAE,EAAG,CAAE,IACxB;AAOH,QAAK,cAAc,cAAc,QAAS;AACzC,YAAM,WAAW,OAAO,YAAY;AACpC,YAAM,cAAc,OAAO,qBAAqB;AAChD,UAAK,eAAe,SAAS,sBAAuB;AACnD;AAAA,MACD;AAAA,IACD;AAQA,QACC,cAAc,cAAc,cAC5B,cAAc,cAAc,QAC3B;AACD,YAAM,WAAW,OAAO,YAAY;AACpC,YAAM,cAAc,OAAO,8BAA8B;AACzD,UAAK,eAAe,SAAS,8BAA+B;AAC3D;AAAA,MACD;AAAA,IACD;AAMA,QAAK,cAAc,cAAc,cAAe;AAC/C,YAAM,cAAc,OAAO,8BAA8B;AACzD,UAAK,eAAe,GAAI;AACvB;AAAA,MACD;AAAA,IACD;AAEA,QAAK,YAAa;AAIjB,YAAM,YACL,WAAW,OAAO,cAAc,KAAM,WAAW,GAAI;AACtD,UAAK,CAAE,WAAY;AAClB,mBAAY,CAAE,UAAW,CAAE;AAAA,MAC5B;AAAA,IACD;AAQA,QAAK,CAAE,WAAY;AAClB,UACC,YACE,CAAE,YAAY,CAAE,OAAO,0BAA2B,EAAG,GACtD;AACD,YAAK,YAAa;AACjB,sBAAa,CAAE,UAAW,CAAE;AAAA,QAC7B;AAEA,iBAAS,WAAY,EAAG;AACxB,iBAAS,eAAgB,EAAG;AAE5B,YAAK,WAAW,OAAO,gBAAiB,OAAQ,GAAI;AACnD,2BAAiB;AAAA,QAClB;AAAA,MACD;AAGA,UAAK,YAAY,WAAW,OAAO,gBAAiB,OAAQ,GAAI;AAC/D,cAAM,aAAa,OAAO,QAAS,QAAS;AAC5C,YAAK,CAAE,YAAa;AACnB;AAAA,QACD;AAGA,YACC,WAAW,cACX,WAAW,WAAW,SAAS,GAC9B;AACD,mBAAS,YAAa,QAAS;AAC/B;AAAA,QACD;AAEA,YAAK,YAAa;AACjB,qBAAW,YAAa,CAAE,UAAW,CAAE;AAAA,QACxC;AAEA,iBAAS,WAAY,QAAS;AAC9B,iBAAS,eAAgB,QAAS;AAElC,YACC,WAAW,WACX,OAAO,gBAAiB,WAAW,OAAQ,GAC1C;AACD,qBAAW,iBAAiB;AAAA,QAC7B;AAAA,MACD;AAOA;AAAA,IACD;AAGA,QACC,cAAc,cAAc,YAC5B,OAAO,0BAA2B,EAAG,GACpC;AACD;AAAA,IACD;AAEA,aAAkC;AAAA,MACjC,MAAM,KAAK;AAAA,MACX;AAAA,MACA;AAAA,IACD,CAAE;AAEF,YAAS,WAAY;AAAA,MACpB,KAAK,cAAc;AAClB,iBAAS,YAAa,KAAK,EAAG;AAC9B;AAAA,MAED,KAAK,cAAc;AAClB,iBAAS;AAAA,UACR,KAAK;AAAA,UACL;AAAA,QACD;AACA;AAAA,MAED,KAAK,cAAc;AAClB,iBAAS;AAAA,UACR,KAAK;AAAA,UACL;AAAA,QACD;AACA;AAAA,MAED,KAAK,cAAc;AAClB,iBAAS;AAAA,UACR,KAAK;AAAA,UACL;AAAA,QACD;AACA;AAAA,MAED,KAAK,cAAc;AAClB,iBAAS;AAAA,UACR,KAAK;AAAA,UACL;AAAA,QACD;AACA;AAAA,MAED,KAAK,cAAc;AAClB,YAAK,KAAK,UAAW;AACpB,mBAAS,aAAc,EAAG;AAAA,QAC3B,OAAO;AACN,mBAAS,WAAY,EAAG;AAAA,QACzB;AACA;AAAA,MAED,KAAK,cAAc;AAClB,iBAAS,mBAAoB,EAAG;AAChC;AAAA,MAED,KAAK,cAAc;AAClB,iBAAS,aAAc,EAAG;AAC1B;AAAA,MAED,KAAK,cAAc;AAClB,iBAAS,eAAgB,EAAG;AAC5B;AAAA,IACF;AAAA,EACD;AACD;AASO,SAAS,aAA+B;AAC9C,SAAO;AAAA,IACN,MAAM,KAAK;AAAA,EACZ;AACD;AAQO,SAAS,cAAc;AAC7B,SAAO,OAAQ,EAAE,QAAQ,SAAS,MAAkB;AACnD,aAA+B;AAAA,MAC9B,MAAM,KAAK;AAAA,IACZ,CAAE;AAEF,eAAY,QAAQ,OAAO,YAAY,GAAI;AAI1C,UAAK,KAAK,WAAW,WAAW,cAAe;AAC9C,iBAAS,aAAc,KAAK,EAAG;AAAA,MAChC,OAAO;AACN,iBAAS,YAAa,KAAK,EAAG;AAAA,MAC/B;AAAA,IACD;AAAA,EACD;AACD;AAOO,SAAS,UAAW,IAAkB;AAC5C,SAAO,OAAQ,EAAE,SAAS,MAAkB;AAC3C,aAA6B;AAAA,MAC5B,MAAM,KAAK;AAAA,MACX;AAAA,IACD,CAAE;AAAA,EACH;AACD;AAOO,SAAS,WAAY,IAAkB;AAC7C,SAAO,OAAQ,EAAE,QAAQ,SAAS,MAAkB;AACnD,UAAM,OAAO,OAAO,QAAS,EAAG;AAChC,QAAK,CAAE,MAAO;AACb;AAAA,IACD;AAKA,kBAAc,OAAQ,EAAG;AAGzB,oBAAiB,EAAG;AAEpB,aAAU;AAAA,MACT,MAAM,KAAK;AAAA,MACX;AAAA,IACD,CAAE;AAOF,QAAK,OAAO,YAAY,EAAE,WAAW,GAAI;AACxC,0BAAoB;AACpB,qCAA+B;AAAA,IAChC;AAAA,EACD;AACD;AAQO,SAAS,gBACf,IACA,SACC;AACD,SAAO,OAAQ,EAAE,QAAQ,SAAS,MAAkB;AACnD,UAAM,OAAO,OAAO,QAAS,EAAG;AAChC,UAAM,oBAAoB,MAAM;AAEhC,aAAmC;AAAA,MAClC,MAAM,KAAK;AAAA,MACX;AAAA,MACA,MAAM;AAAA,IACP,CAAE;AAEF,aAAS,YAAa,EAAG;AAMzB,QAAK,sBAAsB,cAAc,QAAS;AACjD,YAAM,iBAAiB,OAAO,kBAAkB;AAChD,iBAAY,eAAe,gBAAiB;AAC3C,iBAAS,YAAa,YAAY,EAAG;AAAA,MACtC;AAAA,IACD;AAOA,QACC,sBAAsB,cAAc,cACpC,sBAAsB,cAAc,QACnC;AACD,YAAM,eAAe,OAAO,0BAA0B;AACtD,iBAAY,eAAe,cAAe;AACzC,iBAAS,YAAa,YAAY,EAAG;AAAA,MACtC;AAAA,IACD;AAMA,QAAK,sBAAsB,cAAc,cAAe;AACvD,YAAM,eAAe,OAAO,0BAA0B;AACtD,iBAAY,eAAe,cAAe;AACzC,iBAAS,YAAa,YAAY,EAAG;AAAA,MACtC;AAAA,IACD;AAKA,QACC,sBAAsB,cAAc,cACpC,sBAAsB,cAAc,UACpC,sBAAsB,cAAc,gBACnC;AACD,6BAAwB,OAAO,8BAA8B,CAAE;AAAA,IAChE;AAAA,EACD;AACD;AAEA,IAAM,sBAAsB,CAAE,QAAQ,QAAQ,QAAQ,OAAO,KAAM;AAQnE,SAAS,mBAAoB,QAAwC;AACpE,SAAO,oBAAoB,SAAU,MAAsB;AAC5D;AAcA,eAAsB,2BACrB,MACA,gBACA,aAAsB,OACtB,UAAkB,wBAOjB;AAGD,MAAK,KAAK,SAAS,eAAe,mBAAmB,cAAe;AACnE,UAAM,UAAU,cAAe,IAAK;AACpC,QAAI;AACH,YAAM,WAAW,MAAM,oBAAqB,OAAQ;AACpD,UAAK,UAAW;AAEf,eAAO;AAAA,MACR;AAAA,IACD,QAAQ;AAEP,aAAO;AAAA,IACR,UAAE;AACD,oBAAe,OAAQ;AAAA,IACxB;AAAA,EACD;AAEA,QAAM,aAAa,eAAe,MAAO,GAAI,EAAG,CAAE;AAClD,MAAK,CAAE,mBAAoB,UAAW,GAAI;AAEzC,WAAO;AAAA,EACR;AAEA,SAAO;AAAA,IACN,cAAc;AAAA,IACd;AAAA,MACC,cAAc;AAAA,MACd,eAAe;AAAA,MACf;AAAA,IACD;AAAA,EACD;AACD;AAmBO,SAAS,YAAa,IAAkB;AAC9C,SAAO,OAAQ,EAAE,QAAQ,SAAS,MAAkB;AACnD,UAAM,OAAO,OAAO,QAAS,EAAG;AAChC,QAAK,CAAE,MAAO;AACb;AAAA,IACD;AACA,UAAM,EAAE,KAAK,IAAI;AAEjB,UAAM,aAA0B,CAAC;AACjC,UAAM,WAAW,OAAO,YAAY;AAcpC,QACC,KAAK,SAAS,eACd,SAAS,eAAe,SACxB,OAAO,iBAAiB,eACxB,OAAO,iBAAiB,aACvB;AACD,UAAI,aAAa;AACjB,UAAI;AACH,qBAAa,cAAe,MAAM,KAAK,YAAY,CAAE;AAAA,MACtD,QAAQ;AAGP,qBAAa;AAAA,MACd;AACA,UAAK,YAAa;AAOjB,YAAI,kBAAkB;AACtB,cAAM,UAAU,cAAe,IAAK;AACpC,YAAI;AACH,4BAAkB,MAAM,oBAAqB,OAAQ;AAAA,QACtD,QAAQ;AAGP,4BAAkB;AAAA,QACnB,UAAE;AACD,wBAAe,OAAQ;AAAA,QACxB;AAEA,YAAK,CAAE,iBAAkB;AACxB,qBAAW;AAAA,YACV,cAAc;AAAA,YACd,cAAc;AAAA,YACd,cAAc;AAAA,UACf;AAEA,mBAAiC;AAAA,YAChC,MAAM,KAAK;AAAA,YACX;AAAA,YACA;AAAA,UACD,CAAE;AAIF,mBAAS,gBAAiB,IAAI;AAAA,YAC7B,iBAAiB,KAAK;AAAA,UACvB,CAAE;AACF;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAEA,QAAI,WAAwB;AAE5B,UAAM,UAAU,KAAK,KAAK,WAAY,QAAS;AAC/C,UAAM,kBAAkB,iCAAiC;AAAA,MACxD,KAAK;AAAA,IACN;AACA,UAAM,SAAS,gBAAgB,SAAU,KAAK,IAAK;AAQnD,QAAI,oBAAoB;AACxB,QAAK,WAAW,iBAAkB;AACjC,YAAM,aAAa,MAAM,mBAAoB,IAAK;AAClD,UAAK,cAAc,8BAA+B,UAAW,GAAI;AAChE,4BAAoB;AAAA,MACrB;AAAA,IACD;AAMA,QAAK,KAAK,SAAS,gBAAgB,CAAE,mBAAoB;AACxD,iBAAW,KAAM,cAAc,cAAe;AAAA,IAC/C;AAgBA,QAAK,WAAW,mBAAmB,CAAE,mBAAoB;AACxD,iBAAW;AAAA,QACV,cAAc;AAAA,QACd,cAAc;AAAA,QACd,cAAc;AAAA,MACf;AAAA,IACD,WAAY,WAAW,QAAS;AAO/B,UAAI;AACH,mBAAW,MAAM;AAAA,UAChB;AAAA,UACA,SAAS,gBAAgB;AAAA,QAC1B;AAAA,MACD,QAAQ;AACP,iBAAS;AAAA,UACR;AAAA,UACA,IAAI,YAAa;AAAA,YAChB,MAAM,UAAU;AAAA,YAChB,SACC;AAAA,YACD;AAAA,UACD,CAAE;AAAA,QACH;AACA;AAAA,MACD;AAEA,iBAAW;AAAA,QACV,cAAc;AAAA,QACd,cAAc;AAAA,QACd,cAAc;AAAA,MACf;AAAA,IACD,OAAO;AACN,iBAAW,KAAM,cAAc,MAAO;AAAA,IACvC;AAEA,aAAiC;AAAA,MAChC,MAAM,KAAK;AAAA,MACX;AAAA,MACA;AAAA,IACD,CAAE;AAMF,QAAI;AACJ,QAAK,UAAU,UAAW;AAOzB,YAAM,gBAAgB,2BAA2B;AACjD,gBAAU;AAAA,QACT,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,kBAAkB,KAAK;AAAA,QACvB,gBAAgB;AAAA,UACf,GAAG,KAAK;AAAA,UACR,oBAAoB,CAAE;AAAA,UACtB,gBAAgB;AAAA,QACjB;AAAA,MACD;AAAA,IACD,WAAY,CAAE,mBAAmB,CAAE,WAAW,mBAAoB;AAIjE,gBAAU;AAAA,QACT,gBAAgB;AAAA,UACf,GAAG,KAAK;AAAA,UACR,oBAAoB;AAAA,UACpB,gBAAgB;AAAA,QACjB;AAAA,MACD;AAAA,IACD,OAAO;AACN,gBAAU;AAAA,QACT,gBAAgB;AAAA,UACf,GAAG,KAAK;AAAA,UACR,oBAAoB;AAAA,QACrB;AAAA,MACD;AAAA,IACD;AAEA,aAAS,gBAAiB,IAAI,OAAQ;AAAA,EACvC;AACD;AASO,SAAS,eAAgB,IAAkB;AACjD,SAAO,OAAQ,EAAE,QAAQ,SAAS,MAAkB;AACnD,UAAM,OAAO,OAAO,QAAS,EAAG;AAChC,QAAK,CAAE,MAAO;AACb;AAAA,IACD;AAEA,QAAI;AACJ,QAAI;AACH,YAAM,SAAS,MAAM,KAAK,KAAK,YAAY;AAC3C,aAAO,MAAM,oBAAqB,MAAO;AAAA,IAC1C,QAAQ;AAAA,IAER;AAMA,QAAK,MAAO;AACX,oBAAc,IAAK,EAAG;AAAA,IACvB;AAEA,aAAS,gBAAiB,IAAI,CAAC,CAAE;AAAA,EAClC;AACD;AAOO,SAAS,WAAY,IAAkB;AAC7C,SAAO,OAAQ,EAAE,QAAQ,SAAS,MAAkB;AACnD,UAAM,OAAO,OAAO,QAAS,EAAG;AAChC,QAAK,CAAE,MAAO;AACb;AAAA,IACD;AAEA,UAAM,YAAY,YAAY,IAAI;AAClC,QAAI,WAAW;AAEf,UAAM,eAAe,CAAE,eAAuC;AAC7D,UAAK,UAAW;AACf;AAAA,MACD;AACA,iBAAW;AAEX,cAAS;AAAA,QACR,aAAa,UAAW,KAAK,KAAK,IAAK;AAAA,QACvC;AAAA,QACA,aAAa,KAAK,KAAK;AAAA,QACvB,YAAY;AAAA,UACX,CAAE,WAAW,KAAK,EAAG;AAAA,UACrB,CAAE,aAAa,KAAK,KAAK,IAAK;AAAA,QAC/B;AAAA,MACD,CAAE;AAEF,eAAS,gBAAiB,IAAI,EAAE,WAAW,CAAE;AAAA,IAC9C;AAEA,WAAO,YAAY,EAAE,YAAa;AAAA,MACjC,WAAW,CAAE,KAAK,IAAK;AAAA,MACvB,gBAAgB,KAAK;AAAA,MACrB,QAAQ,KAAK,iBAAiB;AAAA,MAC9B,cAAc,CAAE,CAAE,UAAW,MAAO;AACnC,YAAK,cAAc,CAAE,UAAW,WAAW,GAAI,GAAI;AAClD,uBAAc,UAAW;AAAA,QAC1B;AAAA,MACD;AAAA,MACA,WAAW,CAAE,CAAE,UAAW,MAAO;AAChC,qBAAc,UAAW;AAAA,MAC1B;AAAA,MACA,SAAS,CAAE,UAAW;AACrB,iBAAS,WAAY,IAAI,KAAM;AAAA,MAChC;AAAA,IACD,CAAE;AAAA,EACH;AACD;AAOO,SAAS,aAAc,IAAkB;AAC/C,SAAO,OAAQ,EAAE,QAAQ,SAAS,MAAkB;AACnD,UAAM,OAAO,OAAO,QAAS,EAAG;AAChC,QAAK,CAAE,MAAO;AACb;AAAA,IACD;AAEA,UAAM,EAAE,MAAM,GAAG,eAAe,IAC/B,KAAK;AAEN,UAAM,gBAAgB,OAAO,YAAY,EAAE;AAC3C,QAAK,CAAE,eAAgB;AAEtB,eAAS,gBAAiB,IAAI,CAAC,CAAE;AACjC;AAAA,IACD;AAEA,UAAM,YAAY,YAAY,IAAI;AAElC,kBAAe;AAAA,MACd,MAAM,KAAK;AAAA,MACX,cAAc;AAAA,MACd;AAAA,MACA,QAAQ,KAAK,iBAAiB;AAAA,MAC9B,WAAW,CAAE,YAA0B;AACtC,gBAAS;AAAA,UACR,aAAa,YAAa,KAAK,KAAK,IAAK;AAAA,UACzC;AAAA,UACA,aAAa,KAAK,KAAK;AAAA,UACvB,YAAY;AAAA,YACX,CAAE,WAAW,KAAK,EAAG;AAAA,YACrB,CAAE,aAAa,KAAK,KAAK,IAAK;AAAA,UAC/B;AAAA,QACD,CAAE;AAGF,YAAK,KAAK,UAAW;AACpB,mBAAqC;AAAA,YACpC,MAAM,KAAK;AAAA,YACX,IAAI,KAAK;AAAA,YACT;AAAA,UACD,CAAE;AAAA,QACH;AACA,iBAAS,gBAAiB,IAAI,CAAC,CAAE;AAAA,MAClC;AAAA,MACA,SAAS,CAAE,UAAW;AACrB,iBAAS,WAAY,IAAI,KAAM;AAAA,MAChC;AAAA,IACD,CAAE;AAAA,EACH;AACD;AAUO,SAAS,eAAgB,IAAiB,MAA4B;AAC5E,SAAO,OAAQ,EAAE,QAAQ,SAAS,MAAkB;AACnD,UAAM,OAAO,OAAO,QAAS,EAAG;AAChC,QAAK,CAAE,MAAO;AACb;AAAA,IACD;AAEA,QAAK,CAAE,MAAM,QAAS;AACrB,eAAS,gBAAiB,IAAI;AAAA,QAC7B,MAAM,KAAK;AAAA,MACZ,CAAE;AACF;AAAA,IACD;AAEA,UAAM,YAAY,YAAY,IAAI;AAGlC,UAAM,YAAY,QAAS,KAAK,QAAS;AAEzC,UAAM,eAAe,QAAS,KAAK,iBAAkB;AAErD,QAAI;AACH,YAAM,OAAO,MAAM;AAAA,QAClB,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL;AAAA;AAAA,QACA;AAAA,QACA,KAAK,iBAAiB;AAAA,QACtB;AAAA,QACA,KAAK;AAAA,MACN;AAEA,cAAS;AAAA,QACR,aAAa,cAAe,KAAK,KAAK,IAAK;AAAA,QAC3C;AAAA,QACA,aAAa,KAAK,KAAK;AAAA,QACvB,YAAY;AAAA,UACX,CAAE,WAAW,KAAK,EAAG;AAAA,UACrB,CAAE,aAAa,KAAK,KAAK,IAAK;AAAA,QAC/B;AAAA,MACD,CAAE;AAEF,YAAM,UAAU,cAAe,IAAK;AACpC,eAAgC;AAAA,QAC/B,MAAM,KAAK;AAAA,QACX;AAAA,QACA;AAAA,MACD,CAAE;AAEF,eAAS,gBAAiB,IAAI;AAAA,QAC7B;AAAA,QACA,YAAY;AAAA,UACX,KAAK;AAAA,QACN;AAAA,MACD,CAAE;AAAA,IACH,SAAU,OAAQ;AACjB,eAAS;AAAA,QACR;AAAA,QACA,IAAI,YAAa;AAAA,UAChB,MAAM,UAAU;AAAA,UAChB,SAAS;AAAA,YACR;AAAA,UACD;AAAA,UACA,MAAM,KAAK;AAAA,UACX,OAAO,iBAAiB,QAAQ,QAAQ;AAAA,QACzC,CAAE;AAAA,MACH;AAAA,IACD;AAAA,EACD;AACD;AAcO,SAAS,WAAY,IAAiB,MAAwB;AACpE,SAAO,OAAQ,EAAE,QAAQ,SAAS,MAAkB;AACnD,UAAM,OAAO,OAAO,QAAS,EAAG;AAChC,QAAK,CAAE,MAAO;AACb;AAAA,IACD;AAGA,QAAK,CAAE,MAAM,eAAe,KAAK,gBAAgB,GAAI;AACpD,eAAS,gBAAiB,IAAI;AAAA,QAC7B,MAAM,KAAK;AAAA,MACZ,CAAE;AACF;AAAA,IACD;AAEA,UAAM,YAAY,YAAY,IAAI;AAElC,QAAI;AACH,YAAM,OAAO,MAAM;AAAA,QAClB,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK,iBAAiB;AAAA,MACvB;AAEA,cAAS;AAAA,QACR,aAAa,UAAW,KAAK,KAAK,IAAK;AAAA,QACvC;AAAA,QACA,aAAa,KAAK,KAAK;AAAA,QACvB,YAAY;AAAA,UACX,CAAE,WAAW,KAAK,EAAG;AAAA,UACrB,CAAE,aAAa,KAAK,KAAK,IAAK;AAAA,QAC/B;AAAA,MACD,CAAE;AAEF,YAAM,UAAU,cAAe,IAAK;AACpC,eAAgC;AAAA,QAC/B,MAAM,KAAK;AAAA,QACX;AAAA,QACA;AAAA,MACD,CAAE;AAEF,eAAS,gBAAiB,IAAI;AAAA,QAC7B;AAAA,QACA,YAAY;AAAA,UACX,KAAK;AAAA,QACN;AAAA,MACD,CAAE;AAAA,IACH,SAAU,OAAQ;AACjB,eAAS;AAAA,QACR;AAAA,QACA,IAAI,YAAa;AAAA,UAChB,MAAM,UAAU;AAAA,UAChB,SAAS;AAAA,YACR;AAAA,UACD;AAAA,UACA,MAAM,KAAK;AAAA,UACX,OAAO,iBAAiB,QAAQ,QAAQ;AAAA,QACzC,CAAE;AAAA,MACH;AAAA,IACD;AAAA,EACD;AACD;AAaO,SAAS,mBACf,IACA,MACC;AACD,SAAO,OAAQ,EAAE,QAAQ,SAAS,MAAkB;AACnD,UAAM,OAAO,OAAO,QAAS,EAAG;AAChC,QAAK,CAAE,MAAO;AACb;AAAA,IACD;AAGA,QAAK,CAAE,MAAM,cAAe;AAC3B,eAAS,gBAAiB,IAAI;AAAA,QAC7B,MAAM,KAAK;AAAA,MACZ,CAAE;AACF;AAAA,IACD;AAEA,UAAM,YAAY,YAAY,IAAI;AAElC,UAAM,iBAAiB,SAAU,KAAK,YAAa;AAMnD,UAAM,UAAU,KAAK,iBAAiB;AACtC,UAAM,aAAa,KAAK,cAAc;AAEtC,QAAI;AACH,YAAM,OAAO,MAAM;AAAA,QAClB,KAAK;AAAA,QACL,KAAK;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAEA,cAAS;AAAA,QACR,aAAa,aAAc,KAAK,KAAK,IAAK;AAAA,QAC1C;AAAA,QACA,aAAa,KAAK,KAAK;AAAA,QACvB,YAAY;AAAA,UACX,CAAE,WAAW,KAAK,EAAG;AAAA,UACrB,CAAE,aAAa,KAAK,KAAK,IAAK;AAAA,QAC/B;AAAA,MACD,CAAE;AAEF,YAAM,UAAU,cAAe,IAAK;AACpC,eAAgC;AAAA,QAC/B,MAAM,KAAK;AAAA,QACX;AAAA,QACA;AAAA,MACD,CAAE;AAEF,eAAS,gBAAiB,IAAI;AAAA,QAC7B;AAAA,QACA,YAAY;AAAA,UACX,KAAK;AAAA,QACN;AAAA,MACD,CAAE;AAAA,IACH,SAAU,OAAQ;AACjB,eAAS;AAAA,QACR;AAAA,QACA,IAAI,YAAa;AAAA,UAChB,MAAM,UAAU;AAAA,UAChB,SACC;AAAA,UACD,MAAM,KAAK;AAAA,UACX,OAAO,iBAAiB,QAAQ,QAAQ;AAAA,QACzC,CAAE;AAAA,MACH;AAAA,IACD;AAAA,EACD;AACD;AAgBO,SAAS,iBACf,IACA,MACC;AACD,SAAO,OAAQ,EAAE,QAAQ,SAAS,MAAkB;AACnD,UAAM,OAAO,OAAO,QAAS,EAAG;AAChC,QAAK,CAAE,MAAO;AACb;AAAA,IACD;AAEA,UAAM,eAAe,MAAM,gBAAgB;AAC3C,UAAM,iBAAiB,SAAU,YAAa;AAM9C,UAAM,UAAU,KAAK;AAErB,QAAI;AACH,YAAM,OAAO,MAAM;AAAA,QAClB,KAAK;AAAA,QACL;AAAA,QACA;AAAA,MACD;AAKA,eAAS,gBAAiB,IAAI,EAAE,KAAK,CAAE;AAavC,eAAS,gBAAiB;AAAA,QACzB,MAAM;AAAA,QACN,SAAS,OAAO;AAAA,QAChB,UAAU,KAAK;AAAA,QACf,gBAAgB;AAAA,UACf,MAAM,KAAK,gBAAgB;AAAA,UAC3B,YAAY;AAAA,UACZ,gBAAgB;AAAA,QACjB;AAAA,QACA,YAAY;AAAA,UACX;AAAA,YACC,cAAc;AAAA,YACd;AAAA,cACC,cAAc;AAAA,cACd,eAAe;AAAA,cACf,YAAY;AAAA,YACb;AAAA,UACD;AAAA,UACA,cAAc;AAAA,QACf;AAAA,MACD,CAAE;AAAA,IACH,SAAU,OAAQ;AAOjB,UAAK,6BAA8B,KAAM,GAAI;AAC5C,iBAAS;AAAA,UACR;AAAA,UACA,IAAI,MAAO,qCAAsC;AAAA,UACjD;AAAA,QACD;AACA;AAAA,MACD;AAOA,cAAQ;AAAA,QACP;AAAA,QACA;AAAA,MACD;AACA,eAAS;AAAA,QACR;AAAA,QACA,IAAI,YAAa;AAAA,UAChB,MAAM,UAAU;AAAA,UAChB,SAAS;AAAA,UACT,MAAM,KAAK;AAAA,UACX,OAAO,iBAAiB,QAAQ,QAAQ;AAAA,QACzC,CAAE;AAAA,QACF;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD;AAUO,SAAS,mBAAoB,IAAkB;AACrD,SAAO,OAAQ,EAAE,QAAQ,SAAS,MAAkB;AACnD,UAAM,OAAO,OAAO,QAAS,EAAG;AAChC,QAAK,CAAE,MAAO;AACb;AAAA,IACD;AAEA,QAAK,CAAE,KAAK,YAAa;AACxB,eAAS,gBAAiB,IAAI,CAAC,CAAE;AACjC;AAAA,IACD;AACA,UAAM,aAAa,KAAK;AACxB,UAAM,WAAW,OAAO,YAAY;AAUpC,QAAK,KAAK,oBAAoB,WAAW,IAAK;AAC7C,eAAS,gBAAiB;AAAA,QACzB,MAAM,KAAK;AAAA,QACX,SAAS,OAAO;AAAA,QAChB,UAAU,KAAK;AAAA,QACf,gBAAgB;AAAA,UACf,MAAM,WAAW;AAAA,UACjB,YAAY;AAAA,UACZ,gBAAgB;AAAA,QACjB;AAAA,QACA,YAAY,CAAE,cAAc,MAAO;AAAA,MACpC,CAAE;AAAA,IACH;AAQA,QAAK,KAAK,mBAAmB,WAAW,IAAK;AAC5C,YAAM,eACL,SAAS,sBAAsB,eAAe,SAAS;AAExD,eAAS,gBAAiB;AAAA,QACzB,MAAM,KAAK;AAAA,QACX,SAAS,OAAO;AAAA,QAChB,UAAU,KAAK;AAAA,QACf,gBAAgB;AAAA,UACf,MAAM,WAAW;AAAA,UACjB,YAAY;AAAA,UACZ,gBAAgB;AAAA,QACjB;AAAA,QACA,YAAY;AAAA,UACX;AAAA,YACC,cAAc;AAAA,YACd;AAAA,cACC;AAAA,YACD;AAAA,UACD;AAAA,UACA,cAAc;AAAA,QACf;AAAA,MACD,CAAE;AAAA,IAQH;AAWA,QAAI,kBAAkB,WAAW,oBAAoB;AACrD,UAAM,aAAa,KAAK,WAAW;AACnC,UAAM,eACL,eAAe,gBAAgB,eAAe;AAE/C,QAAI,sBAAsB;AAC1B,QAAK,cAAe;AACnB,wBAAkB;AAAA,QACjB,MAAM,KAAK,WAAW,YAAY;AAAA,MACnC;AAIA,4BAAsB,oBAAoB;AAAA,IAC3C;AAOA,QAAI;AACJ;AACC,YAAM,gBACL,oBAAoB,KAAK,CAAE,KAAK,KAAK,KAAK,SAAU,SAAU;AAE/D,WAAO,iBAAiB,wBAAyB,WAAW,IAAK;AAChE,YAAI;AACH,0BAAgB,MAAM;AAAA,YACrB,KAAK;AAAA,YACL,KAAK;AAAA,YACL;AAAA,YACA,KAAK,iBAAiB;AAAA,UACvB;AAAA,QACD,QAAQ;AAKP,kBAAQ;AAAA,YACP;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAKA,UAAK,iBAAiB,iBAAiB,WAAW,IAAK;AACtD,iBAAS,gBAAiB;AAAA,UACzB,MAAM;AAAA,UACN,SAAS,OAAO;AAAA,UAChB,UAAU,KAAK;AAAA,UACf,gBAAgB;AAAA,YACf,MAAM,WAAW;AAAA,YACjB,YAAY;AAAA,YACZ,gBAAgB;AAAA,UACjB;AAAA,UACA,YAAY,CAAE,cAAc,MAAO;AAAA,QACpC,CAAE;AAAA,MACH;AAAA,IACD;AAGA,QACC,CAAE,KAAK,YACP,WAAW,uBACX,WAAW,oBAAoB,SAAS,GACvC;AACD,YAAM,gBAAgB,SAAS,iBAAiB,CAAC;AACjD,YAAM,kBACL,WAAW;AAEZ,YAAM,kBACL,uBAAuB,gBACpB,gBACA,KAAK;AACT,YAAM,OAAO,WAAW,WACrB,WAAY,iBAAiB,WAAW,QAAS,IACjD;AACH,YAAM,UAAU,OAAO;AAOvB,YAAM,aAAa,cAAc,IAAK,KAAK,EAAG;AAG9C,YAAM,iBAAiB,WAAW;AAClC,YAAM,aAAa,WAAW,0BAA0B;AAOxD,YAAM,eAAe,WAAW;AAChC,YAAM,kBACL,SAAS,gBAAgB;AAC1B,YAAM,iBACL,OAAO,cAAc,YAAY,WAC9B,aAAa,UAAU,MACvB;AACJ,YAAM,iBAAiB,CAAE,aAA8B;AACtD,cAAM,QAAQ,cAAc,QAAS,QAAS;AAC9C,YAAK,OAAO,UAAU,UAAW;AAChC,iBAAO,QAAQ;AAAA,QAChB;AACA,eAAO;AAAA,MACR;AAKA,UAAI,8BAKM;AAEV,UAAK,CAAE,cAAc,gBAAiB;AACrC,sCAA8B,MAAM;AAAA,UACnC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACD;AAAA,MACD;AAMA,YAAM,kBAAkB,oBAAI,IAAwB;AACpD,iBAAY,QAAQ,iBAAkB;AACrC,cAAM,YAAY,cAAe,IAAK;AACtC,YAAK,CAAE,WAAY;AAElB,kBAAQ;AAAA,YACP,eAAgB,IAAK;AAAA,UACtB;AACA;AAAA,QACD;AACA,cAAM,MAAM,GAAI,UAAU,KAAM,IAAK,UAAU,MAAO,IAAK,UAAU,IAAK;AAC1E,cAAM,QAAQ,gBAAgB,IAAK,GAAI;AACvC,YAAK,OAAQ;AACZ,gBAAM,KAAM,IAAK;AAAA,QAClB,OAAO;AACN,0BAAgB,IAAK,KAAK,CAAE,IAAK,CAAE;AAAA,QACpC;AAAA,MACD;AAEA,iBAAY,CAAE,EAAE,KAAM,KAAK,iBAAkB;AAC5C,cAAM,YAAY,cAAe,MAAO,CAAE,CAAE;AAK5C,cAAM,cAAc,eAAgB,MAAO,CAAE,CAAE;AAI/C,cAAM,sBAAmC;AAAA,UACxC;AAAA,YACC,cAAc;AAAA,YACd,EAAE,QAAQ,WAAW,SAAS,YAAY;AAAA,UAC3C;AAAA,QACD;AAOA,YAAK,CAAE,cAAc,6BAA8B;AAClD,8BAAoB,KAAM;AAAA,YACzB,4BAA6B,CAAE;AAAA,YAC/B;AAAA,cACC,GAAG,4BAA6B,CAAE;AAAA,cAClC,eAAe;AAAA,YAChB;AAAA,UACD,CAAE;AAAA,QACH;AAEA,4BAAoB,KAAM,cAAc,MAAO;AAI/C,cAAM,iBAAiB,MAAM,WAAW,IAAI,MAAO,CAAE,IAAI;AAEzD,iBAAS,gBAAiB;AAAA,UACzB;AAAA,UACA;AAAA,UACA,UAAU,KAAK;AAAA,UACf,gBAAgB;AAAA;AAAA;AAAA,YAGf,MAAM,WAAW;AAAA,YACjB,YAAY;AAAA,YACZ,gBAAgB;AAAA,UACjB;AAAA,UACA,YAAY;AAAA,QACb,CAAE;AAAA,MACH;AAGA;AACC,cAAM,EAAE,sBAAsB,IAAI;AAClC,YAAK,yBAAyB,WAAW,IAAK;AAI7C,gBAAM,SAAS,MAAM,kBAAmB,eAAgB;AACxD,gBAAM,eACL,OAAO,QAAQ,yBACf,OAAO,SAAS;AACjB,iBAAO,MAAM;AAEb,cAAK,cAAe;AAEnB,kBAAM,kBAAkB,WAAW,WAChC,WAAY,iBAAiB,WAAW,QAAS,IACjD;AAIH,kBAAM,mBAAgC;AAAA,cACrC;AAAA,gBACC,cAAc;AAAA,gBACd;AAAA,kBACC,QAAQ;AAAA,oBACP,OAAO;AAAA,oBACP,QAAQ;AAAA,kBACT;AAAA,kBACA,mBAAmB;AAAA,kBACnB,SAAS;AAAA,gBACV;AAAA,cACD;AAAA,YACD;AAEA,gBAAK,CAAE,cAAc,6BAA8B;AAElD,+BAAiB;AAAA,gBAChB;AAAA,cACD;AAAA,YACD;AAEA,6BAAiB,KAAM,cAAc,MAAO;AAE5C,qBAAS,gBAAiB;AAAA,cACzB,MAAM;AAAA,cACN;AAAA,cACA,UAAU,KAAK;AAAA,cACf,gBAAgB;AAAA,gBACf,MAAM,WAAW;AAAA,gBACjB,YAAY;AAAA,gBACZ,gBAAgB;AAAA,cACjB;AAAA,cACA,YAAY;AAAA,YACb,CAAE;AAAA,UACH;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAEA,aAAS,gBAAiB,IAAI,CAAC,CAAE;AAAA,EAClC;AACD;AAWO,SAAS,aAAc,IAAkB;AAC/C,SAAO,OAAQ,EAAE,QAAQ,SAAS,MAAkB;AACnD,UAAM,OAAO,OAAO,QAAS,EAAG;AAChC,QAAK,CAAE,MAAO;AACb;AAAA,IACD;AAEA,UAAM,aAAa,KAAK;AACxB,UAAM,EAAE,cAAc,IAAI,OAAO,YAAY;AAC7C,UAAM,UAAgC,CAAC;AAGvC,QAAK,YAAY,MAAM,eAAgB;AACtC,UAAI;AAOH,cAAM,oBAAoB,MAAM;AAAA,UAC/B,WAAW;AAAA,UACX,KAAK,YAAY,CAAC;AAAA,QACnB;AACA,YAAK,mBAAoB;AACxB,kBAAQ,aAAa;AAAA,QACtB;AAAA,MACD,SAAU,OAAQ;AAGjB,gBAAQ,KAAM,8BAA8B,KAAM;AAAA,MACnD;AAAA,IACD;AAEA,aAAS,gBAAiB,IAAI,OAAQ;AAAA,EACvC;AACD;AAOO,SAAS,eAAgB,IAAkB;AACjD,SAAO,OAAQ,EAAE,QAAQ,SAAS,MAAkB;AACnD,UAAM,WAAW,OAAO,YAAa,EAAG;AAExC,eAAY,WAAW,UAAW;AACjC,oBAAe,OAAQ;AAAA,IACxB;AAEA,aAAkC;AAAA,MACjC,MAAM,KAAK;AAAA,MACX;AAAA,IACD,CAAE;AAAA,EACH;AACD;AAQO,SAAS,mBAAoB,IAAiB,UAAmB;AACvE,SAAO,OAAQ,EAAE,SAAS,MAAkB;AAC3C,aAAkC;AAAA,MACjC,MAAM,KAAK;AAAA,MACX;AAAA,MACA;AAAA,IACD,CAAE;AAAA,EACH;AACD;AAUO,SAAS,eACf,UACuB;AACvB,SAAO;AAAA,IACN,MAAM,KAAK;AAAA,IACX;AAAA,EACD;AACD;",
  "names": []
}
