File Browser
files-sdk/file-browserFreeComponent
Folder-aware browser that descends into common prefixes with a breadcrumb trail.
Install it
npx shadcn@latest add https://files-sdk.dev/r/file-browser.jsonSource
1"use client";23import type { StoredFile } from "files-sdk";4import type { UseFilesResult } from "files-sdk/react";5import {6 ChevronRightIcon,7 FileIcon,8 FolderIcon,9 HomeIcon,10 Loader2Icon,11} from "lucide-react";12import { Fragment, useCallback, useEffect, useRef, useState } from "react";1314import { FileActions } from "@/components/files-sdk/file-actions";15import { Button } from "@/components/ui/button";16import { cn } from "@/lib/utils";1718export interface FileBrowserProps {19 /** A `useFiles()` instance — folders and files are listed through it. */20 files: UseFilesResult;21 /** Folder to open on mount, e.g. `"photos/"`. Defaults to the root. */22 initialPrefix?: string;23 /** Delimiter that marks a folder boundary. Default `"/"`. */24 delimiter?: string;25 /** Called when a file row (not a folder) is clicked. */26 onSelect?: (file: StoredFile) => void;27 /** Called after a successful copy/rename/move/delete from a row's actions menu. */28 onChanged?: () => void;29 /** Hide the per-file actions menu. */30 readOnly?: boolean;31 className?: string;32}3334const formatBytes = (bytes: number): string => {35 if (bytes === 0) {36 return "0 B";37 }38 const units = ["B", "KB", "MB", "GB", "TB"];39 const exponent = Math.min(40 Math.floor(Math.log(bytes) / Math.log(1024)),41 units.length - 142 );43 return `${(bytes / 1024 ** exponent).toFixed(exponent === 0 ? 0 : 1)} ${units[exponent]}`;44};4546/** Split `"photos/2024/"` into clickable crumbs with their cumulative prefix. */47const crumbsOf = (48 prefix: string,49 delimiter: string50): { label: string; prefix: string }[] => {51 const parts = prefix.split(delimiter).filter(Boolean);52 let acc = "";53 return parts.map((label) => {54 acc += label + delimiter;55 return { label, prefix: acc };56 });57};5859/** Strip the parent prefix + trailing delimiter so a folder shows its own name. */60const folderName = (61 folderPrefix: string,62 parent: string,63 delimiter: string64): string => folderPrefix.slice(parent.length).replace(delimiter, "");6566/**67 * A folder-aware browser for a `useFiles()` instance. Uses `list({ delimiter })`68 * so common prefixes surface as folders you can descend into, with a breadcrumb69 * trail and cursor-based "load more". Each file row carries a `FileActions` menu70 * (download, copy, rename, move, delete) unless `readOnly`. Falls back71 * gracefully on adapters that can't delimit — everything just appears as files72 * at the root.73 */74export const FileBrowser = ({75 files,76 initialPrefix = "",77// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from files-sdk
All 12 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Capabilities Badgescapabilities-badges | files-sdk | Components | Free | 2 deps | |
| Dropzonedropzone | files-sdk | Components | Free | 2 deps | |
| File Actionsfile-actions | files-sdk | Components | Free | 2 deps | |
| File Listfile-list | files-sdk | Components | Free | 2 deps | |
| File Previewfile-preview | files-sdk | Components | Free | 2 deps | |
| File Searchfile-search | files-sdk | Components | Free | 2 deps | |
| Multipart Uploadermultipart-uploader | files-sdk | Components | Free | 2 deps | |
| Share Dialogshare-dialog | files-sdk | Components | Free | 2 deps |
