Version History
files-sdk/version-historyFreeComponent
A version timeline for one key with one-click restore (versioning plugin).
Install it
npx shadcn@latest add https://files-sdk.dev/r/version-history.jsonSource
1"use client";23import type { FileVersion, UseFilesResult } from "files-sdk/react";4import { HistoryIcon, Loader2Icon, RotateCcwIcon } from "lucide-react";5import { useCallback, useEffect, useRef, useState } from "react";67import { Button } from "@/components/ui/button";8import { cn } from "@/lib/utils";910export interface VersionHistoryProps {11 /** A `useFiles()` instance backed by a gateway with the `versioning()` plugin. */12 files: UseFilesResult;13 /** The key whose history to show. */14 fileKey: string;15 /** Called after a successful restore. */16 onRestored?: (file: { key: string }) => void;17 className?: string;18}1920const formatBytes = (bytes: number): string => {21 if (bytes === 0) {22 return "0 B";23 }24 const units = ["B", "KB", "MB", "GB", "TB"];25 const exponent = Math.min(26 Math.floor(Math.log(bytes) / Math.log(1024)),27 units.length - 128 );29 return `${(bytes / 1024 ** exponent).toFixed(exponent === 0 ? 0 : 1)} ${units[exponent]}`;30};3132/**33 * A version timeline for one key, backed by the `versioning()` plugin. Lists the34 * saved snapshots (newest first) and restores any of them through the same35 * `useFiles()` instance. Restoring snapshots the current bytes first, so it's36 * itself reversible.37 */38export const VersionHistory = ({39 files,40 fileKey,41 onRestored,42 className,43}: VersionHistoryProps) => {44 const [versions, setVersions] = useState<FileVersion[]>([]);45 const [isLoading, setIsLoading] = useState(true);46 const [restoring, setRestoring] = useState<string>();4748 const filesRef = useRef(files);49 filesRef.current = files;5051 const refresh = useCallback(async () => {52 setIsLoading(true);53 try {54 setVersions(await filesRef.current.versions(fileKey));55 } catch {56 // The hook mirrors the error to `files.error` for display.57 } finally {58 setIsLoading(false);59 }60 }, [fileKey]);6162 useEffect(() => {63 void refresh();64 }, [refresh]);6566 const restore = useCallback(67 async (versionId: string) => {68 setRestoring(versionId);69 try {70 const file = await filesRef.current.restoreVersion(fileKey, versionId);71 await refresh();72 onRestored?.(file);73 } catch {74 // Mirrored to `files.error`.75 } finally {76 setRestoring(undefined);77 }78 },79 [fileKey, refresh, onRestored]80 );8182 if (isLoading && !versions.length) {83 return (84 <div85 className={cn(86// … 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 Browserfile-browser | 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 |
