dialog Stable WINMACLNX
Open native OS file dialogs — open, save, and folder picker. Dialogs are modal and block input to the app window while open.
Capability
{
"capabilities": ["dialog"]
}Import
import { dialog } from 'veloxkit'API
dialog.openFile(opts?)
Show the native "Open File" dialog.
const paths = await dialog.openFile({
multiple: false, // true allows multi-select
filters: [
{ name: 'Images', extensions: ['png', 'jpg', 'jpeg', 'webp'] },
{ name: 'All Files', extensions: ['*'] },
],
})
if (paths === null) {
// user cancelled
} else {
const filePath = paths[0] // always an array, even when multiple: false
}Options
| Option | Type | Default | Description |
|---|---|---|---|
multiple | boolean | false | Allow selecting multiple files |
filters | Filter[] | [] | File type filters shown in the dialog |
Filter shape
type Filter = {
name: string // display name, e.g. "Images"
extensions: string[] // without dots: ['png', 'jpg'] — or ['*'] for all
}Returns Promise<string[] | null> — array of absolute paths, or null if cancelled.
dialog.saveFile(opts?)
Show the native "Save File" dialog.
const savePath = await dialog.saveFile({
defaultName: 'export.csv',
filters: [
{ name: 'CSV', extensions: ['csv'] },
{ name: 'JSON', extensions: ['json'] },
],
})
if (savePath !== null) {
await fs.writeFile(savePath, csvContent)
}Options
| Option | Type | Default | Description |
|---|---|---|---|
defaultName | string | '' | Pre-filled filename |
filters | Filter[] | [] | File type filters |
Returns Promise<string | null> — absolute path chosen by the user, or null if cancelled.
dialog.openFolder()
Show the native "Select Folder" dialog.
const folderPath = await dialog.openFolder()
if (folderPath !== null) {
const entries = await fs.listDir(folderPath)
console.log(`${entries.length} items in folder`)
}Returns Promise<string | null> — absolute folder path, or null if cancelled.
Examples
Image importer
import { dialog, fs } from 'veloxkit'
import { useState } from 'react'
const IMAGE_FILTERS = [
{ name: 'Images', extensions: ['png', 'jpg', 'jpeg', 'webp', 'gif'] },
]
function ImageImporter() {
const [imagePath, setImagePath] = useState<string | null>(null)
const handlePick = async () => {
const paths = await dialog.openFile({ filters: IMAGE_FILTERS })
if (paths) setImagePath(paths[0])
}
return (
<View style={{ gap: 12 }}>
<Pressable onPress={handlePick}
style={{ padding: 12, backgroundColor: '#3a3a5e', borderRadius: 8 }}>
<Text>Choose Image…</Text>
</Pressable>
{imagePath && (
<Image src={imagePath} width={300} height={200} resizeMode="contain" />
)}
</View>
)
}Export with save dialog
import { dialog, fs } from 'veloxkit'
async function exportToCSV(rows: Record<string, unknown>[]) {
const path = await dialog.saveFile({
defaultName: `export-${Date.now()}.csv`,
filters: [{ name: 'CSV', extensions: ['csv'] }],
})
if (!path) return
const header = Object.keys(rows[0]).join(',')
const body = rows.map(r => Object.values(r).join(',')).join('\n')
await fs.writeFile(path, `${header}\n${body}`)
}Batch import (multiple files)
const paths = await dialog.openFile({
multiple: true,
filters: [{ name: 'Documents', extensions: ['pdf', 'txt', 'md'] }],
})
if (paths) {
for (const p of paths) {
const content = await fs.readFile(p)
await db.run('INSERT INTO docs (path, content) VALUES (?, ?)', [p, content])
}
}FileInput component
For in-form file picking, use the built-in FileInput component instead of calling dialog.openFile() manually:
import { FileInput } from 'veloxkit'
<FileInput
label="Attach file"
onFilesSelected={(paths) => console.log(paths)}
filters={[{ name: 'All Files', extensions: ['*'] }]}
/>Dialogs are always attached to the main window and are fully modal. The Promise resolves only when the user confirms or cancels — there is no timeout.