DropFiles
Collect local files through a picker, drag and drop, or paste, with removable selections and file-type filtering.
DropFilesCollect project attachments
Add local text, image or PDF files, remove individual entries and inspect the total size. Nothing is uploaded. In single-file mode, the next accepted file replaces the selection.
<RegorApp id="drop-files-demo" src="./playground.ts"/> import {
type DropFileItem,
defineButtonComponents,
defineDropFilesComponents,
defineFlexComponents,
defineFormComponents,
defineIconComponents,
} from '@purestack/ts-components'
import {
lucide_cloud_upload,
lucide_file,
lucide_file_archive,
lucide_file_image,
lucide_file_text,
lucide_trash_2,
} from '@purestack/ts-svg-icons'
import {
type ComputedRef,
computed,
createApp,
defineComponent,
html,
type Ref,
ref,
type SRef,
sref,
} from 'regor'
export interface DropFilesExample {
selectedFiles: SRef<DropFileItem[]>
allowMany: Ref<boolean>
locked: Ref<boolean>
totalBytes: ComputedRef<number>
clear: () => void
}
const dropFilesExampleTemplate = html`<Flex direction="column">
<DropFiles
label="Project attachments"
hint="Text, images and PDF files. Files stay in this browser."
accept="text/*,image/*,.pdf"
:files="selectedFiles"
:multiple="allowMany"
:disabled="locked"
/>
<Flex wrap="true">
<FormCheck
id="files-multiple"
label="Allow multiple files"
:checked="allowMany"
/>
<FormCheck id="files-disabled" label="Lock file selection" :checked="locked" />
<Btn variant="link" :disabled="locked" @click="clear">Clear files</Btn>
</Flex>
<FormStatus>
{{ selectedFiles.length }} files · {{ totalBytes }} bytes selected
</FormStatus>
</Flex>`
function createDropFilesExample(): DropFilesExample {
const selectedFiles = sref<DropFileItem[]>([])
return {
selectedFiles,
allowMany: ref(true),
locked: ref(false),
totalBytes: computed(() =>
selectedFiles().reduce((sum, item) => sum + item.size, 0),
),
clear: () => selectedFiles([]),
}
}
const component = defineComponent<DropFilesExample>(dropFilesExampleTemplate, {
context: createDropFilesExample,
})
const icons: Record<string, string> = {
'lucide:cloud-upload': lucide_cloud_upload,
'lucide:file': lucide_file,
'lucide:trash-2': lucide_trash_2,
'lucide:file-image': lucide_file_image,
'lucide:file-text': lucide_file_text,
'lucide:file-archive': lucide_file_archive,
}
createApp(
{
components: {
DropFilesExample: component,
...defineDropFilesComponents(),
...defineFlexComponents(),
...defineFormComponents(),
...defineButtonComponents(),
...defineIconComponents((name) => icons[name] ?? ''),
},
},
{ selector: 'app#drop-files-demo', template: html`<DropFilesExample />` },
) A clearly disabled drop zone
Use a hint to explain why selection is unavailable.
<DropFiles
label="Attachments"
emptyTitle="Attachments are locked"
emptyText="Finish the current review to add files."
hint="Read-only example"
:disabled="true"
/> Behavior and accessibility
The drop zone opens the native picker with Enter or Space. File acceptance is a client-side convenience, not server validation. Duplicates are identified from file metadata. onChange runs when the component changes the selection; assigning the files ref yourself is application state management.
API reference
DropFiles contract
Props below are the public template API. RefOrValue accepts a literal or a reactive ref; bind refs with a colon-prefixed attribute. Native attributes and events can be passed through the component root.
files
SRef<DropFileItem[]> - Default
sref([])
Writable shallow ref of DropFileItem[]. Each item retains its File plus id, name, type, size, sizeLabel, lastModified and icon.
accept
RefOrValue<string> | string[] - Default
all files, or iconMap keys
Comma-separated MIME types, wildcards or extensions; arrays are also accepted. An explicit accept list takes precedence over iconMap keys.
iconMap
DropFilesIconMap | SRef<DropFilesIconMap> - Default
built-in type icons
MIME/extension-to-icon map merged with the defaults. When accept is omitted, a supplied map also determines accepted types.
label
RefOrValue<string> - Default
not set
Visible label. Use language that describes the control or value in its surrounding context.
hint
RefOrValue<string> - Default
not set
Supporting text beneath the drop-zone instructions.
emptyTitle
RefOrValue<string> - Default
Add files
Drop-zone heading, shown even when files are selected.
emptyText
RefOrValue<string> - Default
Click, tap, paste, or drag files here.
Drop-zone instructions.
disabled
RefOrValue<boolean> - Default
false
Disables interaction. Use a bound boolean, for example :disabled="isLocked".
multiple
RefOrValue<boolean> - Default
true
false accepts the first matching file and replaces the current list.
tone
RefOrValue<SemanticTone> - Default
inherited
Semantic intent: neutral, accent, secondary, info, success, warning, danger, feature, custom or ghost. The active skin supplies the colors.
variant
RefOrValue<ComponentVariant> - Default
surfaceAlt
Visual treatment. Accepts solid, surface, surfaceAlt, spotlight, glass, flat, flatAlt, flatSolid, outlineFill, outline, subtle, subtleBtn, link, sheen, underline, rail, bracket or none.
uploadIcon
RefOrValue<string> - Default
lucide:cloud-upload
Drop-zone icon.
fileIcon
RefOrValue<string> - Default
lucide:file
Fallback file icon when no type-specific mapping matches.
removeIcon
RefOrValue<string> - Default
lucide:trash-2
Icon on each remove button.
onChange
(files: DropFileItem[]) => void - Default
not set
Callback receiving the updated DropFileItem[] after a component-driven change.
Composition
No slots. Register defineDropFilesComponents and its icons. Use addDropFiles when another input path needs the same filtering, metadata and deduplication behavior.