Documentation Index Fetch the complete documentation index at: https://mintlify.com/uploadcare/file-uploader/llms.txt
Use this file to discover all available pages before exploring further.
The File Uploader is built on a component-based architecture using Web Components. This guide explains how components are structured, how they communicate, and how you can build custom solutions.
Component Hierarchy
The File Uploader uses a hierarchical component system with three main layers:
Solution Blocks (FileUploaderRegular, FileUploaderInline, etc.)
↓
Uploader Blocks (UploadList, SourceList, etc.)
↓
Base Blocks (Icon, Button, Modal, etc.)
Base: LitBlock
All components extend from LitBlock, which provides core functionality:
From src/lit/LitBlock.ts:35-52:
export class LitBlock extends LitBlockBase {
private _cfgProxy !: ConfigType ;
protected _sharedContextInstances : Map < keyof SharedInstancesState , ISharedInstance > = new Map ();
public static styleAttrs : string [] = [];
public activityType : ActivityType = null ;
public init$ = blockCtx ();
public l10n = createL10n (() => this . sharedCtx );
public debugPrint = createDebugPrinter (() => this . sharedCtx , this . constructor . name );
protected _sharedInstancesBag = createSharedInstancesBag (() => this . sharedCtx );
}
Key features:
State management via reactive context
Localization support (l10n)
Shared instance management
Debug utilities
Accessibility features
Uploader Block
LitUploaderBlock extends LitActivityBlock and adds upload-specific functionality:
From src/lit/LitUploaderBlock.ts:24-35:
export class LitUploaderBlock extends LitActivityBlock {
public static extSrcList : Readonly < typeof ExternalUploadSource >;
public static sourceTypes : Readonly < typeof UploadSource >;
protected couldBeCtxOwner = false ;
private _isCtxOwner = false ;
private _unobserveCollection ?: () => void ;
private _unobserveCollectionProperties ?: () => void ;
public override init$ = uploaderBlockCtx ( this );
}
Key features:
Upload collection management
File validation
Upload queue control
Event emission
API access
Solution Block
LitSolutionBlock is the top-level container for complete solutions:
From src/lit/LitSolutionBlock.ts:7-21:
export class LitSolutionBlock extends LitBlock {
public static override styleAttrs = [ 'uc-wgt-common' ];
public override init$ = solutionBlockCtx ( this );
public override initCallback () : void {
super . initCallback ();
this . a11y ?. registerBlock ( this );
this . clipboardLayer ?. registerBlock ( this );
this . sharedCtx . pub ( '*solution' , this . tagName );
}
}
Key features:
Complete uploader experience
Pre-configured component composition
Theme support
Clipboard integration
Core Components
Config Component
Manages all configuration options and propagates changes:
< uc-config
pubkey = "your_public_key"
multiple = "true"
source-list = "local, camera"
></ uc-config >
See Configuration System for details.
UploadCtxProvider
Provides shared context for upload operations:
< uc-upload-ctx-provider ctx-name = "my-uploader" >
<!-- All child components share this context -->
</ uc-upload-ctx-provider >
Modal Component
Containers for activities that appear in modal dialogs:
< uc-modal id = "start-from" strokes block-body-scrolling >
< uc-start-from >
<!-- Modal content -->
</ uc-start-from >
</ uc-modal >
Upload Sources
Components for different file upload sources:
DropArea Drag-and-drop zone for local files < uc-drop-area
with-icon
clickable
></ uc-drop-area >
CameraSource Camera/webcam capture interface < uc-camera-source ></ uc-camera-source >
UrlSource Upload files from URLs < uc-url-source ></ uc-url-source >
ExternalSource External services (Dropbox, Google Drive, etc.) < uc-external-source ></ uc-external-source >
UploadList Component
Displays and manages uploaded files:
< uc-upload-list ></ uc-upload-list >
SourceList Component
Displays available upload sources as buttons:
< uc-source-list role = "list" wrap ></ uc-source-list >
Component Registration
Components are automatically registered as custom elements using a naming convention:
From src/abstract/defineComponents.ts:3-26:
export function defineComponents ( blockExports : Record < string , any >) {
for ( const blockName in blockExports ) {
if ( EXCLUDE_COMPONENTS . includes ( blockName )) {
continue ;
}
let tagName = [ ... blockName ]. reduce (( name , char ) => {
if ( char . toUpperCase () === char ) {
char = `- ${ char . toLowerCase () } ` ;
}
name += char ;
return name ;
}, '' );
if ( tagName . startsWith ( '-' )) {
tagName = tagName . replace ( '-' , '' );
}
if ( ! tagName . startsWith ( 'uc-' )) {
tagName = `uc- ${ tagName } ` ;
}
if ( blockExports [ blockName ]. reg ) {
blockExports [ blockName ]. reg ( tagName );
}
}
}
Examples:
FileUploaderRegular → uc-file-uploader-regular
UploadList → uc-upload-list
CameraSource → uc-camera-source
State Management
Components use a reactive state system based on TypedData:
From src/abstract/TypedData.ts:7-30:
export class TypedData < T extends Record < string , unknown >> {
private _ctxId : Uid ;
private _data : PubSub < T >;
public setValue < K extends keyof T >( prop : K , value : T [ K ]) : void {
if ( ! this . _data . has ( prop )) {
console . warn ( ` ${ MSG_NAME }${ String ( prop ) } ` );
return ;
}
const isChanged = this . _data . read ( prop ) !== value ;
if ( isChanged ) {
this . _data . pub ( prop , value );
}
}
public getValue < K extends keyof T >( prop : K ) : T [ K ] {
if ( ! this . _data . has ( prop )) {
console . warn ( ` ${ MSG_NAME }${ String ( prop ) } ` );
}
return this . _data . read ( prop );
}
}
Subscribing to State Changes
Components can subscribe to state changes:
// Subscribe to configuration changes
this . sub ( '*currentActivity' , ( activity ) => {
console . log ( 'Activity changed:' , activity );
});
// Subscribe to upload collection changes
this . sub ( '*uploadList' , ( files ) => {
console . log ( 'Files changed:' , files );
});
Publishing State Changes
Components can publish state changes:
// Change the current activity
this . $ [ '*currentActivity' ] = 'upload-list' ;
// Update upload progress
this . $ [ '*commonProgress' ] = 50 ;
Shared Instances
Certain functionality is shared across all components in a context:
Event Emitter
Upload Collection
Modal Manager
Validation Manager
Handles all uploader events: this . emit ( EventType . FILE_ADDED , fileEntry );
this . emit ( EventType . UPLOAD_PROGRESS , progressData );
Manages the collection of files being uploaded: this . uploadCollection . add ( fileData );
this . uploadCollection . remove ( fileId );
this . uploadCollection . items ();
Controls modal dialogs: this . modalManager . open ( 'start-from' );
this . modalManager . close ( 'upload-list' );
Runs file and collection validators: this . validationManager . runFileValidators ( 'add' , [ fileId ]);
this . validationManager . runCollectionValidators ();
Building Custom Components
You can create custom components by extending the base classes:
Custom Block
import { Block } from '@uploadcare/file-uploader' ;
import { html } from 'lit' ;
export class MyCustomBlock extends Block {
static styleAttrs = [ 'my-custom-block' ];
initCallback () {
super . initCallback ();
// Subscribe to configuration
this . subConfigValue ( 'pubkey' , ( pubkey ) => {
console . log ( 'Public key:' , pubkey );
});
// Subscribe to upload list
this . sub ( '*uploadList' , ( files ) => {
console . log ( 'Files:' , files );
});
}
render () {
return html `
<div class="my-custom-block">
<slot></slot>
</div>
` ;
}
}
MyCustomBlock . reg ( 'my-custom-block' );
Custom Solution
import { SolutionBlock } from '@uploadcare/file-uploader' ;
import { html } from 'lit' ;
export class MyCustomSolution extends SolutionBlock {
static styleAttrs = [
... SolutionBlock . styleAttrs ,
'my-custom-solution'
];
render () {
return html `
${ super . render () }
<uc-config
ctx-name="my-solution"
pubkey=" ${ this . pubkey } "
></uc-config>
<uc-drop-area clickable></uc-drop-area>
<uc-upload-list></uc-upload-list>
<uc-modal id="camera">
<uc-camera-source></uc-camera-source>
</uc-modal>
` ;
}
}
MyCustomSolution . reg ( 'my-custom-solution' );
Component Communication
Components communicate through several mechanisms:
1. Shared State
All components in a context share reactive state:
// Component A sets state
this . $ [ '*currentActivity' ] = 'camera' ;
// Component B subscribes to state
this . sub ( '*currentActivity' , ( activity ) => {
// Reacts to change
});
2. Events
Components emit events through the event emitter:
// Emit event
this . emit ( EventType . FILE_ADDED , fileData );
// Listen to event
api . on ( EventType . FILE_ADDED , ( file ) => {
console . log ( 'File added:' , file );
});
3. Public API
The public API provides methods for programmatic control:
const api = uploader . getAPI ();
api . addFileFromUrl ( 'https://example.com/image.jpg' );
api . uploadAll ();
api . setCurrentActivity ( 'upload-list' );
Component Lifecycle
Lifecycle Hooks
class MyComponent extends Block {
constructor () {
super ();
// Initialize instance properties
}
connectedCallback () {
super . connectedCallback ();
// Component added to DOM
}
initCallback () {
super . initCallback ();
// Component initialized
// Set up subscriptions
}
disconnectedCallback () {
super . disconnectedCallback ();
// Component removed from DOM
// Clean up resources
}
}
Best Practices
Always use the shared context for state management rather than component-local state when data needs to be accessed by multiple components.
Unsubscribe from state changes in disconnectedCallback to prevent memory leaks.
Build complex UIs by composing simple components rather than creating monolithic components.
Follow naming conventions
Use the uc- prefix for custom components to maintain consistency.
Next Steps
Configuration System Learn about configuration options
Solutions Overview Explore pre-built solutions