diff --git a/docs/content/docs/components/file-field.mdx b/docs/content/docs/components/file-field.mdx
index e1f527ad..8cbd38de 100644
--- a/docs/content/docs/components/file-field.mdx
+++ b/docs/content/docs/components/file-field.mdx
@@ -57,7 +57,7 @@ First you will need to follow the [manual install setup](./manual-install) guide
- [uploader-provider](./uploader-provider)
- [dropzone](./dropzone)
-- [multi-file](./multi-file)
+- [file-list](./file-list)
diff --git a/docs/content/docs/components/file-list.mdx b/docs/content/docs/components/file-list.mdx
new file mode 100644
index 00000000..4ad48a0b
--- /dev/null
+++ b/docs/content/docs/components/file-list.mdx
@@ -0,0 +1,103 @@
+---
+title: File List
+description: Lists the files of an UploaderProvider with their status, progress and actions.
+---
+
+import { LimitedCode } from '@/components/ui/limited-code';
+import {
+ OpenTabs,
+ OpenTabsContent,
+ OpenTabsList,
+ OpenTabsTrigger,
+} from '@/components/ui/open-tabs';
+import { Callout } from 'fumadocs-ui/components/callout';
+import { Step, Steps } from 'fumadocs-ui/components/steps';
+
+`file-list.tsx` exports:
+
+- `FileList`: lists the files of the nearest `UploaderProvider`.
+- `FileListItem`: renders one file with its status, progress and actions (retry, cancel, remove).
+- `FileBadge`: renders the colored file-type tile.
+
+Use it next to an [Upload Button](./upload-button), or anywhere you want the files of an `UploaderProvider` shown as a list.
+
+
+ The [multi-file](./multi-file) and [file field](./file-field) components
+ install it automatically via the CLI.
+
+
+## Installation
+
+
+
+
+ CLI
+ Manual
+
+
+
+
+Use the shadcn CLI to add the component to your project.
+
+```package-install
+npx shadcn@latest add https://edgestore.dev/r/file-list.json
+```
+
+
+
+
+
+
+
+
+
+### Setup for manual installation
+
+First you will need to follow the [manual install setup](./manual-install) guide.
+
+
+
+
+
+### Install required components
+
+- [uploader-provider](./uploader-provider)
+- [progress-bar](./progress-bar)
+
+
+
+
+
+### Copy this component
+
+
+
+../../../src/components/upload/file-list.tsx
+
+../../../src/components/upload/upload-utils.ts
+
+
+
+
+
+
+
+
+
+
+
+## Usage
+
+```tsx
+
+ {/* anything that adds files, e.g. */}
+
+
+```
+
+## Props
+
+| Prop | Type | Default | Description |
+| ---------- | --------- | ------- | ------------------------------------------- |
+| `disabled` | `boolean` | `false` | Hides the retry, cancel and remove actions. |
+| `...` | | | Any other `
` prop, such as `className`. |
diff --git a/docs/content/docs/components/multi-file.mdx b/docs/content/docs/components/multi-file.mdx
index a2c46bd6..f2706d40 100644
--- a/docs/content/docs/components/multi-file.mdx
+++ b/docs/content/docs/components/multi-file.mdx
@@ -57,7 +57,7 @@ First you will need to follow the [manual install setup](./manual-install) guide
- [uploader-provider](./uploader-provider)
- [dropzone](./dropzone)
-- [progress-bar](./progress-bar)
+- [file-list](./file-list)
- [shadcn/ui button](https://ui.shadcn.com/docs/components/button)
@@ -143,8 +143,4 @@ export function MultiFileDropzoneUsage() {
### Building your own layout
-`multi-file.tsx` also exports the pieces it is made of, so you can arrange them differently:
-
-- `FileList` lists the files of the nearest `UploaderProvider`.
-- `FileListItem` renders one file with its status and actions.
-- `FileBadge` renders the colored file-type tile.
+`FileUploader` is a `Dropzone` and a [`FileList`](./file-list), so you can arrange the two differently.
diff --git a/docs/content/docs/components/upload-button.mdx b/docs/content/docs/components/upload-button.mdx
index 3ec36b89..a5bf8a02 100644
--- a/docs/content/docs/components/upload-button.mdx
+++ b/docs/content/docs/components/upload-button.mdx
@@ -18,7 +18,7 @@ import { Step, Steps } from 'fumadocs-ui/components/steps';
-It takes the same props as the shadcn/ui `Button`. Several buttons can feed the same `UploaderProvider`, so you can pair them with a `FileList` or build your own list with `useUploader`.
+It takes the same props as the shadcn/ui `Button`. Several buttons can feed the same `UploaderProvider`, so you can pair them with a [`FileList`](./file-list) or build your own list with `useUploader`.
## Installation
@@ -81,13 +81,17 @@ First you will need to follow the [manual install setup](./manual-install) guide
## Usage
-Install or copy the component from [Installation](#installation) before using this example.
+Install or copy the component from [Installation](#installation) before using this example. It also uses [`FileList`](./file-list):
+
+```package-install
+npx shadcn@latest add https://edgestore.dev/r/file-list.json
+```
```tsx
'use client';
import { UploadErrors } from '@/components/upload/dropzone';
-import { FileList } from '@/components/upload/multi-file';
+import { FileList } from '@/components/upload/file-list';
import { UploadButton } from '@/components/upload/upload-button';
import {
UploaderProvider,
diff --git a/docs/content/docs/components/uploader-provider.mdx b/docs/content/docs/components/uploader-provider.mdx
index 66b51c72..44fa59d0 100644
--- a/docs/content/docs/components/uploader-provider.mdx
+++ b/docs/content/docs/components/uploader-provider.mdx
@@ -69,7 +69,7 @@ function MyUploaderPage() {
// Define the upload function
const uploadFn: UploadFn = React.useCallback(
async ({ file, onProgressChange, signal }) => {
- // Example using Edge Store client
+ // Example using EdgeStore client
const res = await edgestore.publicFiles.upload({
file,
signal,
diff --git a/docs/content/docs/meta.json b/docs/content/docs/meta.json
index 6c84954e..e9cd52c0 100644
--- a/docs/content/docs/meta.json
+++ b/docs/content/docs/meta.json
@@ -18,6 +18,7 @@
"components/avatar",
"components/file-field",
"components/upload-button",
+ "components/file-list",
"components/uploader-provider",
"components/dropzone",
"components/progress-circle",
diff --git a/docs/public/r/avatar-dropzone-block.json b/docs/public/r/avatar-dropzone-block.json
index d67a5e3c..7994f694 100644
--- a/docs/public/r/avatar-dropzone-block.json
+++ b/docs/public/r/avatar-dropzone-block.json
@@ -11,8 +11,8 @@
{
"path": "examples/components/src/components/upload/blocks/avatar-block.tsx",
"content": "'use client';\n\nimport { AvatarDropzone } from '@/components/upload/avatar-dropzone';\nimport {\n UploaderProvider,\n type UploadFn,\n} from '@/components/upload/uploader-provider';\nimport * as React from 'react';\n\nexport default function AvatarDropzoneBlock() {\n const { edgestore } = useMockEdgeStore(); // Mock edgestore for easy v0 integration\n\n const uploadFn: UploadFn = React.useCallback(\n async ({ file, signal, onProgressChange }) => {\n const res = await edgestore.myPublicImages.upload({\n file,\n signal,\n onProgressChange,\n });\n // you can run some server action or api here\n // to add the necessary data to your database\n return { url: res.url };\n },\n [edgestore],\n );\n\n return (\n \n );\n}\n\n// Mock implementation of EdgeStore\nfunction useMockEdgeStore() {\n return {\n edgestore: {\n myPublicImages: {\n upload: async ({\n signal,\n onProgressChange,\n }: {\n file: File;\n signal?: AbortSignal;\n onProgressChange?: (progress: number) => void | Promise;\n }) => {\n // Simulate upload progress. Rejects like EdgeStore when the upload is aborted.\n await new Promise((resolve, reject) => {\n let progress = 0;\n const interval = setInterval(() => {\n progress = Math.min(\n progress + Math.floor(Math.random() * 21) + 10,\n 100,\n );\n void onProgressChange?.(progress);\n if (progress >= 100) {\n clearInterval(interval);\n resolve();\n }\n }, 300);\n signal?.addEventListener('abort', () => {\n clearInterval(interval);\n reject(new DOMException('Upload aborted', 'AbortError'));\n });\n });\n\n return {\n url: 'https://edgestore.dev/img/upload-demo.webp',\n };\n },\n },\n },\n };\n}\n",
- "type": "registry:block",
- "target": "components/upload/blocks/avatar-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
],
"type": "registry:block"
diff --git a/docs/public/r/file-field-block.json b/docs/public/r/file-field-block.json
index 655e44b4..e93770a7 100644
--- a/docs/public/r/file-field-block.json
+++ b/docs/public/r/file-field-block.json
@@ -12,8 +12,8 @@
{
"path": "examples/components/src/components/upload/blocks/file-field-block.tsx",
"content": "'use client';\n\nimport { FileField } from '@/components/upload/file-field';\nimport { DOCUMENT_ACCEPT } from '@/components/upload/upload-utils';\nimport {\n UploaderProvider,\n type UploadFn,\n} from '@/components/upload/uploader-provider';\nimport * as React from 'react';\n\nexport default function FileFieldBlock() {\n const { edgestore } = useMockEdgeStore(); // Mock edgestore for easy v0 integration\n\n const uploadFn: UploadFn = React.useCallback(\n async ({ file, signal, onProgressChange }) => {\n const res = await edgestore.myPublicFiles.upload({\n file,\n signal,\n onProgressChange,\n });\n // you can run some server action or api here\n // to add the necessary data to your database\n return { url: res.url };\n },\n [edgestore],\n );\n\n return (\n \n
\n \n Resume\n \n \n \n \n
\n
\n );\n}\n\n// Mock implementation of EdgeStore\nfunction useMockEdgeStore() {\n return {\n edgestore: {\n myPublicFiles: {\n upload: async ({\n signal,\n onProgressChange,\n }: {\n file: File;\n signal?: AbortSignal;\n onProgressChange?: (progress: number) => void | Promise;\n }) => {\n // Simulate upload progress. Rejects like EdgeStore when the upload is aborted.\n await new Promise((resolve, reject) => {\n let progress = 0;\n const interval = setInterval(() => {\n progress = Math.min(\n progress + Math.floor(Math.random() * 21) + 10,\n 100,\n );\n void onProgressChange?.(progress);\n if (progress >= 100) {\n clearInterval(interval);\n resolve();\n }\n }, 300);\n signal?.addEventListener('abort', () => {\n clearInterval(interval);\n reject(new DOMException('Upload aborted', 'AbortError'));\n });\n });\n\n return {\n url: 'https://edgestore.dev/img/upload-demo.webp',\n };\n },\n },\n },\n };\n}\n",
- "type": "registry:block",
- "target": "components/upload/blocks/file-field-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
],
"type": "registry:block"
diff --git a/docs/public/r/file-field.json b/docs/public/r/file-field.json
index f8b49b5f..845eaf86 100644
--- a/docs/public/r/file-field.json
+++ b/docs/public/r/file-field.json
@@ -3,20 +3,23 @@
"name": "file-field",
"title": "File Field",
"description": "A compact single-file input that sits in a form next to regular fields.",
- "dependencies": ["react-dropzone", "lucide-react"],
+ "dependencies": [
+ "react-dropzone",
+ "lucide-react"
+ ],
"registryDependencies": [
"https://edgestore.dev/r/dropzone.json",
- "https://edgestore.dev/r/file-uploader.json",
+ "https://edgestore.dev/r/file-list.json",
"https://edgestore.dev/r/uploader-provider.json",
"https://edgestore.dev/r/upload-utils.json"
],
"files": [
{
"path": "examples/components/src/components/upload/file-field.tsx",
- "content": "'use client';\n\nimport { cn } from '@/lib/utils';\nimport { UploadIcon } from 'lucide-react';\nimport * as React from 'react';\nimport { type Accept } from 'react-dropzone';\nimport { dropzoneState, dropzoneVariants, useUploadDropzone } from './dropzone';\nimport { FileListItem } from './multi-file';\nimport { formatFileSize } from './upload-utils';\nimport { useUploader } from './uploader-provider';\n\n/**\n * Props for the FileField component.\n */\nexport type FileFieldProps = Omit, 'children'> & {\n /**\n * Accepted file types.\n */\n accept?: Accept;\n\n /**\n * Human-readable list of accepted types, shown in the hint and messages.\n *\n * @example \"PDF, DOC or DOCX\"\n */\n typesLabel?: string;\n\n /**\n * Maximum file size in bytes.\n */\n maxSize?: number;\n\n /**\n * Whether the field is disabled.\n */\n disabled?: boolean;\n\n /**\n * Id for the hidden file input, so a `` opens the file dialog.\n */\n inputId?: string;\n};\n\n/**\n * A compact, single-file input that sits in a form next to regular fields.\n * Once a file is chosen, it shows the file with its progress instead.\n *\n * @example\n * ```tsx\n * Resume \n * \n * ```\n */\nexport function FileField({\n accept,\n typesLabel,\n maxSize,\n disabled,\n inputId,\n className,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n ...props\n}: FileFieldProps) {\n const { fileStates } = useUploader();\n const fileState = fileStates[0];\n const errorId = React.useId();\n\n const { getRootProps, getInputProps, isDragActive, isDragReject, errors } =\n useUploadDropzone({ accept, maxSize, typesLabel, disabled, replace: true });\n\n const hint = [typesLabel, maxSize && formatFileSize(maxSize)]\n .filter(Boolean)\n .join(' · ');\n\n return (\n \n {fileState ? (\n
\n ) : (\n
0 && errorId]\n .filter(Boolean)\n .join(' ') || undefined,\n 'aria-invalid': errors.length > 0 || undefined,\n className: cn(\n dropzoneVariants,\n 'grid grid-cols-[auto_minmax(0,1fr)] gap-x-2.5 gap-y-1.5 rounded-lg bg-background px-3.5 py-3 text-left hover:bg-background aria-invalid:border-destructive @min-[22rem]:grid-cols-[auto_minmax(0,1fr)_auto]',\n ),\n })}\n {...dropzoneState({ isDragActive, isDragReject, disabled })}\n >\n \n \n \n {isDragReject ? (\n 'File type not supported'\n ) : isDragActive ? (\n 'Drop to upload'\n ) : (\n <>\n Drop a file or{' '}\n browse \n >\n )}\n \n {hint && (\n \n {hint}\n \n )}\n
\n )}\n {errors[0] && (\n
\n {errors[0]}\n
\n )}\n
\n );\n}\n",
+ "content": "'use client';\n\nimport { cn } from '@/lib/utils';\nimport { UploadIcon } from 'lucide-react';\nimport * as React from 'react';\nimport { type Accept } from 'react-dropzone';\nimport { dropzoneState, dropzoneVariants, useUploadDropzone } from './dropzone';\nimport { FileListItem } from './file-list';\nimport { formatFileSize } from './upload-utils';\nimport { useUploader } from './uploader-provider';\n\n/**\n * Props for the FileField component.\n */\nexport type FileFieldProps = Omit, 'children'> & {\n /**\n * Accepted file types.\n */\n accept?: Accept;\n\n /**\n * Human-readable list of accepted types, shown in the hint and messages.\n *\n * @example \"PDF, DOC or DOCX\"\n */\n typesLabel?: string;\n\n /**\n * Maximum file size in bytes.\n */\n maxSize?: number;\n\n /**\n * Whether the field is disabled.\n */\n disabled?: boolean;\n\n /**\n * Id for the hidden file input, so a `` opens the file dialog.\n */\n inputId?: string;\n};\n\n/**\n * A compact, single-file input that sits in a form next to regular fields.\n * Once a file is chosen, it shows the file with its progress instead.\n *\n * @example\n * ```tsx\n * Resume \n * \n * ```\n */\nexport function FileField({\n accept,\n typesLabel,\n maxSize,\n disabled,\n inputId,\n className,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n ...props\n}: FileFieldProps) {\n const { fileStates } = useUploader();\n const fileState = fileStates[0];\n const errorId = React.useId();\n\n const { getRootProps, getInputProps, isDragActive, isDragReject, errors } =\n useUploadDropzone({ accept, maxSize, typesLabel, disabled, replace: true });\n\n const hint = [typesLabel, maxSize && formatFileSize(maxSize)]\n .filter(Boolean)\n .join(' · ');\n\n return (\n \n {fileState ? (\n
\n ) : (\n
0 && errorId]\n .filter(Boolean)\n .join(' ') || undefined,\n 'aria-invalid': errors.length > 0 || undefined,\n className: cn(\n dropzoneVariants,\n 'grid grid-cols-[auto_minmax(0,1fr)] gap-x-2.5 gap-y-1.5 rounded-lg bg-background px-3.5 py-3 text-left hover:bg-background aria-invalid:border-destructive @min-[22rem]:grid-cols-[auto_minmax(0,1fr)_auto]',\n ),\n })}\n {...dropzoneState({ isDragActive, isDragReject, disabled })}\n >\n \n \n \n {isDragReject ? (\n 'File type not supported'\n ) : isDragActive ? (\n 'Drop to upload'\n ) : (\n <>\n Drop a file or{' '}\n browse \n >\n )}\n \n {hint && (\n \n {hint}\n \n )}\n
\n )}\n {errors[0] && (\n
\n {errors[0]}\n
\n )}\n
\n );\n}\n",
"type": "registry:component",
"target": "components/upload/file-field.tsx"
}
],
"type": "registry:component"
-}
+}
\ No newline at end of file
diff --git a/docs/public/r/file-list.json b/docs/public/r/file-list.json
new file mode 100644
index 00000000..e5d8c613
--- /dev/null
+++ b/docs/public/r/file-list.json
@@ -0,0 +1,23 @@
+{
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
+ "name": "file-list",
+ "title": "File List",
+ "description": "Lists the files of an UploaderProvider with their status, progress, retry, cancel and remove.",
+ "dependencies": [
+ "lucide-react"
+ ],
+ "registryDependencies": [
+ "https://edgestore.dev/r/progress-bar.json",
+ "https://edgestore.dev/r/uploader-provider.json",
+ "https://edgestore.dev/r/upload-utils.json"
+ ],
+ "files": [
+ {
+ "path": "examples/components/src/components/upload/file-list.tsx",
+ "content": "'use client';\n\nimport { cn } from '@/lib/utils';\nimport { CheckIcon, RotateCwIcon, XIcon } from 'lucide-react';\nimport * as React from 'react';\nimport { ProgressBar } from './progress-bar';\nimport {\n fileExtension,\n fileKind,\n formatFileSize,\n type FileKind,\n} from './upload-utils';\nimport { useUploader, type FileState } from './uploader-provider';\n\nconst KIND_CLASSNAMES: Record = {\n image: 'text-purple-600 dark:text-purple-400',\n video: 'text-pink-600 dark:text-pink-400',\n audio: 'text-cyan-600 dark:text-cyan-400',\n pdf: 'text-red-600 dark:text-red-400',\n doc: 'text-blue-600 dark:text-blue-400',\n sheet: 'text-green-600 dark:text-green-400',\n slides: 'text-orange-600 dark:text-orange-400',\n archive: 'text-yellow-600 dark:text-yellow-400',\n code: 'text-teal-600 dark:text-teal-400',\n other: 'text-muted-foreground',\n};\n\n/**\n * A colored tile with the file's extension.\n */\nexport function FileBadge({\n file,\n className,\n}: {\n file: File;\n className?: string;\n}) {\n return (\n \n {fileExtension(file.name).slice(0, 4) || 'file'}\n \n );\n}\n\nfunction IconButton({\n label,\n className,\n ...props\n}: React.ComponentProps<'button'> & { label: string }) {\n return (\n \n );\n}\n\n/**\n * One file with its status, progress and actions (retry, cancel, remove).\n */\nexport function FileListItem({\n fileState,\n disabled,\n className,\n ...props\n}: React.ComponentProps<'li'> & {\n fileState: FileState;\n /** Hides the retry, cancel and remove actions. */\n disabled?: boolean;\n}) {\n const { removeFile, cancelUpload, uploadFiles } = useUploader();\n const { file, key, status, progress, error } = fileState;\n\n return (\n \n \n \n
\n \n {file.name}\n \n {status === 'COMPLETE' && (\n \n \n Uploaded \n \n )}\n
\n
\n {status === 'ERROR'\n ? (error ?? 'Upload failed')\n : status === 'UPLOADING'\n ? `${formatFileSize((file.size * progress) / 100)} of ${formatFileSize(file.size)} · ${Math.round(progress)}%`\n : formatFileSize(file.size)}\n
\n
\n {/* Pinned to the bottom edge so the row keeps its height when the upload ends. */}\n {status === 'UPLOADING' && (\n \n )}\n {!disabled && (\n \n {status === 'ERROR' && (\n void uploadFiles([key])}\n >\n \n \n )}\n {status === 'UPLOADING' ? (\n cancelUpload(key)}\n >\n \n \n ) : (\n removeFile(key)}\n >\n \n \n )}\n
\n )}\n \n );\n}\n\n/**\n * Lists the files of the nearest `UploaderProvider`.\n *\n * @example\n * ```tsx\n * \n * ```\n */\nexport function FileList({\n disabled,\n className,\n ...props\n}: React.ComponentProps<'ul'> & {\n /** Hides the retry, cancel and remove actions. */\n disabled?: boolean;\n}) {\n const { fileStates } = useUploader();\n if (fileStates.length === 0) return null;\n\n return (\n \n {fileStates.map((fileState) => (\n \n ))}\n \n );\n}\n",
+ "type": "registry:component",
+ "target": "components/upload/file-list.tsx"
+ }
+ ],
+ "type": "registry:component"
+}
\ No newline at end of file
diff --git a/docs/public/r/file-uploader-block.json b/docs/public/r/file-uploader-block.json
index fab6dd14..6cabbfec 100644
--- a/docs/public/r/file-uploader-block.json
+++ b/docs/public/r/file-uploader-block.json
@@ -11,8 +11,8 @@
{
"path": "examples/components/src/components/upload/blocks/multi-file-block.tsx",
"content": "'use client';\n\nimport { FileUploader } from '@/components/upload/multi-file';\nimport {\n UploaderProvider,\n useUploader,\n type CompletedFileState,\n type UploadFn,\n} from '@/components/upload/uploader-provider';\nimport * as React from 'react';\n\nexport default function FileUploaderBlock() {\n const { edgestore } = useMockEdgeStore(); // Mock edgestore for easy v0 integration\n\n const uploadFn: UploadFn = React.useCallback(\n async ({ file, signal, onProgressChange }) => {\n const res = await edgestore.myPublicFiles.upload({\n file,\n signal,\n onProgressChange,\n });\n // you can run some server action or api here\n // to add the necessary data to your database\n return { url: res.url };\n },\n [edgestore],\n );\n\n return (\n \n );\n}\n\nfunction CompletedFiles() {\n const { fileStates } = useUploader();\n\n const completedFiles = fileStates.filter(\n (fs): fs is CompletedFileState => fs.status === 'COMPLETE',\n );\n\n if (completedFiles.length === 0) {\n return null;\n }\n\n return (\n \n );\n}\n\n// Mock implementation of EdgeStore\nfunction useMockEdgeStore() {\n return {\n edgestore: {\n myPublicFiles: {\n upload: async ({\n signal,\n onProgressChange,\n }: {\n file: File;\n signal?: AbortSignal;\n onProgressChange?: (progress: number) => void | Promise;\n }) => {\n // Simulate upload progress. Rejects like EdgeStore when the upload is aborted.\n await new Promise((resolve, reject) => {\n let progress = 0;\n const interval = setInterval(() => {\n progress = Math.min(\n progress + Math.floor(Math.random() * 21) + 10,\n 100,\n );\n void onProgressChange?.(progress);\n if (progress >= 100) {\n clearInterval(interval);\n resolve();\n }\n }, 300);\n signal?.addEventListener('abort', () => {\n clearInterval(interval);\n reject(new DOMException('Upload aborted', 'AbortError'));\n });\n });\n\n return {\n url: 'https://edgestore.dev/img/upload-demo.webp',\n };\n },\n },\n },\n };\n}\n",
- "type": "registry:block",
- "target": "components/upload/blocks/multi-file-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
],
"type": "registry:block"
diff --git a/docs/public/r/file-uploader.json b/docs/public/r/file-uploader.json
index 8db1bb9a..80944ff7 100644
--- a/docs/public/r/file-uploader.json
+++ b/docs/public/r/file-uploader.json
@@ -10,14 +10,14 @@
"registryDependencies": [
"button",
"https://edgestore.dev/r/dropzone.json",
- "https://edgestore.dev/r/progress-bar.json",
+ "https://edgestore.dev/r/file-list.json",
"https://edgestore.dev/r/uploader-provider.json",
"https://edgestore.dev/r/upload-utils.json"
],
"files": [
{
"path": "examples/components/src/components/upload/multi-file.tsx",
- "content": "'use client';\n\nimport { Button } from '@/components/ui/button';\nimport { cn } from '@/lib/utils';\nimport { CheckIcon, RotateCwIcon, XIcon } from 'lucide-react';\nimport * as React from 'react';\nimport { type Accept } from 'react-dropzone';\nimport { Dropzone } from './dropzone';\nimport { ProgressBar } from './progress-bar';\nimport {\n fileExtension,\n fileKind,\n formatFileSize,\n type FileKind,\n} from './upload-utils';\nimport { useUploader, type FileState } from './uploader-provider';\n\nconst KIND_CLASSNAMES: Record = {\n image: 'text-purple-600 dark:text-purple-400',\n video: 'text-pink-600 dark:text-pink-400',\n audio: 'text-cyan-600 dark:text-cyan-400',\n pdf: 'text-red-600 dark:text-red-400',\n doc: 'text-blue-600 dark:text-blue-400',\n sheet: 'text-green-600 dark:text-green-400',\n slides: 'text-orange-600 dark:text-orange-400',\n archive: 'text-yellow-600 dark:text-yellow-400',\n code: 'text-teal-600 dark:text-teal-400',\n other: 'text-muted-foreground',\n};\n\n/**\n * A colored tile with the file's extension.\n */\nexport function FileBadge({\n file,\n className,\n}: {\n file: File;\n className?: string;\n}) {\n return (\n \n {fileExtension(file.name).slice(0, 4) || 'file'}\n \n );\n}\n\nfunction IconButton({\n label,\n className,\n ...props\n}: React.ComponentProps<'button'> & { label: string }) {\n return (\n \n );\n}\n\n/**\n * One file with its status, progress and actions (retry, cancel, remove).\n */\nexport function FileListItem({\n fileState,\n disabled,\n className,\n ...props\n}: React.ComponentProps<'li'> & {\n fileState: FileState;\n /** Hides the retry, cancel and remove actions. */\n disabled?: boolean;\n}) {\n const { removeFile, cancelUpload, uploadFiles } = useUploader();\n const { file, key, status, progress, error } = fileState;\n\n return (\n \n \n \n
\n \n {file.name}\n \n {status === 'COMPLETE' && (\n \n \n Uploaded \n \n )}\n
\n
\n {status === 'ERROR'\n ? (error ?? 'Upload failed')\n : status === 'UPLOADING'\n ? `${formatFileSize((file.size * progress) / 100)} of ${formatFileSize(file.size)} · ${Math.round(progress)}%`\n : formatFileSize(file.size)}\n
\n
\n {/* Pinned to the bottom edge so the row keeps its height when the upload ends. */}\n {status === 'UPLOADING' && (\n \n )}\n {!disabled && (\n \n {status === 'ERROR' && (\n void uploadFiles([key])}\n >\n \n \n )}\n {status === 'UPLOADING' ? (\n cancelUpload(key)}\n >\n \n \n ) : (\n removeFile(key)}\n >\n \n \n )}\n
\n )}\n \n );\n}\n\n/**\n * Lists the files of the nearest `UploaderProvider`.\n *\n * @example\n * ```tsx\n * \n * ```\n */\nexport function FileList({\n disabled,\n className,\n ...props\n}: React.ComponentProps<'ul'> & {\n /** Hides the retry, cancel and remove actions. */\n disabled?: boolean;\n}) {\n const { fileStates } = useUploader();\n if (fileStates.length === 0) return null;\n\n return (\n \n {fileStates.map((fileState) => (\n \n ))}\n \n );\n}\n\n/**\n * Props for the FileUploader component.\n */\nexport type FileUploaderProps = React.ComponentProps<'div'> & {\n /**\n * Maximum number of files allowed in total.\n */\n maxFiles?: number;\n\n /**\n * Maximum file size in bytes.\n */\n maxSize?: number;\n\n /**\n * Accepted file types.\n *\n * @example\n * ```tsx\n * accept={{ 'application/pdf': ['.pdf'] }}\n * ```\n */\n accept?: Accept;\n\n /**\n * Human-readable list of accepted types, shown in the hint and messages.\n *\n * @example \"PDF or TXT\"\n */\n typesLabel?: string;\n\n /**\n * Whether the uploader is disabled.\n */\n disabled?: boolean;\n\n /**\n * Additional className for the dropzone.\n */\n dropzoneClassName?: string;\n\n /**\n * Additional className for the file list.\n */\n fileListClassName?: string;\n};\n\n/**\n * A dropzone with a list of files, their progress and a summary.\n *\n * @example\n * ```tsx\n * \n * ```\n */\nexport function FileUploader({\n maxFiles,\n maxSize,\n accept,\n typesLabel,\n disabled,\n className,\n dropzoneClassName,\n fileListClassName,\n ...props\n}: FileUploaderProps) {\n const { fileStates, resetFiles } = useUploader();\n const completed = fileStates.filter((fs) => fs.status === 'COMPLETE').length;\n const totalSize = fileStates.reduce((sum, fs) => sum + fs.file.size, 0);\n\n return (\n \n
\n
\n {fileStates.length > 0 && (\n
\n \n {completed} of {fileStates.length} uploaded ·{' '}\n {formatFileSize(totalSize)}\n \n \n Clear all\n \n
\n )}\n
\n );\n}\n",
+ "content": "'use client';\n\nimport { Button } from '@/components/ui/button';\nimport { cn } from '@/lib/utils';\nimport * as React from 'react';\nimport { type Accept } from 'react-dropzone';\nimport { Dropzone } from './dropzone';\nimport { FileList } from './file-list';\nimport { formatFileSize } from './upload-utils';\nimport { useUploader } from './uploader-provider';\n\n/**\n * Props for the FileUploader component.\n */\nexport type FileUploaderProps = React.ComponentProps<'div'> & {\n /**\n * Maximum number of files allowed in total.\n */\n maxFiles?: number;\n\n /**\n * Maximum file size in bytes.\n */\n maxSize?: number;\n\n /**\n * Accepted file types.\n *\n * @example\n * ```tsx\n * accept={{ 'application/pdf': ['.pdf'] }}\n * ```\n */\n accept?: Accept;\n\n /**\n * Human-readable list of accepted types, shown in the hint and messages.\n *\n * @example \"PDF or TXT\"\n */\n typesLabel?: string;\n\n /**\n * Whether the uploader is disabled.\n */\n disabled?: boolean;\n\n /**\n * Additional className for the dropzone.\n */\n dropzoneClassName?: string;\n\n /**\n * Additional className for the file list.\n */\n fileListClassName?: string;\n};\n\n/**\n * A dropzone with a list of files, their progress and a summary.\n *\n * @example\n * ```tsx\n * \n * ```\n */\nexport function FileUploader({\n maxFiles,\n maxSize,\n accept,\n typesLabel,\n disabled,\n className,\n dropzoneClassName,\n fileListClassName,\n ...props\n}: FileUploaderProps) {\n const { fileStates, resetFiles } = useUploader();\n const completed = fileStates.filter((fs) => fs.status === 'COMPLETE').length;\n const totalSize = fileStates.reduce((sum, fs) => sum + fs.file.size, 0);\n\n return (\n \n
\n
\n {fileStates.length > 0 && (\n
\n \n {completed} of {fileStates.length} uploaded ·{' '}\n {formatFileSize(totalSize)}\n \n \n Clear all\n \n
\n )}\n
\n );\n}\n",
"type": "registry:component",
"target": "components/upload/multi-file.tsx"
}
diff --git a/docs/public/r/multi-image-uploader-block.json b/docs/public/r/multi-image-uploader-block.json
index 505f5299..d3e0c6cd 100644
--- a/docs/public/r/multi-image-uploader-block.json
+++ b/docs/public/r/multi-image-uploader-block.json
@@ -11,8 +11,8 @@
{
"path": "examples/components/src/components/upload/blocks/multi-image-block.tsx",
"content": "'use client';\n\nimport { ImageUploader } from '@/components/upload/multi-image';\nimport {\n UploaderProvider,\n useUploader,\n type CompletedFileState,\n type UploadFn,\n} from '@/components/upload/uploader-provider';\nimport * as React from 'react';\n\nexport default function MultiImageUploaderBlock() {\n const { edgestore } = useMockEdgeStore(); // Mock edgestore for easy v0 integration\n\n const uploadFn: UploadFn = React.useCallback(\n async ({ file, signal, onProgressChange }) => {\n const res = await edgestore.myPublicImages.upload({\n file,\n signal,\n onProgressChange,\n });\n // you can run some server action or api here\n // to add the necessary data to your database\n return { url: res.url };\n },\n [edgestore],\n );\n\n return (\n \n );\n}\n\nfunction CompletedFiles() {\n const { fileStates } = useUploader();\n\n const completedFiles = fileStates.filter(\n (fs): fs is CompletedFileState => fs.status === 'COMPLETE',\n );\n\n if (completedFiles.length === 0) {\n return null;\n }\n\n return (\n \n );\n}\n\n// Mock implementation of EdgeStore\nfunction useMockEdgeStore() {\n return {\n edgestore: {\n myPublicImages: {\n upload: async ({\n signal,\n onProgressChange,\n }: {\n file: File;\n signal?: AbortSignal;\n onProgressChange?: (progress: number) => void | Promise;\n }) => {\n // Simulate upload progress. Rejects like EdgeStore when the upload is aborted.\n await new Promise((resolve, reject) => {\n let progress = 0;\n const interval = setInterval(() => {\n progress = Math.min(\n progress + Math.floor(Math.random() * 21) + 10,\n 100,\n );\n void onProgressChange?.(progress);\n if (progress >= 100) {\n clearInterval(interval);\n resolve();\n }\n }, 300);\n signal?.addEventListener('abort', () => {\n clearInterval(interval);\n reject(new DOMException('Upload aborted', 'AbortError'));\n });\n });\n\n return {\n url: 'https://edgestore.dev/img/upload-demo.webp',\n };\n },\n },\n },\n };\n}\n",
- "type": "registry:block",
- "target": "components/upload/blocks/multi-image-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
],
"type": "registry:block"
diff --git a/docs/public/r/progress-bar-block.json b/docs/public/r/progress-bar-block.json
index d0235832..f232bb53 100644
--- a/docs/public/r/progress-bar-block.json
+++ b/docs/public/r/progress-bar-block.json
@@ -9,9 +9,9 @@
"files": [
{
"path": "examples/components/src/components/upload/blocks/progress-bar-block.tsx",
- "content": "'use client';\n\nimport * as React from 'react';\nimport { ProgressBar } from '../progress-bar';\n\nexport default function ProgressBarUsage() {\n const [progress, setProgress] = React.useState(0);\n\n React.useEffect(() => {\n const startAnimation = () => {\n const interval = setInterval(() => {\n setProgress((prevProgress) => {\n if (prevProgress >= 100) {\n clearInterval(interval);\n // Reset after 1 second when reaching 100%\n setTimeout(() => {\n setProgress(0);\n startAnimation(); // Restart the animation cycle\n }, 1000);\n return 100;\n }\n // Add a random value between 10-20 percent\n return Math.min(\n 100,\n prevProgress + Math.floor(Math.random() * 11) + 10,\n );\n });\n }, 300);\n\n return interval;\n };\n\n const interval = startAnimation();\n\n return () => {\n clearInterval(interval);\n };\n }, []);\n\n return (\n \n );\n}\n",
- "type": "registry:block",
- "target": "components/upload/blocks/progress-bar-block.tsx"
+ "content": "'use client';\n\nimport { ProgressBar } from '@/components/upload/progress-bar';\nimport * as React from 'react';\n\nexport default function ProgressBarUsage() {\n const [progress, setProgress] = React.useState(0);\n\n React.useEffect(() => {\n const startAnimation = () => {\n const interval = setInterval(() => {\n setProgress((prevProgress) => {\n if (prevProgress >= 100) {\n clearInterval(interval);\n // Reset after 1 second when reaching 100%\n setTimeout(() => {\n setProgress(0);\n startAnimation(); // Restart the animation cycle\n }, 1000);\n return 100;\n }\n // Add a random value between 10-20 percent\n return Math.min(\n 100,\n prevProgress + Math.floor(Math.random() * 11) + 10,\n );\n });\n }, 300);\n\n return interval;\n };\n\n const interval = startAnimation();\n\n return () => {\n clearInterval(interval);\n };\n }, []);\n\n return (\n \n );\n}\n",
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
],
"type": "registry:block"
diff --git a/docs/public/r/progress-circle-block.json b/docs/public/r/progress-circle-block.json
index 86d11fd4..0ec5241c 100644
--- a/docs/public/r/progress-circle-block.json
+++ b/docs/public/r/progress-circle-block.json
@@ -9,9 +9,9 @@
"files": [
{
"path": "examples/components/src/components/upload/blocks/progress-circle-block.tsx",
- "content": "'use client';\n\nimport * as React from 'react';\nimport { ProgressCircle } from '../progress-circle';\n\nexport default function ProgressCircleUsage() {\n const [progress, setProgress] = React.useState(0);\n\n React.useEffect(() => {\n const startAnimation = () => {\n const interval = setInterval(() => {\n setProgress((prevProgress) => {\n if (prevProgress >= 100) {\n clearInterval(interval);\n // Reset after 1 second when reaching 100%\n setTimeout(() => {\n setProgress(0);\n startAnimation(); // Restart the animation cycle\n }, 1000);\n return 100;\n }\n // Add a random value between 10-20 percent\n return Math.min(\n 100,\n prevProgress + Math.floor(Math.random() * 11) + 10,\n );\n });\n }, 300);\n\n return interval;\n };\n\n const interval = startAnimation();\n\n return () => {\n clearInterval(interval);\n };\n }, []);\n\n return (\n \n );\n}\n",
- "type": "registry:block",
- "target": "components/upload/blocks/progress-circle-block.tsx"
+ "content": "'use client';\n\nimport { ProgressCircle } from '@/components/upload/progress-circle';\nimport * as React from 'react';\n\nexport default function ProgressCircleUsage() {\n const [progress, setProgress] = React.useState(0);\n\n React.useEffect(() => {\n const startAnimation = () => {\n const interval = setInterval(() => {\n setProgress((prevProgress) => {\n if (prevProgress >= 100) {\n clearInterval(interval);\n // Reset after 1 second when reaching 100%\n setTimeout(() => {\n setProgress(0);\n startAnimation(); // Restart the animation cycle\n }, 1000);\n return 100;\n }\n // Add a random value between 10-20 percent\n return Math.min(\n 100,\n prevProgress + Math.floor(Math.random() * 11) + 10,\n );\n });\n }, 300);\n\n return interval;\n };\n\n const interval = startAnimation();\n\n return () => {\n clearInterval(interval);\n };\n }, []);\n\n return (\n \n );\n}\n",
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
],
"type": "registry:block"
diff --git a/docs/public/r/registry.json b/docs/public/r/registry.json
index 9a5189c4..18f57379 100644
--- a/docs/public/r/registry.json
+++ b/docs/public/r/registry.json
@@ -48,6 +48,25 @@
}
]
},
+ {
+ "name": "file-list",
+ "type": "registry:component",
+ "title": "File List",
+ "description": "Lists the files of an UploaderProvider with their status, progress, retry, cancel and remove.",
+ "dependencies": ["lucide-react"],
+ "registryDependencies": [
+ "https://edgestore.dev/r/progress-bar.json",
+ "https://edgestore.dev/r/uploader-provider.json",
+ "https://edgestore.dev/r/upload-utils.json"
+ ],
+ "files": [
+ {
+ "path": "examples/components/src/components/upload/file-list.tsx",
+ "type": "registry:component",
+ "target": "components/upload/file-list.tsx"
+ }
+ ]
+ },
{
"name": "file-uploader",
"type": "registry:component",
@@ -57,7 +76,7 @@
"registryDependencies": [
"button",
"https://edgestore.dev/r/dropzone.json",
- "https://edgestore.dev/r/progress-bar.json",
+ "https://edgestore.dev/r/file-list.json",
"https://edgestore.dev/r/uploader-provider.json",
"https://edgestore.dev/r/upload-utils.json"
],
@@ -139,7 +158,7 @@
"dependencies": ["react-dropzone", "lucide-react"],
"registryDependencies": [
"https://edgestore.dev/r/dropzone.json",
- "https://edgestore.dev/r/file-uploader.json",
+ "https://edgestore.dev/r/file-list.json",
"https://edgestore.dev/r/uploader-provider.json",
"https://edgestore.dev/r/upload-utils.json"
],
@@ -208,8 +227,8 @@
"files": [
{
"path": "examples/components/src/components/upload/blocks/multi-file-block.tsx",
- "type": "registry:block",
- "target": "components/upload/blocks/multi-file-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
]
},
@@ -225,8 +244,8 @@
"files": [
{
"path": "examples/components/src/components/upload/blocks/single-image-block.tsx",
- "type": "registry:block",
- "target": "components/upload/blocks/single-image-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
]
},
@@ -242,8 +261,8 @@
"files": [
{
"path": "examples/components/src/components/upload/blocks/multi-image-block.tsx",
- "type": "registry:block",
- "target": "components/upload/blocks/multi-image-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
]
},
@@ -259,8 +278,8 @@
"files": [
{
"path": "examples/components/src/components/upload/blocks/avatar-block.tsx",
- "type": "registry:block",
- "target": "components/upload/blocks/avatar-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
]
},
@@ -277,8 +296,8 @@
"files": [
{
"path": "examples/components/src/components/upload/blocks/file-field-block.tsx",
- "type": "registry:block",
- "target": "components/upload/blocks/file-field-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
]
},
@@ -290,15 +309,15 @@
"dependencies": ["lucide-react"],
"registryDependencies": [
"https://edgestore.dev/r/upload-button.json",
- "https://edgestore.dev/r/file-uploader.json",
+ "https://edgestore.dev/r/file-list.json",
"https://edgestore.dev/r/dropzone.json",
"https://edgestore.dev/r/uploader-provider.json"
],
"files": [
{
"path": "examples/components/src/components/upload/blocks/upload-button-block.tsx",
- "type": "registry:block",
- "target": "components/upload/blocks/upload-button-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
]
},
@@ -311,8 +330,8 @@
"files": [
{
"path": "examples/components/src/components/upload/blocks/progress-bar-block.tsx",
- "type": "registry:block",
- "target": "components/upload/blocks/progress-bar-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
]
},
@@ -325,8 +344,8 @@
"files": [
{
"path": "examples/components/src/components/upload/blocks/progress-circle-block.tsx",
- "type": "registry:block",
- "target": "components/upload/blocks/progress-circle-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
]
}
diff --git a/docs/public/r/single-image-dropzone-block.json b/docs/public/r/single-image-dropzone-block.json
index b8f7e699..30bca9d4 100644
--- a/docs/public/r/single-image-dropzone-block.json
+++ b/docs/public/r/single-image-dropzone-block.json
@@ -11,8 +11,8 @@
{
"path": "examples/components/src/components/upload/blocks/single-image-block.tsx",
"content": "'use client';\n\nimport { SingleImageDropzone } from '@/components/upload/single-image';\nimport {\n UploaderProvider,\n useUploader,\n type CompletedFileState,\n type UploadFn,\n} from '@/components/upload/uploader-provider';\nimport * as React from 'react';\n\nexport default function SingleImageUploaderBlock() {\n const { edgestore } = useMockEdgeStore(); // Mock edgestore for easy v0 integration\n\n const uploadFn: UploadFn = React.useCallback(\n async ({ file, signal, onProgressChange }) => {\n const res = await edgestore.myPublicImages.upload({\n file,\n signal,\n onProgressChange,\n });\n // you can run some server action or api here\n // to add the necessary data to your database\n return { url: res.url };\n },\n [edgestore],\n );\n\n return (\n \n \n \n \n \n
\n );\n}\n\nfunction CompletedFiles() {\n const { fileStates } = useUploader();\n\n const completedFiles = fileStates.filter(\n (fs): fs is CompletedFileState => fs.status === 'COMPLETE',\n );\n\n if (completedFiles.length === 0) {\n return null;\n }\n\n return (\n \n );\n}\n\n// Mock implementation of EdgeStore\nfunction useMockEdgeStore() {\n return {\n edgestore: {\n myPublicImages: {\n upload: async ({\n signal,\n onProgressChange,\n }: {\n file: File;\n signal?: AbortSignal;\n onProgressChange?: (progress: number) => void | Promise;\n }) => {\n // Simulate upload progress. Rejects like EdgeStore when the upload is aborted.\n await new Promise((resolve, reject) => {\n let progress = 0;\n const interval = setInterval(() => {\n progress = Math.min(\n progress + Math.floor(Math.random() * 21) + 10,\n 100,\n );\n void onProgressChange?.(progress);\n if (progress >= 100) {\n clearInterval(interval);\n resolve();\n }\n }, 300);\n signal?.addEventListener('abort', () => {\n clearInterval(interval);\n reject(new DOMException('Upload aborted', 'AbortError'));\n });\n });\n\n return {\n url: 'https://edgestore.dev/img/upload-demo.webp',\n };\n },\n },\n },\n };\n}\n",
- "type": "registry:block",
- "target": "components/upload/blocks/single-image-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
],
"type": "registry:block"
diff --git a/docs/public/r/upload-button-block.json b/docs/public/r/upload-button-block.json
index 9cda7a90..03fc977a 100644
--- a/docs/public/r/upload-button-block.json
+++ b/docs/public/r/upload-button-block.json
@@ -8,16 +8,16 @@
],
"registryDependencies": [
"https://edgestore.dev/r/upload-button.json",
- "https://edgestore.dev/r/file-uploader.json",
+ "https://edgestore.dev/r/file-list.json",
"https://edgestore.dev/r/dropzone.json",
"https://edgestore.dev/r/uploader-provider.json"
],
"files": [
{
"path": "examples/components/src/components/upload/blocks/upload-button-block.tsx",
- "content": "'use client';\n\nimport { UploadErrors } from '@/components/upload/dropzone';\nimport { FileList } from '@/components/upload/multi-file';\nimport { UploadButton } from '@/components/upload/upload-button';\nimport {\n UploaderProvider,\n type UploadFn,\n} from '@/components/upload/uploader-provider';\nimport { PaperclipIcon, UploadIcon } from 'lucide-react';\nimport * as React from 'react';\n\nexport default function UploadButtonBlock() {\n const [errors, setErrors] = React.useState([]);\n const { edgestore } = useMockEdgeStore(); // Mock edgestore for easy v0 integration\n\n const uploadFn: UploadFn = React.useCallback(\n async ({ file, signal, onProgressChange }) => {\n const res = await edgestore.myPublicFiles.upload({\n file,\n signal,\n onProgressChange,\n });\n // you can run some server action or api here\n // to add the necessary data to your database\n return { url: res.url };\n },\n [edgestore],\n );\n\n return (\n \n
\n
\n \n
\n Upload files\n \n
\n \n \n
\n setErrors([])} />\n \n \n
\n
\n );\n}\n\n// Mock implementation of EdgeStore\nfunction useMockEdgeStore() {\n return {\n edgestore: {\n myPublicFiles: {\n upload: async ({\n signal,\n onProgressChange,\n }: {\n file: File;\n signal?: AbortSignal;\n onProgressChange?: (progress: number) => void | Promise;\n }) => {\n // Simulate upload progress. Rejects like EdgeStore when the upload is aborted.\n await new Promise((resolve, reject) => {\n let progress = 0;\n const interval = setInterval(() => {\n progress = Math.min(\n progress + Math.floor(Math.random() * 21) + 10,\n 100,\n );\n void onProgressChange?.(progress);\n if (progress >= 100) {\n clearInterval(interval);\n resolve();\n }\n }, 300);\n signal?.addEventListener('abort', () => {\n clearInterval(interval);\n reject(new DOMException('Upload aborted', 'AbortError'));\n });\n });\n\n return {\n url: 'https://edgestore.dev/img/upload-demo.webp',\n };\n },\n },\n },\n };\n}\n",
- "type": "registry:block",
- "target": "components/upload/blocks/upload-button-block.tsx"
+ "content": "'use client';\n\nimport { UploadErrors } from '@/components/upload/dropzone';\nimport { FileList } from '@/components/upload/file-list';\nimport { UploadButton } from '@/components/upload/upload-button';\nimport {\n UploaderProvider,\n type UploadFn,\n} from '@/components/upload/uploader-provider';\nimport { PaperclipIcon, UploadIcon } from 'lucide-react';\nimport * as React from 'react';\n\nexport default function UploadButtonBlock() {\n const [errors, setErrors] = React.useState([]);\n const { edgestore } = useMockEdgeStore(); // Mock edgestore for easy v0 integration\n\n const uploadFn: UploadFn = React.useCallback(\n async ({ file, signal, onProgressChange }) => {\n const res = await edgestore.myPublicFiles.upload({\n file,\n signal,\n onProgressChange,\n });\n // you can run some server action or api here\n // to add the necessary data to your database\n return { url: res.url };\n },\n [edgestore],\n );\n\n return (\n \n
\n
\n \n
\n Upload files\n \n
\n \n \n
\n setErrors([])} />\n \n \n
\n
\n );\n}\n\n// Mock implementation of EdgeStore\nfunction useMockEdgeStore() {\n return {\n edgestore: {\n myPublicFiles: {\n upload: async ({\n signal,\n onProgressChange,\n }: {\n file: File;\n signal?: AbortSignal;\n onProgressChange?: (progress: number) => void | Promise;\n }) => {\n // Simulate upload progress. Rejects like EdgeStore when the upload is aborted.\n await new Promise((resolve, reject) => {\n let progress = 0;\n const interval = setInterval(() => {\n progress = Math.min(\n progress + Math.floor(Math.random() * 21) + 10,\n 100,\n );\n void onProgressChange?.(progress);\n if (progress >= 100) {\n clearInterval(interval);\n resolve();\n }\n }, 300);\n signal?.addEventListener('abort', () => {\n clearInterval(interval);\n reject(new DOMException('Upload aborted', 'AbortError'));\n });\n });\n\n return {\n url: 'https://edgestore.dev/img/upload-demo.webp',\n };\n },\n },\n },\n };\n}\n",
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
],
"type": "registry:block"
diff --git a/docs/src/app/(main)/pricing/_components/pricing.tsx b/docs/src/app/(main)/pricing/_components/pricing.tsx
index 3b10a080..8de41116 100644
--- a/docs/src/app/(main)/pricing/_components/pricing.tsx
+++ b/docs/src/app/(main)/pricing/_components/pricing.tsx
@@ -1,5 +1,6 @@
import { ActionButton } from '@/components/action-button';
import { env } from '@/env';
+import { SPONSOR_URL } from '@/lib/constants';
import { formatFileSize, formatNumber } from '@/lib/formatter';
import { cn } from '@/lib/utils';
import { CheckCircleIcon, HeartIcon } from 'lucide-react';
@@ -127,7 +128,7 @@ function PricingBlock(props: {
function SponsorButton() {
return (
-
+
Sponsor
);
@@ -224,7 +225,7 @@ function buildPricingBlocks(
id: 'STARTER',
title: 'Starter',
description:
- 'Best for start-ups and businesses who build commercial products with Edge Store.',
+ 'Best for start-ups and businesses who build commercial products with EdgeStore.',
price: toDollars(defaultPricing.STARTER.basePrice, 5),
upcoming: toUpcoming(upcomingPricing?.STARTER),
features: [
@@ -286,7 +287,7 @@ function buildPricingBlocks(
id: 'PRO',
title: 'Pro',
description:
- 'Best for businesses who build larger commercial products with Edge Store.',
+ 'Best for businesses who build larger commercial products with EdgeStore.',
price: toDollars(defaultPricing.PRO.basePrice, 35),
upcoming: toUpcoming(upcomingPricing?.PRO),
features: [
diff --git a/docs/src/components/setup-guide.tsx b/docs/src/components/setup-guide.tsx
index 65c66efe..c210a344 100644
--- a/docs/src/components/setup-guide.tsx
+++ b/docs/src/components/setup-guide.tsx
@@ -1,67 +1,14 @@
'use client';
+import { useRevealAnchor } from '@/hooks/use-reveal-anchor';
import { ChevronRight } from 'lucide-react';
-import { useEffect, useRef, type ReactNode } from 'react';
+import { useRef, type ReactNode } from 'react';
export function SetupGuide({ children }: { children: ReactNode }) {
const details = useRef(null);
-
- useEffect(() => {
- let frame: number | undefined;
-
- function reveal(hash: string) {
- let id: string;
- try {
- id = decodeURIComponent(hash.slice(1));
- } catch {
- return;
- }
- const target = document.getElementById(id);
- if (!target || !details.current?.contains(target)) return;
- details.current.open = true;
- if (frame !== undefined) cancelAnimationFrame(frame);
- frame = requestAnimationFrame(() =>
- target.scrollIntoView({ block: 'start' }),
- );
- }
-
- function onHashChange() {
- reveal(window.location.hash);
- }
-
- // Also handle clicks on the current hash after the reader closes the guide.
- function onClick(event: MouseEvent) {
- if (
- event.button !== 0 ||
- event.metaKey ||
- event.ctrlKey ||
- event.shiftKey ||
- event.altKey
- )
- return;
- const link =
- event.target instanceof Element ? event.target.closest('a') : null;
- if (!link || link.target === '_blank' || link.hasAttribute('download'))
- return;
- const url = new URL(link.href, window.location.href);
- if (
- url.origin === window.location.origin &&
- url.pathname === window.location.pathname &&
- url.search === window.location.search
- ) {
- reveal(url.hash);
- }
- }
-
- onHashChange();
- window.addEventListener('hashchange', onHashChange);
- document.addEventListener('click', onClick, true);
- return () => {
- window.removeEventListener('hashchange', onHashChange);
- document.removeEventListener('click', onClick, true);
- if (frame !== undefined) cancelAnimationFrame(frame);
- };
- }, []);
+ useRevealAnchor(details, () => {
+ if (details.current) details.current.open = true;
+ });
return (
diff --git a/docs/src/components/ui/open-tabs.tsx b/docs/src/components/ui/open-tabs.tsx
index 9cafdea3..4a7b660f 100644
--- a/docs/src/components/ui/open-tabs.tsx
+++ b/docs/src/components/ui/open-tabs.tsx
@@ -1,10 +1,28 @@
'use client';
+import { useRevealAnchor } from '@/hooks/use-reveal-anchor';
import { cn } from '@/lib/utils';
import * as TabsPrimitive from '@radix-ui/react-tabs';
import * as React from 'react';
-const OpenTabs = TabsPrimitive.Root;
+const SelectTabContext = React.createContext<((value: string) => void) | null>(
+ null,
+);
+
+function OpenTabs({
+ defaultValue,
+ ...props
+}: Omit<
+ React.ComponentProps,
+ 'value' | 'onValueChange'
+>) {
+ const [value, setValue] = React.useState(defaultValue);
+ return (
+
+
+
+ );
+}
const OpenTabsList = React.forwardRef<
React.ComponentRef,
@@ -36,19 +54,28 @@ const OpenTabsTrigger = React.forwardRef<
));
OpenTabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
-const OpenTabsContent = React.forwardRef<
- React.ComponentRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-));
-OpenTabsContent.displayName = TabsPrimitive.Content.displayName;
+// Inactive panels stay mounted so links to headings inside them can open them.
+function OpenTabsContent({
+ className,
+ value,
+ ...props
+}: Omit, 'forceMount'>) {
+ const selectTab = React.use(SelectTabContext);
+ const content = React.useRef(null);
+ useRevealAnchor(content, () => selectTab?.(value));
+
+ return (
+
+ );
+}
export { OpenTabs, OpenTabsList, OpenTabsTrigger, OpenTabsContent };
diff --git a/docs/src/components/upload/blocks/upload-button-block.tsx b/docs/src/components/upload/blocks/upload-button-block.tsx
index 2a4406a6..5f2df2f2 100644
--- a/docs/src/components/upload/blocks/upload-button-block.tsx
+++ b/docs/src/components/upload/blocks/upload-button-block.tsx
@@ -1,7 +1,7 @@
'use client';
import { UploadErrors } from '@/components/upload/dropzone';
-import { FileList } from '@/components/upload/multi-file';
+import { FileList } from '@/components/upload/file-list';
import { UploadButton } from '@/components/upload/upload-button';
import {
UploaderProvider,
diff --git a/docs/src/components/upload/file-field.tsx b/docs/src/components/upload/file-field.tsx
index a4393bc7..a46adfb5 100644
--- a/docs/src/components/upload/file-field.tsx
+++ b/docs/src/components/upload/file-field.tsx
@@ -5,7 +5,7 @@ import { UploadIcon } from 'lucide-react';
import * as React from 'react';
import { type Accept } from 'react-dropzone';
import { dropzoneState, dropzoneVariants, useUploadDropzone } from './dropzone';
-import { FileListItem } from './multi-file';
+import { FileListItem } from './file-list';
import { formatFileSize } from './upload-utils';
import { useUploader } from './uploader-provider';
diff --git a/docs/src/components/upload/file-list.tsx b/docs/src/components/upload/file-list.tsx
new file mode 100644
index 00000000..6e980be1
--- /dev/null
+++ b/docs/src/components/upload/file-list.tsx
@@ -0,0 +1,196 @@
+'use client';
+
+import { cn } from '@/lib/utils';
+import { CheckIcon, RotateCwIcon, XIcon } from 'lucide-react';
+import * as React from 'react';
+import { ProgressBar } from './progress-bar';
+import {
+ fileExtension,
+ fileKind,
+ formatFileSize,
+ type FileKind,
+} from './upload-utils';
+import { useUploader, type FileState } from './uploader-provider';
+
+const KIND_CLASSNAMES: Record = {
+ image: 'text-purple-600 dark:text-purple-400',
+ video: 'text-pink-600 dark:text-pink-400',
+ audio: 'text-cyan-600 dark:text-cyan-400',
+ pdf: 'text-red-600 dark:text-red-400',
+ doc: 'text-blue-600 dark:text-blue-400',
+ sheet: 'text-green-600 dark:text-green-400',
+ slides: 'text-orange-600 dark:text-orange-400',
+ archive: 'text-yellow-600 dark:text-yellow-400',
+ code: 'text-teal-600 dark:text-teal-400',
+ other: 'text-muted-foreground',
+};
+
+/**
+ * A colored tile with the file's extension.
+ */
+export function FileBadge({
+ file,
+ className,
+}: {
+ file: File;
+ className?: string;
+}) {
+ return (
+
+ {fileExtension(file.name).slice(0, 4) || 'file'}
+
+ );
+}
+
+function IconButton({
+ label,
+ className,
+ ...props
+}: React.ComponentProps<'button'> & { label: string }) {
+ return (
+
+ );
+}
+
+/**
+ * One file with its status, progress and actions (retry, cancel, remove).
+ */
+export function FileListItem({
+ fileState,
+ disabled,
+ className,
+ ...props
+}: React.ComponentProps<'li'> & {
+ fileState: FileState;
+ /** Hides the retry, cancel and remove actions. */
+ disabled?: boolean;
+}) {
+ const { removeFile, cancelUpload, uploadFiles } = useUploader();
+ const { file, key, status, progress, error } = fileState;
+
+ return (
+
+
+
+
+
+ {file.name}
+
+ {status === 'COMPLETE' && (
+
+
+ Uploaded
+
+ )}
+
+
+ {status === 'ERROR'
+ ? (error ?? 'Upload failed')
+ : status === 'UPLOADING'
+ ? `${formatFileSize((file.size * progress) / 100)} of ${formatFileSize(file.size)} · ${Math.round(progress)}%`
+ : formatFileSize(file.size)}
+
+
+ {/* Pinned to the bottom edge so the row keeps its height when the upload ends. */}
+ {status === 'UPLOADING' && (
+
+ )}
+ {!disabled && (
+
+ {status === 'ERROR' && (
+ void uploadFiles([key])}
+ >
+
+
+ )}
+ {status === 'UPLOADING' ? (
+ cancelUpload(key)}
+ >
+
+
+ ) : (
+ removeFile(key)}
+ >
+
+
+ )}
+
+ )}
+
+ );
+}
+
+/**
+ * Lists the files of the nearest `UploaderProvider`.
+ *
+ * @example
+ * ```tsx
+ *
+ * ```
+ */
+export function FileList({
+ disabled,
+ className,
+ ...props
+}: React.ComponentProps<'ul'> & {
+ /** Hides the retry, cancel and remove actions. */
+ disabled?: boolean;
+}) {
+ const { fileStates } = useUploader();
+ if (fileStates.length === 0) return null;
+
+ return (
+
+ {fileStates.map((fileState) => (
+
+ ))}
+
+ );
+}
diff --git a/docs/src/components/upload/multi-file.tsx b/docs/src/components/upload/multi-file.tsx
index 95adfe66..d622210b 100644
--- a/docs/src/components/upload/multi-file.tsx
+++ b/docs/src/components/upload/multi-file.tsx
@@ -2,201 +2,12 @@
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
-import { CheckIcon, RotateCwIcon, XIcon } from 'lucide-react';
import * as React from 'react';
import { type Accept } from 'react-dropzone';
import { Dropzone } from './dropzone';
-import { ProgressBar } from './progress-bar';
-import {
- fileExtension,
- fileKind,
- formatFileSize,
- type FileKind,
-} from './upload-utils';
-import { useUploader, type FileState } from './uploader-provider';
-
-const KIND_CLASSNAMES: Record = {
- image: 'text-purple-600 dark:text-purple-400',
- video: 'text-pink-600 dark:text-pink-400',
- audio: 'text-cyan-600 dark:text-cyan-400',
- pdf: 'text-red-600 dark:text-red-400',
- doc: 'text-blue-600 dark:text-blue-400',
- sheet: 'text-green-600 dark:text-green-400',
- slides: 'text-orange-600 dark:text-orange-400',
- archive: 'text-yellow-600 dark:text-yellow-400',
- code: 'text-teal-600 dark:text-teal-400',
- other: 'text-muted-foreground',
-};
-
-/**
- * A colored tile with the file's extension.
- */
-export function FileBadge({
- file,
- className,
-}: {
- file: File;
- className?: string;
-}) {
- return (
-
- {fileExtension(file.name).slice(0, 4) || 'file'}
-
- );
-}
-
-function IconButton({
- label,
- className,
- ...props
-}: React.ComponentProps<'button'> & { label: string }) {
- return (
-
- );
-}
-
-/**
- * One file with its status, progress and actions (retry, cancel, remove).
- */
-export function FileListItem({
- fileState,
- disabled,
- className,
- ...props
-}: React.ComponentProps<'li'> & {
- fileState: FileState;
- /** Hides the retry, cancel and remove actions. */
- disabled?: boolean;
-}) {
- const { removeFile, cancelUpload, uploadFiles } = useUploader();
- const { file, key, status, progress, error } = fileState;
-
- return (
-
-
-
-
-
- {file.name}
-
- {status === 'COMPLETE' && (
-
-
- Uploaded
-
- )}
-
-
- {status === 'ERROR'
- ? (error ?? 'Upload failed')
- : status === 'UPLOADING'
- ? `${formatFileSize((file.size * progress) / 100)} of ${formatFileSize(file.size)} · ${Math.round(progress)}%`
- : formatFileSize(file.size)}
-
-
- {/* Pinned to the bottom edge so the row keeps its height when the upload ends. */}
- {status === 'UPLOADING' && (
-
- )}
- {!disabled && (
-
- {status === 'ERROR' && (
- void uploadFiles([key])}
- >
-
-
- )}
- {status === 'UPLOADING' ? (
- cancelUpload(key)}
- >
-
-
- ) : (
- removeFile(key)}
- >
-
-
- )}
-
- )}
-
- );
-}
-
-/**
- * Lists the files of the nearest `UploaderProvider`.
- *
- * @example
- * ```tsx
- *
- * ```
- */
-export function FileList({
- disabled,
- className,
- ...props
-}: React.ComponentProps<'ul'> & {
- /** Hides the retry, cancel and remove actions. */
- disabled?: boolean;
-}) {
- const { fileStates } = useUploader();
- if (fileStates.length === 0) return null;
-
- return (
-
- {fileStates.map((fileState) => (
-
- ))}
-
- );
-}
+import { FileList } from './file-list';
+import { formatFileSize } from './upload-utils';
+import { useUploader } from './uploader-provider';
/**
* Props for the FileUploader component.
diff --git a/docs/src/hooks/use-reveal-anchor.ts b/docs/src/hooks/use-reveal-anchor.ts
new file mode 100644
index 00000000..44068cc2
--- /dev/null
+++ b/docs/src/hooks/use-reveal-anchor.ts
@@ -0,0 +1,70 @@
+'use client';
+
+import { useEffect, useEffectEvent, type RefObject } from 'react';
+import { flushSync } from 'react-dom';
+
+/**
+ * Calls `reveal` when the URL hash targets an element inside `container`, then
+ * scrolls to the target. Use it for content hidden behind collapsed sections or
+ * inactive tabs, so direct links and table of contents links still work.
+ */
+export function useRevealAnchor(
+ container: RefObject,
+ reveal: () => void,
+) {
+ const onReveal = useEffectEvent(reveal);
+
+ useEffect(() => {
+ function revealHash(hash: string) {
+ let id: string;
+ try {
+ id = decodeURIComponent(hash.slice(1));
+ } catch {
+ return;
+ }
+ const target = id ? document.getElementById(id) : null;
+ if (!target || !container.current?.contains(target)) return;
+ if (target.checkVisibility()) return;
+ flushSync(onReveal);
+ target.scrollIntoView({ block: 'start' });
+ }
+
+ function onHashChange() {
+ revealHash(window.location.hash);
+ }
+
+ // Clicking a link to the current hash does not fire `hashchange`.
+ function onClick(event: MouseEvent) {
+ if (
+ event.button !== 0 ||
+ event.metaKey ||
+ event.ctrlKey ||
+ event.shiftKey ||
+ event.altKey
+ )
+ return;
+ const link =
+ event.target instanceof Element ? event.target.closest('a') : null;
+ if (!link || link.target === '_blank' || link.hasAttribute('download'))
+ return;
+ const url = new URL(link.href, window.location.href);
+ if (
+ url.origin === window.location.origin &&
+ url.pathname === window.location.pathname &&
+ url.search === window.location.search
+ ) {
+ revealHash(url.hash);
+ }
+ }
+
+ // Defer the initial check so `flushSync` runs outside React's commit.
+ const timeout = setTimeout(onHashChange);
+ window.addEventListener('hashchange', onHashChange);
+ document.addEventListener('click', onClick, true);
+ return () => {
+ clearTimeout(timeout);
+ window.removeEventListener('hashchange', onHashChange);
+ document.removeEventListener('click', onClick, true);
+ };
+ }, [container]);
+}
diff --git a/docs/src/lib/constants.ts b/docs/src/lib/constants.ts
index 75bdd2d3..3384af2d 100644
--- a/docs/src/lib/constants.ts
+++ b/docs/src/lib/constants.ts
@@ -14,6 +14,6 @@ export const DOCS_ORIGIN = deployment.origin;
export const DOCS_GIT_REF = deployment.gitRef;
export const GITHUB_URL = `https://github.com/${GITHUB_OWNER}/${GITHUB_REPO}`;
export const SITE_URL = new URL('https://edgestore.dev');
-export const SPONSOR_URL = 'https://github.com/sponsors/perfectbase';
-export const YOUTUBE_URL = 'https://youtube.com/@perfectbase';
+export const SPONSOR_URL = 'https://github.com/sponsors/raviships';
+export const YOUTUBE_URL = 'https://youtube.com/@ravi_ships';
export const X_URL = 'https://x.com/edgestorejs';
diff --git a/docs/src/lib/testimonials.ts b/docs/src/lib/testimonials.ts
index 084caf81..fee17da4 100644
--- a/docs/src/lib/testimonials.ts
+++ b/docs/src/lib/testimonials.ts
@@ -19,7 +19,7 @@ export const testimonials = [
user: '@sathishkannan6600',
image: '/img/testimonials/sathishkannan6600.jpg',
comment:
- 'Unbelievable and exhaustive features.Edge store thought about all the use cases. Also, not using a database for protected files is a nice idea. Very clear explanation in the video.',
+ 'Unbelievable and exhaustive features.EdgeStore thought about all the use cases. Also, not using a database for protected files is a nice idea. Very clear explanation in the video.',
platform: 'youtube',
url: 'https://www.youtube.com/watch?v=Acq9UEA2akU&lc=Ugw4ne4z1Pj3NS_MGbB4AaABAg',
},
@@ -35,7 +35,7 @@ export const testimonials = [
user: '@PhilippeKhin',
image: '/img/testimonials/PhilippeKhin.jpg',
comment:
- "Feeling that Edge Store will take off 🚀 Great stuff you're building here Ravi 👍",
+ "Feeling that EdgeStore will take off 🚀 Great stuff you're building here Ravi 👍",
platform: 'youtube',
url: 'https://www.youtube.com/watch?v=Acq9UEA2akU&lc=UgyEH4ERhW0fXigeWN14AaABAg',
},
@@ -82,7 +82,7 @@ export const testimonials = [
user: '@developerpranav',
image: '/img/testimonials/developerpranav.jpg',
comment:
- '🤯 Blown away by the simplicity of defining the types of asset uploaded, which then determines the file path. Awesome video, and amazing job on Edge Store btw! Highly considering it for my current project! Just one question, can I use my own S3 Bucket? Specifically, I use Cloudflare R2 which has compatibility with the S3 API.',
+ '🤯 Blown away by the simplicity of defining the types of asset uploaded, which then determines the file path. Awesome video, and amazing job on EdgeStore btw! Highly considering it for my current project! Just one question, can I use my own S3 Bucket? Specifically, I use Cloudflare R2 which has compatibility with the S3 API.',
platform: 'youtube',
url: 'https://www.youtube.com/watch?v=Acq9UEA2akU&lc=UgxL7xpOk8ygYV7iYgx4AaABAg',
},
@@ -141,7 +141,7 @@ export const testimonials = [
user: '@alijansoomro4277',
image: '/img/testimonials/alijansoomro4277.jpg',
comment:
- 'This service looks easier to use than UploadThing — I was looking for a better way to upload files in Next-JS, and I like Edge Store.',
+ 'This service looks easier to use than UploadThing — I was looking for a better way to upload files in Next-JS, and I like EdgeStore.',
platform: 'youtube',
url: 'https://www.youtube.com/watch?v=Acq9UEA2akU&lc=Ugw9Jvy13TVCEXCvftR4AaABAg',
},
diff --git a/docs/src/scripts/download-images.ts b/docs/src/scripts/download-images.ts
index 411e0f1c..4add6005 100644
--- a/docs/src/scripts/download-images.ts
+++ b/docs/src/scripts/download-images.ts
@@ -21,14 +21,14 @@ const testimonials = [
image:
'https://yt3.ggpht.com/ytc/AIdro_nzjrEGEW1ljvq0slQBOeXcZwQqHlmFzyPXXTdRQf6ZP8E=s88-c-k-c0x00ffffff-no-rj',
comment:
- 'Unbelievable and exhaustive features.Edge store thought about all the use cases. Also, not using a database for protected files is a nice idea. Very clear explanation in the video.',
+ 'Unbelievable and exhaustive features.EdgeStore thought about all the use cases. Also, not using a database for protected files is a nice idea. Very clear explanation in the video.',
},
{
user: '@PhilippeKhin',
image:
'https://yt3.ggpht.com/ytc/AIdro_noIo8kfGBJIlJ3OqosAAIx0Wmce06n5_N-OYSxM5AhvGI=s88-c-k-c0x00ffffff-no-rj',
comment:
- "Feeling that Edge Store will take off 🚀 Great stuff you're building here Ravi 👍",
+ "Feeling that EdgeStore will take off 🚀 Great stuff you're building here Ravi 👍",
},
{
user: '@IyanSR',
@@ -55,7 +55,7 @@ const testimonials = [
image:
'https://yt3.ggpht.com/ytc/AIdro_kA5_GhiyHqNvdgi44X2S1x2fkUP98mX--QS0B_N9xNGPs=s88-c-k-c0x00ffffff-no-rj',
comment:
- '🤯 Blown away by the simplicity of defining the types of asset uploaded, which then determines the file path. Awesome video, and amazing job on Edge Store btw! Highly considering it for my current project! Just one question, can I use my own S3 Bucket? Specifically, I use Cloudflare R2 which has compatibility with the S3 API.',
+ '🤯 Blown away by the simplicity of defining the types of asset uploaded, which then determines the file path. Awesome video, and amazing job on EdgeStore btw! Highly considering it for my current project! Just one question, can I use my own S3 Bucket? Specifically, I use Cloudflare R2 which has compatibility with the S3 API.',
},
{
user: '@ryanpp27',
@@ -106,13 +106,13 @@ const testimonials = [
image:
'https://yt3.ggpht.com/ytc/AIdro_lBj2_SaydLARaf_VD4cxIDjF_cmHeL_5YSGeFUIfycc9w=s88-c-k-c0x00ffffff-no-rj',
comment:
- 'This service looks easier to use than UploadThing — I was looking for a better way to upload files in Next-JS, and I like Edge Store.',
+ 'This service looks easier to use than UploadThing — I was looking for a better way to upload files in Next-JS, and I like EdgeStore.',
},
{
user: '@hikmatullah2131',
image:
'https://yt3.ggpht.com/NLFF28hZDwFf8SnxYbPyiTb9Gzg8jxa3mfC_4OYmo2gOuHmyuVTXWc9XMHgaJQAsoeBPQkXz4g=s88-c-k-c0x00ffffff-no-rj',
- comment: 'You covered a lot in a short time, and I love Edge Store too.',
+ comment: 'You covered a lot in a short time, and I love EdgeStore too.',
},
];
diff --git a/examples/basic-access-control/package.json b/examples/basic-access-control/package.json
index 1f1636d5..10372e45 100644
--- a/examples/basic-access-control/package.json
+++ b/examples/basic-access-control/package.json
@@ -11,7 +11,7 @@
"dependencies": {
"@edgestore/react": "^1.0.0",
"@edgestore/server": "^1.0.0",
- "next": "16.2.10",
+ "next": "16.4.1",
"react": "19.2.7",
"react-dom": "19.2.7",
"zod": "3.25.76"
diff --git a/examples/components/package.json b/examples/components/package.json
index b459eb81..4f553cc9 100644
--- a/examples/components/package.json
+++ b/examples/components/package.json
@@ -20,7 +20,7 @@
"class-variance-authority": "0.7.1",
"clsx": "1.2.1",
"lucide-react": "0.487.0",
- "next": "16.2.10",
+ "next": "16.4.1",
"next-themes": "0.2.1",
"postcss": "8.4.21",
"react": "19.2.7",
diff --git a/examples/components/src/app/(tabs)/buttons/page.tsx b/examples/components/src/app/(tabs)/buttons/page.tsx
index 26aaea79..705cbc71 100644
--- a/examples/components/src/app/(tabs)/buttons/page.tsx
+++ b/examples/components/src/app/(tabs)/buttons/page.tsx
@@ -2,7 +2,7 @@
import { ExampleFrame } from '@/components/ui/example-frame';
import { UploadErrors } from '@/components/upload/dropzone';
-import { FileList } from '@/components/upload/multi-file';
+import { FileList } from '@/components/upload/file-list';
import { UploadButton } from '@/components/upload/upload-button';
import { SPREADSHEET_ACCEPT } from '@/components/upload/upload-utils';
import {
diff --git a/examples/components/src/components/upload/blocks/progress-bar-block.tsx b/examples/components/src/components/upload/blocks/progress-bar-block.tsx
index d50865f6..9671435e 100644
--- a/examples/components/src/components/upload/blocks/progress-bar-block.tsx
+++ b/examples/components/src/components/upload/blocks/progress-bar-block.tsx
@@ -1,7 +1,7 @@
'use client';
+import { ProgressBar } from '@/components/upload/progress-bar';
import * as React from 'react';
-import { ProgressBar } from '../progress-bar';
export default function ProgressBarUsage() {
const [progress, setProgress] = React.useState(0);
diff --git a/examples/components/src/components/upload/blocks/progress-circle-block.tsx b/examples/components/src/components/upload/blocks/progress-circle-block.tsx
index c93aeecd..e25989b7 100644
--- a/examples/components/src/components/upload/blocks/progress-circle-block.tsx
+++ b/examples/components/src/components/upload/blocks/progress-circle-block.tsx
@@ -1,7 +1,7 @@
'use client';
+import { ProgressCircle } from '@/components/upload/progress-circle';
import * as React from 'react';
-import { ProgressCircle } from '../progress-circle';
export default function ProgressCircleUsage() {
const [progress, setProgress] = React.useState(0);
diff --git a/examples/components/src/components/upload/blocks/upload-button-block.tsx b/examples/components/src/components/upload/blocks/upload-button-block.tsx
index 2a4406a6..5f2df2f2 100644
--- a/examples/components/src/components/upload/blocks/upload-button-block.tsx
+++ b/examples/components/src/components/upload/blocks/upload-button-block.tsx
@@ -1,7 +1,7 @@
'use client';
import { UploadErrors } from '@/components/upload/dropzone';
-import { FileList } from '@/components/upload/multi-file';
+import { FileList } from '@/components/upload/file-list';
import { UploadButton } from '@/components/upload/upload-button';
import {
UploaderProvider,
diff --git a/examples/components/src/components/upload/file-field.tsx b/examples/components/src/components/upload/file-field.tsx
index a4393bc7..a46adfb5 100644
--- a/examples/components/src/components/upload/file-field.tsx
+++ b/examples/components/src/components/upload/file-field.tsx
@@ -5,7 +5,7 @@ import { UploadIcon } from 'lucide-react';
import * as React from 'react';
import { type Accept } from 'react-dropzone';
import { dropzoneState, dropzoneVariants, useUploadDropzone } from './dropzone';
-import { FileListItem } from './multi-file';
+import { FileListItem } from './file-list';
import { formatFileSize } from './upload-utils';
import { useUploader } from './uploader-provider';
diff --git a/examples/components/src/components/upload/file-list.tsx b/examples/components/src/components/upload/file-list.tsx
new file mode 100644
index 00000000..6e980be1
--- /dev/null
+++ b/examples/components/src/components/upload/file-list.tsx
@@ -0,0 +1,196 @@
+'use client';
+
+import { cn } from '@/lib/utils';
+import { CheckIcon, RotateCwIcon, XIcon } from 'lucide-react';
+import * as React from 'react';
+import { ProgressBar } from './progress-bar';
+import {
+ fileExtension,
+ fileKind,
+ formatFileSize,
+ type FileKind,
+} from './upload-utils';
+import { useUploader, type FileState } from './uploader-provider';
+
+const KIND_CLASSNAMES: Record = {
+ image: 'text-purple-600 dark:text-purple-400',
+ video: 'text-pink-600 dark:text-pink-400',
+ audio: 'text-cyan-600 dark:text-cyan-400',
+ pdf: 'text-red-600 dark:text-red-400',
+ doc: 'text-blue-600 dark:text-blue-400',
+ sheet: 'text-green-600 dark:text-green-400',
+ slides: 'text-orange-600 dark:text-orange-400',
+ archive: 'text-yellow-600 dark:text-yellow-400',
+ code: 'text-teal-600 dark:text-teal-400',
+ other: 'text-muted-foreground',
+};
+
+/**
+ * A colored tile with the file's extension.
+ */
+export function FileBadge({
+ file,
+ className,
+}: {
+ file: File;
+ className?: string;
+}) {
+ return (
+
+ {fileExtension(file.name).slice(0, 4) || 'file'}
+
+ );
+}
+
+function IconButton({
+ label,
+ className,
+ ...props
+}: React.ComponentProps<'button'> & { label: string }) {
+ return (
+
+ );
+}
+
+/**
+ * One file with its status, progress and actions (retry, cancel, remove).
+ */
+export function FileListItem({
+ fileState,
+ disabled,
+ className,
+ ...props
+}: React.ComponentProps<'li'> & {
+ fileState: FileState;
+ /** Hides the retry, cancel and remove actions. */
+ disabled?: boolean;
+}) {
+ const { removeFile, cancelUpload, uploadFiles } = useUploader();
+ const { file, key, status, progress, error } = fileState;
+
+ return (
+
+
+
+
+
+ {file.name}
+
+ {status === 'COMPLETE' && (
+
+
+ Uploaded
+
+ )}
+
+
+ {status === 'ERROR'
+ ? (error ?? 'Upload failed')
+ : status === 'UPLOADING'
+ ? `${formatFileSize((file.size * progress) / 100)} of ${formatFileSize(file.size)} · ${Math.round(progress)}%`
+ : formatFileSize(file.size)}
+
+
+ {/* Pinned to the bottom edge so the row keeps its height when the upload ends. */}
+ {status === 'UPLOADING' && (
+
+ )}
+ {!disabled && (
+
+ {status === 'ERROR' && (
+ void uploadFiles([key])}
+ >
+
+
+ )}
+ {status === 'UPLOADING' ? (
+ cancelUpload(key)}
+ >
+
+
+ ) : (
+ removeFile(key)}
+ >
+
+
+ )}
+
+ )}
+
+ );
+}
+
+/**
+ * Lists the files of the nearest `UploaderProvider`.
+ *
+ * @example
+ * ```tsx
+ *
+ * ```
+ */
+export function FileList({
+ disabled,
+ className,
+ ...props
+}: React.ComponentProps<'ul'> & {
+ /** Hides the retry, cancel and remove actions. */
+ disabled?: boolean;
+}) {
+ const { fileStates } = useUploader();
+ if (fileStates.length === 0) return null;
+
+ return (
+
+ {fileStates.map((fileState) => (
+
+ ))}
+
+ );
+}
diff --git a/examples/components/src/components/upload/multi-file.tsx b/examples/components/src/components/upload/multi-file.tsx
index 95adfe66..d622210b 100644
--- a/examples/components/src/components/upload/multi-file.tsx
+++ b/examples/components/src/components/upload/multi-file.tsx
@@ -2,201 +2,12 @@
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
-import { CheckIcon, RotateCwIcon, XIcon } from 'lucide-react';
import * as React from 'react';
import { type Accept } from 'react-dropzone';
import { Dropzone } from './dropzone';
-import { ProgressBar } from './progress-bar';
-import {
- fileExtension,
- fileKind,
- formatFileSize,
- type FileKind,
-} from './upload-utils';
-import { useUploader, type FileState } from './uploader-provider';
-
-const KIND_CLASSNAMES: Record = {
- image: 'text-purple-600 dark:text-purple-400',
- video: 'text-pink-600 dark:text-pink-400',
- audio: 'text-cyan-600 dark:text-cyan-400',
- pdf: 'text-red-600 dark:text-red-400',
- doc: 'text-blue-600 dark:text-blue-400',
- sheet: 'text-green-600 dark:text-green-400',
- slides: 'text-orange-600 dark:text-orange-400',
- archive: 'text-yellow-600 dark:text-yellow-400',
- code: 'text-teal-600 dark:text-teal-400',
- other: 'text-muted-foreground',
-};
-
-/**
- * A colored tile with the file's extension.
- */
-export function FileBadge({
- file,
- className,
-}: {
- file: File;
- className?: string;
-}) {
- return (
-
- {fileExtension(file.name).slice(0, 4) || 'file'}
-
- );
-}
-
-function IconButton({
- label,
- className,
- ...props
-}: React.ComponentProps<'button'> & { label: string }) {
- return (
-
- );
-}
-
-/**
- * One file with its status, progress and actions (retry, cancel, remove).
- */
-export function FileListItem({
- fileState,
- disabled,
- className,
- ...props
-}: React.ComponentProps<'li'> & {
- fileState: FileState;
- /** Hides the retry, cancel and remove actions. */
- disabled?: boolean;
-}) {
- const { removeFile, cancelUpload, uploadFiles } = useUploader();
- const { file, key, status, progress, error } = fileState;
-
- return (
-
-
-
-
-
- {file.name}
-
- {status === 'COMPLETE' && (
-
-
- Uploaded
-
- )}
-
-
- {status === 'ERROR'
- ? (error ?? 'Upload failed')
- : status === 'UPLOADING'
- ? `${formatFileSize((file.size * progress) / 100)} of ${formatFileSize(file.size)} · ${Math.round(progress)}%`
- : formatFileSize(file.size)}
-
-
- {/* Pinned to the bottom edge so the row keeps its height when the upload ends. */}
- {status === 'UPLOADING' && (
-
- )}
- {!disabled && (
-
- {status === 'ERROR' && (
- void uploadFiles([key])}
- >
-
-
- )}
- {status === 'UPLOADING' ? (
- cancelUpload(key)}
- >
-
-
- ) : (
- removeFile(key)}
- >
-
-
- )}
-
- )}
-
- );
-}
-
-/**
- * Lists the files of the nearest `UploaderProvider`.
- *
- * @example
- * ```tsx
- *
- * ```
- */
-export function FileList({
- disabled,
- className,
- ...props
-}: React.ComponentProps<'ul'> & {
- /** Hides the retry, cancel and remove actions. */
- disabled?: boolean;
-}) {
- const { fileStates } = useUploader();
- if (fileStates.length === 0) return null;
-
- return (
-
- {fileStates.map((fileState) => (
-
- ))}
-
- );
-}
+import { FileList } from './file-list';
+import { formatFileSize } from './upload-utils';
+import { useUploader } from './uploader-provider';
/**
* Props for the FileUploader component.
diff --git a/examples/next-advanced/package.json b/examples/next-advanced/package.json
index 42d1676e..7ad4e044 100644
--- a/examples/next-advanced/package.json
+++ b/examples/next-advanced/package.json
@@ -11,7 +11,7 @@
"dependencies": {
"@edgestore/react": "^1.0.0",
"@edgestore/server": "^1.0.0",
- "next": "16.2.10",
+ "next": "16.4.1",
"react": "19.2.7",
"react-dom": "19.2.7",
"zod": "3.25.76"
diff --git a/examples/next-basic-aws/package.json b/examples/next-basic-aws/package.json
index 0de523c5..994399cd 100644
--- a/examples/next-basic-aws/package.json
+++ b/examples/next-basic-aws/package.json
@@ -14,7 +14,7 @@
"@aws-sdk/s3-request-presigner": "3.1091.0",
"@edgestore/react": "^1.0.0",
"@edgestore/server": "^1.0.0",
- "next": "16.2.10",
+ "next": "16.4.1",
"react": "19.2.7",
"react-dom": "19.2.7",
"zod": "3.25.76"
diff --git a/examples/next-basic-with-intl/package.json b/examples/next-basic-with-intl/package.json
index 4e9c367a..7ce5699a 100644
--- a/examples/next-basic-with-intl/package.json
+++ b/examples/next-basic-with-intl/package.json
@@ -11,7 +11,7 @@
"dependencies": {
"@edgestore/react": "^1.0.0",
"@edgestore/server": "^1.0.0",
- "next": "16.2.10",
+ "next": "16.4.1",
"next-intl": "4.13.3",
"react": "19.2.7",
"react-dom": "19.2.7",
diff --git a/examples/next-basic/package.json b/examples/next-basic/package.json
index cc045f0d..225d33ab 100644
--- a/examples/next-basic/package.json
+++ b/examples/next-basic/package.json
@@ -11,7 +11,7 @@
"dependencies": {
"@edgestore/react": "^1.0.0",
"@edgestore/server": "^1.0.0",
- "next": "16.2.10",
+ "next": "16.4.1",
"react": "19.2.7",
"react-dom": "19.2.7",
"zod": "3.25.76"
diff --git a/examples/next-complete/package.json b/examples/next-complete/package.json
index a1ae3905..d333388f 100644
--- a/examples/next-complete/package.json
+++ b/examples/next-complete/package.json
@@ -12,7 +12,7 @@
"@edgestore/react": "^1.0.0",
"@edgestore/sdk": "^1.0.0",
"@edgestore/server": "^1.0.0",
- "next": "16.2.10",
+ "next": "16.4.1",
"react": "19.2.7",
"react-dom": "19.2.7",
"zod": "3.25.76"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 14bacf16..3216716e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -46,8 +46,8 @@ catalogs:
specifier: 4.12.31
version: 4.12.31
next:
- specifier: 16.2.10
- version: 16.2.10
+ specifier: 16.4.1
+ version: 16.4.1
react:
specifier: 19.2.7
version: 19.2.7
@@ -145,7 +145,7 @@ importers:
version: 9.0.1(rollup@4.62.2)(vite@8.1.5(@types/node@25.0.3)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))
rollup-plugin-swc3:
specifier: 0.12.1
- version: 0.12.1(@swc/core@1.15.46)(rollup@4.62.2)
+ version: 0.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(rollup@4.62.2)
shadcn:
specifier: 4.21.0
version: 4.21.0(supports-color@9.4.0)(typescript@6.0.3)
@@ -184,7 +184,7 @@ importers:
version: link:../packages/server
'@fumadocs/mdx-remote':
specifier: 1.4.4
- version: 1.4.4(@types/react@19.2.17)(fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76))(react@19.2.7)(supports-color@9.4.0)
+ version: 1.4.4(@types/react@19.2.17)(fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76))(react@19.2.7)(supports-color@9.4.0)
'@langfuse/otel':
specifier: 5.10.1
version: 5.10.1(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1))(@opentelemetry/exporter-trace-otlp-http@0.221.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.10.0(@opentelemetry/api@1.9.1))
@@ -226,16 +226,16 @@ importers:
version: 2.1.1
fumadocs-core:
specifier: 16.4.6
- version: 16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76)
+ version: 16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76)
fumadocs-mdx:
specifier: 14.2.4
- version: 14.2.4(18ab8919947fad7e1a46c05e2f7eb114)
+ version: 14.2.4(7ef7f3fe088cf3dbc6b7b28a4923ccff)
fumadocs-twoslash:
specifier: 3.1.12
- version: 3.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(fumadocs-ui@16.4.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(tailwindcss@4.3.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(typescript@6.0.3)
+ version: 3.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(fumadocs-ui@16.4.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(tailwindcss@4.3.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(typescript@6.0.3)
fumadocs-ui:
specifier: 16.4.6
- version: 16.4.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(tailwindcss@4.3.3)
+ version: 16.4.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(tailwindcss@4.3.3)
hast-util-to-jsx-runtime:
specifier: 2.3.6
version: 2.3.6(supports-color@9.4.0)
@@ -247,7 +247,7 @@ importers:
version: 12.42.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
next:
specifier: 'catalog:'
- version: 16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
+ version: 16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
next-themes:
specifier: 0.4.6
version: 0.4.6(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
@@ -362,8 +362,8 @@ importers:
specifier: workspace:*
version: link:../../packages/server
next:
- specifier: 16.2.10
- version: 16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
+ specifier: 16.4.1
+ version: 16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
react:
specifier: 19.2.7
version: 19.2.7
@@ -423,11 +423,11 @@ importers:
specifier: 0.487.0
version: 0.487.0(react@19.2.7)
next:
- specifier: 16.2.10
- version: 16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
+ specifier: 16.4.1
+ version: 16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
next-themes:
specifier: 0.2.1
- version: 0.2.1(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
+ version: 0.2.1(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
postcss:
specifier: 8.4.21
version: 8.4.21
@@ -568,8 +568,8 @@ importers:
specifier: workspace:*
version: link:../../packages/server
next:
- specifier: 16.2.10
- version: 16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
+ specifier: 16.4.1
+ version: 16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
react:
specifier: 19.2.7
version: 19.2.7
@@ -602,8 +602,8 @@ importers:
specifier: workspace:*
version: link:../../packages/server
next:
- specifier: 16.2.10
- version: 16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
+ specifier: 16.4.1
+ version: 16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
react:
specifier: 19.2.7
version: 19.2.7
@@ -642,8 +642,8 @@ importers:
specifier: workspace:*
version: link:../../packages/server
next:
- specifier: 16.2.10
- version: 16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
+ specifier: 16.4.1
+ version: 16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
react:
specifier: 19.2.7
version: 19.2.7
@@ -676,11 +676,11 @@ importers:
specifier: workspace:*
version: link:../../packages/server
next:
- specifier: 16.2.10
- version: 16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
+ specifier: 16.4.1
+ version: 16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
next-intl:
specifier: 4.13.3
- version: 4.13.3(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(typescript@6.0.3)
+ version: 4.13.3(@swc/helpers@0.5.23)(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(typescript@6.0.3)
react:
specifier: 19.2.7
version: 19.2.7
@@ -716,8 +716,8 @@ importers:
specifier: workspace:*
version: link:../../packages/server
next:
- specifier: 16.2.10
- version: 16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
+ specifier: 16.4.1
+ version: 16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
react:
specifier: 19.2.7
version: 19.2.7
@@ -948,7 +948,7 @@ importers:
version: 29.1.1
next:
specifier: 'catalog:'
- version: 16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
+ version: 16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
react:
specifier: 'catalog:'
version: 19.2.7
@@ -1022,7 +1022,7 @@ importers:
version: 25.0.3
astro:
specifier: 'catalog:'
- version: 7.1.3(@azure/storage-blob@12.33.0(supports-color@9.4.0))(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)(@types/node@25.0.3)(db0@0.3.4)(jiti@2.7.0)(rollup@4.62.2)(tsx@4.23.1)(yaml@2.9.0)
+ version: 7.1.3(@azure/storage-blob@12.33.0(supports-color@9.4.0))(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.3)(@types/node@25.0.3)(db0@0.3.4)(jiti@2.7.0)(rollup@4.62.2)(tsx@4.23.1)(yaml@2.9.0)
dotenv:
specifier: 17.4.2
version: 17.4.2
@@ -1037,7 +1037,7 @@ importers:
version: 4.12.31
next:
specifier: 'catalog:'
- version: 16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
+ version: 16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
react:
specifier: 'catalog:'
version: 19.2.7
@@ -1725,6 +1725,9 @@ packages:
'@emnapi/runtime@1.11.2':
resolution: {integrity: sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==}
+ '@emnapi/runtime@1.11.3':
+ resolution: {integrity: sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==}
+
'@emnapi/wasi-threads@1.2.2':
resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==}
@@ -2425,22 +2428,16 @@ packages:
resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==}
engines: {node: '>=18'}
- '@img/sharp-darwin-arm64@0.34.5':
- resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [arm64]
- os: [darwin]
-
'@img/sharp-darwin-arm64@0.35.3':
resolution: {integrity: sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==}
engines: {node: '>=20.9.0'}
cpu: [arm64]
os: [darwin]
- '@img/sharp-darwin-x64@0.34.5':
- resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [x64]
+ '@img/sharp-darwin-arm64@0.35.5':
+ resolution: {integrity: sha512-QRUlFQ0WxvdWyqqG/WtI3iupfD5rBzmCHXSdPsY91sAtVtTo7Q4cb6zOccZ3gqEqkr0f1As1ehLqmEpDsRf+lg==}
+ engines: {node: '>=20.9.0'}
+ cpu: [arm64]
os: [darwin]
'@img/sharp-darwin-x64@0.35.3':
@@ -2449,24 +2446,30 @@ packages:
cpu: [x64]
os: [darwin]
+ '@img/sharp-darwin-x64@0.35.5':
+ resolution: {integrity: sha512-+BR255RhDlpygUpOc/Jdt1nT6DQ3XG/ERo5wbcdOf5Q320dKtPCKPLR1LJs9VGXRaMa8l1uUa0tkCNOXiAxZUw==}
+ engines: {node: '>=20.9.0'}
+ cpu: [x64]
+ os: [darwin]
+
'@img/sharp-freebsd-wasm32@0.35.3':
resolution: {integrity: sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==}
engines: {node: '>=20.9.0'}
os: [freebsd]
- '@img/sharp-libvips-darwin-arm64@1.2.4':
- resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==}
- cpu: [arm64]
- os: [darwin]
+ '@img/sharp-freebsd-wasm32@0.35.5':
+ resolution: {integrity: sha512-Y/z91nEZ4uIBX5X3nfTovjU9lHNKFYbL2lpHCLVNmXQK03VIZvXBBt0KxbPGp2SdGSF+2mQU4e+hQaWOt86iAw==}
+ engines: {node: '>=20.9.0'}
+ os: [freebsd]
'@img/sharp-libvips-darwin-arm64@1.3.2':
resolution: {integrity: sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==}
cpu: [arm64]
os: [darwin]
- '@img/sharp-libvips-darwin-x64@1.2.4':
- resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==}
- cpu: [x64]
+ '@img/sharp-libvips-darwin-arm64@1.3.4':
+ resolution: {integrity: sha512-5R89nBYiRdUlSWJxPhO+GVtaXzXSxKnRu/xqMn3KTA3L9EB9Oy/P+Nn2f2vlhPuUdy/Zusb2DarbyTpGCfEDuw==}
+ cpu: [arm64]
os: [darwin]
'@img/sharp-libvips-darwin-x64@1.3.2':
@@ -2474,11 +2477,10 @@ packages:
cpu: [x64]
os: [darwin]
- '@img/sharp-libvips-linux-arm64@1.2.4':
- resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==}
- cpu: [arm64]
- os: [linux]
- libc: [glibc]
+ '@img/sharp-libvips-darwin-x64@1.3.4':
+ resolution: {integrity: sha512-iR2OKH80yi0U+dUplyh3/xdpFvps6YkCwsXenIJxqxR1v9o+xtKTGbS9H7cps+2Vxjc8B1j96p75NmTGjIhtpQ==}
+ cpu: [x64]
+ os: [darwin]
'@img/sharp-libvips-linux-arm64@1.3.2':
resolution: {integrity: sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==}
@@ -2486,9 +2488,9 @@ packages:
os: [linux]
libc: [glibc]
- '@img/sharp-libvips-linux-arm@1.2.4':
- resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==}
- cpu: [arm]
+ '@img/sharp-libvips-linux-arm64@1.3.4':
+ resolution: {integrity: sha512-Y3dgX/6lE2QhQb+Gxy0WZxfg9MEm/JBjamZpS2IklP7xIQoKN4hzAm7KcMVGtaVDt3neE9OKBC7vAfonA/Lr1A==}
+ cpu: [arm64]
os: [linux]
libc: [glibc]
@@ -2498,9 +2500,9 @@ packages:
os: [linux]
libc: [glibc]
- '@img/sharp-libvips-linux-ppc64@1.2.4':
- resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==}
- cpu: [ppc64]
+ '@img/sharp-libvips-linux-arm@1.3.4':
+ resolution: {integrity: sha512-LmRtTsOHuvM2+wlO2Db37dx5MiZhB0FvSunciw48YjdOkZz9KAiRbm8ujeMOA1INqmei5NapFxYEK1D1ZSidmw==}
+ cpu: [arm]
os: [linux]
libc: [glibc]
@@ -2510,9 +2512,9 @@ packages:
os: [linux]
libc: [glibc]
- '@img/sharp-libvips-linux-riscv64@1.2.4':
- resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==}
- cpu: [riscv64]
+ '@img/sharp-libvips-linux-ppc64@1.3.4':
+ resolution: {integrity: sha512-Le6boB8Tai0Nis+gIxIpKx68UDVVIqdR8Tin5Yf1z2LJJQLDJvCDRqRu+jC2qCoD+eIomonmOwB4smBRxfVpYQ==}
+ cpu: [ppc64]
os: [linux]
libc: [glibc]
@@ -2522,9 +2524,9 @@ packages:
os: [linux]
libc: [glibc]
- '@img/sharp-libvips-linux-s390x@1.2.4':
- resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==}
- cpu: [s390x]
+ '@img/sharp-libvips-linux-riscv64@1.3.4':
+ resolution: {integrity: sha512-aHkkIEHPRdQEegJN20MLmGtxYD9R2wQr3Cwpddnu5+YKMt6Uzax7S9h5gpZTo8wyrGuZSlfQ63OevL5mTyOC7Q==}
+ cpu: [riscv64]
os: [linux]
libc: [glibc]
@@ -2534,9 +2536,9 @@ packages:
os: [linux]
libc: [glibc]
- '@img/sharp-libvips-linux-x64@1.2.4':
- resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==}
- cpu: [x64]
+ '@img/sharp-libvips-linux-s390x@1.3.4':
+ resolution: {integrity: sha512-ra/mB6MikESDUO7Yg+Mi95bFBb9GsObURuhnOv3OqknjGe9sZrG8tCe9q0xSIGrtLgvgw0gKnFWcK4blSgQOuQ==}
+ cpu: [s390x]
os: [linux]
libc: [glibc]
@@ -2546,11 +2548,11 @@ packages:
os: [linux]
libc: [glibc]
- '@img/sharp-libvips-linuxmusl-arm64@1.2.4':
- resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==}
- cpu: [arm64]
+ '@img/sharp-libvips-linux-x64@1.3.4':
+ resolution: {integrity: sha512-GJ//SSXbnwSDes02umB3nDJLFcQzw8a18V8fyhqr6tV515tOEMdImjjxj1AoafMRz56F3PHgftnj1QEKSU1zkw==}
+ cpu: [x64]
os: [linux]
- libc: [musl]
+ libc: [glibc]
'@img/sharp-libvips-linuxmusl-arm64@1.3.2':
resolution: {integrity: sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==}
@@ -2558,9 +2560,9 @@ packages:
os: [linux]
libc: [musl]
- '@img/sharp-libvips-linuxmusl-x64@1.2.4':
- resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==}
- cpu: [x64]
+ '@img/sharp-libvips-linuxmusl-arm64@1.3.4':
+ resolution: {integrity: sha512-hvulFwtjUcagsis6BBxHwGFwWoNZjgYmULGVrZcyfNbjA8hKILbRxGg15/7w5HDyXHXUos/j6baAWqnCyQ2DWA==}
+ cpu: [arm64]
os: [linux]
libc: [musl]
@@ -2570,12 +2572,11 @@ packages:
os: [linux]
libc: [musl]
- '@img/sharp-linux-arm64@0.34.5':
- resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [arm64]
+ '@img/sharp-libvips-linuxmusl-x64@1.3.4':
+ resolution: {integrity: sha512-6zXKeE/p39I1AmA3cJG35eyBGNqNddLnUXjhwBnsGjFPWqf5VKkDBEqaEkPDoTEtkxwi2vv8Tcr2mDyP4So7Fg==}
+ cpu: [x64]
os: [linux]
- libc: [glibc]
+ libc: [musl]
'@img/sharp-linux-arm64@0.35.3':
resolution: {integrity: sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==}
@@ -2584,10 +2585,10 @@ packages:
os: [linux]
libc: [glibc]
- '@img/sharp-linux-arm@0.34.5':
- resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [arm]
+ '@img/sharp-linux-arm64@0.35.5':
+ resolution: {integrity: sha512-LYVx5JTsOM2CBzmxreh+nl64/3H6Xb09iSLknqH47z2T2DFFxDeFLP5y4dJwe6H7uGQlHPyEEtIqyo3DYsRwdQ==}
+ engines: {node: '>=20.9.0'}
+ cpu: [arm64]
os: [linux]
libc: [glibc]
@@ -2598,10 +2599,10 @@ packages:
os: [linux]
libc: [glibc]
- '@img/sharp-linux-ppc64@0.34.5':
- resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [ppc64]
+ '@img/sharp-linux-arm@0.35.5':
+ resolution: {integrity: sha512-LEaXK2WdXVK5ykcw0buWyPMsmLLL2vpHLD6yrNSW+JGEL3BZPA4tpKN6iaMc4AxTTAoaX/sU1rOL51lcIz48ZQ==}
+ engines: {node: '>=20.9.0'}
+ cpu: [arm]
os: [linux]
libc: [glibc]
@@ -2612,10 +2613,10 @@ packages:
os: [linux]
libc: [glibc]
- '@img/sharp-linux-riscv64@0.34.5':
- resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [riscv64]
+ '@img/sharp-linux-ppc64@0.35.5':
+ resolution: {integrity: sha512-QVxAAq8evVRI9ia2vqgwrmWucn5Dfv+JdWzj75pD8omHLPSP7f8p20O8jxzjCcuCEQEOtYOZUmX1hkiZ0kdevA==}
+ engines: {node: '>=20.9.0'}
+ cpu: [ppc64]
os: [linux]
libc: [glibc]
@@ -2626,10 +2627,10 @@ packages:
os: [linux]
libc: [glibc]
- '@img/sharp-linux-s390x@0.34.5':
- resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [s390x]
+ '@img/sharp-linux-riscv64@0.35.5':
+ resolution: {integrity: sha512-LtdreXguaavKODPIfzJ4kffx7UNt1omwtK0rch4EBbbSTXPnxWmYSayXdLJw0fJzQ97kHt1gL/yh4tvU+nCyRQ==}
+ engines: {node: '>=20.9.0'}
+ cpu: [riscv64]
os: [linux]
libc: [glibc]
@@ -2640,10 +2641,10 @@ packages:
os: [linux]
libc: [glibc]
- '@img/sharp-linux-x64@0.34.5':
- resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [x64]
+ '@img/sharp-linux-s390x@0.35.5':
+ resolution: {integrity: sha512-UZasTOFiYzotTsGOCu42BfUzP6Tu6Do/947iRm1RsLKvlllxwGcn4RN27LibGWceix4Y+Pmw3jsnTcCQIgWjqA==}
+ engines: {node: '>=20.9.0'}
+ cpu: [s390x]
os: [linux]
libc: [glibc]
@@ -2654,12 +2655,12 @@ packages:
os: [linux]
libc: [glibc]
- '@img/sharp-linuxmusl-arm64@0.34.5':
- resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [arm64]
+ '@img/sharp-linux-x64@0.35.5':
+ resolution: {integrity: sha512-SxFtLTeJInhAA9Q836kux2vZNeOBQEx658qvbboZScr0wIARym3IcGmW7KpVD5sbVg0Ojy+udFQdayYIZyoNog==}
+ engines: {node: '>=20.9.0'}
+ cpu: [x64]
os: [linux]
- libc: [musl]
+ libc: [glibc]
'@img/sharp-linuxmusl-arm64@0.35.3':
resolution: {integrity: sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==}
@@ -2668,10 +2669,10 @@ packages:
os: [linux]
libc: [musl]
- '@img/sharp-linuxmusl-x64@0.34.5':
- resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [x64]
+ '@img/sharp-linuxmusl-arm64@0.35.5':
+ resolution: {integrity: sha512-9HbMclmI1zlNkFRs3z9/eBtDjfD0sGlrX1z6b1qwmiFY5ElDLh4BC0LPBdVp7z1DXFiKlIcznf+ZlsuZzLxQqg==}
+ engines: {node: '>=20.9.0'}
+ cpu: [arm64]
os: [linux]
libc: [musl]
@@ -2682,25 +2683,30 @@ packages:
os: [linux]
libc: [musl]
- '@img/sharp-wasm32@0.34.5':
- resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [wasm32]
+ '@img/sharp-linuxmusl-x64@0.35.5':
+ resolution: {integrity: sha512-4KOphqB035HrVdqLZfCgMzzERrQkkzOwRhl4OAkRO1YCldbaFjySXMaK534Mo0V+LndnlJk+sbUyLeU0ULyD1A==}
+ engines: {node: '>=20.9.0'}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
'@img/sharp-wasm32@0.35.3':
resolution: {integrity: sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==}
engines: {node: '>=20.9.0'}
+ '@img/sharp-wasm32@0.35.5':
+ resolution: {integrity: sha512-Ptsga1su4tQx+LLF1ECS9U6nz5kmrXKo6XVbtR48Ke3ZRxxgaWBu7IDtEe1quo8hiupwm6WFqxVlXaSf7IINGQ==}
+ engines: {node: '>=20.9.0'}
+
'@img/sharp-webcontainers-wasm32@0.35.3':
resolution: {integrity: sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==}
engines: {node: '>=20.9.0'}
cpu: [wasm32]
- '@img/sharp-win32-arm64@0.34.5':
- resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [arm64]
- os: [win32]
+ '@img/sharp-webcontainers-wasm32@0.35.5':
+ resolution: {integrity: sha512-hfhF/FmoQyTUkA0bIKFOtw536BQSeBMe6BF6QyWlrPxT754+TFLaZ7sKKTfvvM0yJgKgaYTwnFCIZ/GuDw5SUA==}
+ engines: {node: '>=20.9.0'}
+ cpu: [wasm32]
'@img/sharp-win32-arm64@0.35.3':
resolution: {integrity: sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==}
@@ -2708,10 +2714,10 @@ packages:
cpu: [arm64]
os: [win32]
- '@img/sharp-win32-ia32@0.34.5':
- resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [ia32]
+ '@img/sharp-win32-arm64@0.35.5':
+ resolution: {integrity: sha512-X4t7g+7ZA5DKblCBEXGjUqqemj4vczING/5viFwAL8h4N3qYeyjwdCvRLHi4EdOUI+2Z7UFlp1VM+p/AuEtm6Q==}
+ engines: {node: '>=20.9.0'}
+ cpu: [arm64]
os: [win32]
'@img/sharp-win32-ia32@0.35.3':
@@ -2720,10 +2726,10 @@ packages:
cpu: [ia32]
os: [win32]
- '@img/sharp-win32-x64@0.34.5':
- resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
- cpu: [x64]
+ '@img/sharp-win32-ia32@0.35.5':
+ resolution: {integrity: sha512-5Zm82LoBc43nhwNybZlG7Y1KO//Zhsn306fQl29ZOuStHLGTo3BWL83q3cznX0poxSAMuYL1On/BHBxkBeKr6A==}
+ engines: {node: ^20.9.0}
+ cpu: [ia32]
os: [win32]
'@img/sharp-win32-x64@0.35.3':
@@ -2732,6 +2738,12 @@ packages:
cpu: [x64]
os: [win32]
+ '@img/sharp-win32-x64@0.35.5':
+ resolution: {integrity: sha512-x76eH0vEiHlcMQu8Y8IenntaACtddpT6W0wmXtWrnKcnKI7ME5DdgqhAD6SEWOEl1v2zDvkZDhFA9KnURwpfqg==}
+ engines: {node: '>=20.9.0'}
+ cpu: [x64]
+ os: [win32]
+
'@inquirer/external-editor@1.0.3':
resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==}
engines: {node: '>=18'}
@@ -2914,57 +2926,57 @@ packages:
'@emnapi/core': ^1.7.1
'@emnapi/runtime': ^1.7.1
- '@next/env@16.2.10':
- resolution: {integrity: sha512-zLPxg9M0MEHmygpj5OuxjQ+vHMiy/K7cSp74G8ecYolmgUWw0RwN02tF56npup/+qaI8JB97hQgS/r2Hb6QwVA==}
+ '@next/env@16.4.1':
+ resolution: {integrity: sha512-5sUUrrSvs/2/2LnLoesybMGx12EtPB46fdZ6RhAw0XDGSPxU2LFyQBB7yuEiOFFJPKmBY6+q2jTr1/AMbnp0/g==}
- '@next/swc-darwin-arm64@16.2.10':
- resolution: {integrity: sha512-v9IdJCa0H0mbo+8z5zwUpOk1Vj7RjkcI5uNYf5Ws1y6szf/p3Mzl9hLaST8SCt6L9h8NGnruZcd2+o0NTNwDhA==}
+ '@next/swc-darwin-arm64@16.4.1':
+ resolution: {integrity: sha512-U+hQ5Gj3fpzf4fveTIF3dpUFYhaSW8vHhdAnbiIomzXzg7boreYFgBqprepXFtW4sw+aTttiNmg0gew/iFNhbg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
- '@next/swc-darwin-x64@16.2.10':
- resolution: {integrity: sha512-17IS0jJRViROGmA9uGdNR8VPJpfbnaVG7E9qhso5jDLkmyd0lSDORWxbcKINzcFqzZqGwGtMSnrFRxBpuUYjLQ==}
+ '@next/swc-darwin-x64@16.4.1':
+ resolution: {integrity: sha512-/hqC3V1XLUjhMASf/WridKdO9FXoEgN3HBWmtKbj00MPgnltutfraWJ3bYTpCRIgEIpbjJyOVLpYgAhh/BkdcQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
- '@next/swc-linux-arm64-gnu@16.2.10':
- resolution: {integrity: sha512-GRQRsRtuciNJvB54AvvuQTiq0oZtFwa1owQqtZD8wwnGpM2L39MV22kpI72YSXLKIyY40LC66EiLFv4PiicXxg==}
+ '@next/swc-linux-arm64-gnu@16.4.1':
+ resolution: {integrity: sha512-GHzncHbcaS9g95kcvTNtKQW3aCLoR+xc3Jm7qrkpk1R+D2BjMHIPyvQGRPKCdMX95BsH/421jBUK06q9tEwzjw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
libc: [glibc]
- '@next/swc-linux-arm64-musl@16.2.10':
- resolution: {integrity: sha512-zkN9MQYS7UQBro+FnISUq1itaQjXI9xqISzuQ+2bc921NcJ1x4yPCqrn77tVN6/dOOXaaWVX3k6/bR07pPwK+A==}
+ '@next/swc-linux-arm64-musl@16.4.1':
+ resolution: {integrity: sha512-1SuJyDxW/PR9dHJat/ZRgcYLhuSZ+1psP4DlKb2tKIuXbjygqpLrJWRSq+onZQBv8LcmU67EIrmb6c3XTaJLjw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
libc: [musl]
- '@next/swc-linux-x64-gnu@16.2.10':
- resolution: {integrity: sha512-iCVJnwvrPYECvA6WM/7+oo+OiTvedIKLxtCLAZP4xZR3nXa1zmzZyLPbYCmWvpd4CvMYF1EMTafd0ii3DygLvA==}
+ '@next/swc-linux-x64-gnu@16.4.1':
+ resolution: {integrity: sha512-Istng1hMGp9TGO4lUqeKLd70MPN/OOkucVTP2Nmj+gLkwBgmPqUw8CJYBCC7nbl/B/23bBCcjCI5Hsh6hazC1A==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
libc: [glibc]
- '@next/swc-linux-x64-musl@16.2.10':
- resolution: {integrity: sha512-ov2g4H0dHY9bPoOU83m91hWT7Iq5qy13bUnyyshLU3HGR1Ownn0X9QpmDPc5iIUaahTp7f7LeGAhV4DSFtackw==}
+ '@next/swc-linux-x64-musl@16.4.1':
+ resolution: {integrity: sha512-aSC9wMNiZRRFVpPkPWBzRwLQxIGm/CiQcXyFF1XNcgodb+uMxdk7aSSGGpDXCbnvZdf4itjHxpOd5h7i7zaiYw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
libc: [musl]
- '@next/swc-win32-arm64-msvc@16.2.10':
- resolution: {integrity: sha512-DwAnhLX76HQiFFQNgWlcK+JzlnD1rZ+UK/WY0ZMI/deXpvgnesjNYrqcfo1JzBuz4Kf7o3brIBL0glI1junatA==}
+ '@next/swc-win32-arm64-msvc@16.4.1':
+ resolution: {integrity: sha512-t/myvwFDlypMUjRvbBf8qLPyuaB0iXYYdBtwMt6DM6f+60wtGr4bSYholdPqNeV5VUXZhrpMwfza829kmhS3iA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
- '@next/swc-win32-x64-msvc@16.2.10':
- resolution: {integrity: sha512-0JXq3b85Jk9Jg4ntLUbXSPvoDw3gpZou7twuKdoFG2jOw635v7+IiXfTaa0TxVMyx78pUjnrVYwLgjKfX4e6/A==}
+ '@next/swc-win32-x64-msvc@16.4.1':
+ resolution: {integrity: sha512-6ICqPo9awCkrtYNPhwkx1uU7rlFWrZRrIboDHS2LU+jv088UBYQtmJ25h6pCp27/+FZjF6BQ4Te4ErugyMeuBg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
@@ -4743,8 +4755,8 @@ packages:
'@swc/counter@0.1.3':
resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
- '@swc/helpers@0.5.15':
- resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==}
+ '@swc/helpers@0.5.23':
+ resolution: {integrity: sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==}
'@swc/types@0.1.27':
resolution: {integrity: sha512-K6h3iUlqeM946U4sXFYeahefR1YBbXJvko+hv8WS8/0BNJ4OHiHRywMnQUJCqkR7Y9+hqQ1TvEpiKqUhz7NEFg==}
@@ -7781,8 +7793,8 @@ packages:
react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
- next@16.2.10:
- resolution: {integrity: sha512-2som5AVXb3kE6Yjine3/mNbBayYF58eguBWIVVUdr1y/L426xyVEgYxgBG+1QC34P2x5E+tcDup6XkuOAX3dCA==}
+ next@16.4.1:
+ resolution: {integrity: sha512-uc657V62E34fOI6W5NtG9IzwsPcms0Z60grz2MJGtglgD+pTFnNt4Yw2PzaU622tfX4vhrDgLZzicE2YlhI20Q==}
engines: {node: '>=20.9.0'}
hasBin: true
peerDependencies:
@@ -8183,14 +8195,14 @@ packages:
resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==}
engines: {node: ^10 || ^12 || >=14}
- postcss@8.4.31:
- resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==}
- engines: {node: ^10 || ^12 || >=14}
-
postcss@8.5.21:
resolution: {integrity: sha512-v4sDNP3fdNiWMfabO7OwOQdOX8TiQSztKyT1Wj0w+j7LDallJThJRBBBmzVGyYj0crMh7jlV4zepPkiNu9UwDQ==}
engines: {node: ^10 || ^12 || >=14}
+ postcss@8.5.23:
+ resolution: {integrity: sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==}
+ engines: {node: ^10 || ^12 || >=14}
+
posthog-js@1.249.5:
resolution: {integrity: sha512-ynB2bcSZz91xF36Aun2OgAvJ37WPjp8hrUHplZJTdJKhaX7j63CePR+Ved6NVO4YqwhCOVqepxwGGJXG4ROBeA==}
peerDependencies:
@@ -8740,10 +8752,6 @@ packages:
engines: {node: '>=20.18.1'}
hasBin: true
- sharp@0.34.5:
- resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
- engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
-
sharp@0.35.3:
resolution: {integrity: sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==}
engines: {node: '>=20.9.0'}
@@ -8753,6 +8761,15 @@ packages:
'@types/node':
optional: true
+ sharp@0.35.5:
+ resolution: {integrity: sha512-Ywn4OnzGukp7CDMrp08RQ50YKmuwG47brZgIVPTvBaaAfQlRlygrRqSrxdCiL9M+LlzLBiJ68IR1QqvzHyjC7g==}
+ engines: {node: '>=20.9.0'}
+ peerDependencies:
+ '@types/node': '*'
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+
shebang-command@2.0.0:
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
engines: {node: '>=8'}
@@ -9886,6 +9903,14 @@ snapshots:
- '@emnapi/runtime'
optional: true
+ '@astrojs/compiler-binding-wasm32-wasi@0.3.1(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.3)':
+ dependencies:
+ '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.3)
+ transitivePeerDependencies:
+ - '@emnapi/core'
+ - '@emnapi/runtime'
+ optional: true
+
'@astrojs/compiler-binding-win32-arm64-msvc@0.3.1':
optional: true
@@ -9907,6 +9932,21 @@ snapshots:
- '@emnapi/core'
- '@emnapi/runtime'
+ '@astrojs/compiler-binding@0.3.1(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.3)':
+ optionalDependencies:
+ '@astrojs/compiler-binding-darwin-arm64': 0.3.1
+ '@astrojs/compiler-binding-darwin-x64': 0.3.1
+ '@astrojs/compiler-binding-linux-arm64-gnu': 0.3.1
+ '@astrojs/compiler-binding-linux-arm64-musl': 0.3.1
+ '@astrojs/compiler-binding-linux-x64-gnu': 0.3.1
+ '@astrojs/compiler-binding-linux-x64-musl': 0.3.1
+ '@astrojs/compiler-binding-wasm32-wasi': 0.3.1(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.3)
+ '@astrojs/compiler-binding-win32-arm64-msvc': 0.3.1
+ '@astrojs/compiler-binding-win32-x64-msvc': 0.3.1
+ transitivePeerDependencies:
+ - '@emnapi/core'
+ - '@emnapi/runtime'
+
'@astrojs/compiler-rs@0.3.1(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)':
dependencies:
'@astrojs/compiler-binding': 0.3.1(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)
@@ -9914,6 +9954,13 @@ snapshots:
- '@emnapi/core'
- '@emnapi/runtime'
+ '@astrojs/compiler-rs@0.3.1(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.3)':
+ dependencies:
+ '@astrojs/compiler-binding': 0.3.1(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.3)
+ transitivePeerDependencies:
+ - '@emnapi/core'
+ - '@emnapi/runtime'
+
'@astrojs/internal-helpers@0.10.1':
dependencies:
'@types/hast': 3.0.5
@@ -10759,6 +10806,11 @@ snapshots:
tslib: 2.8.1
optional: true
+ '@emnapi/runtime@1.11.3':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
'@emnapi/wasi-threads@1.2.2':
dependencies:
tslib: 2.8.1
@@ -11185,10 +11237,10 @@ snapshots:
dependencies:
'@formatjs/fast-memoize': 3.1.7
- '@fumadocs/mdx-remote@1.4.4(@types/react@19.2.17)(fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76))(react@19.2.7)(supports-color@9.4.0)':
+ '@fumadocs/mdx-remote@1.4.4(@types/react@19.2.17)(fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76))(react@19.2.7)(supports-color@9.4.0)':
dependencies:
'@mdx-js/mdx': 3.1.1(supports-color@9.4.0)
- fumadocs-core: 16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76)
+ fumadocs-core: 16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76)
gray-matter: 4.0.3
react: 19.2.7
zod: 4.4.3
@@ -11197,9 +11249,9 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@fumadocs/ui@16.4.6(@types/react@19.2.17)(fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(tailwindcss@4.3.3)':
+ '@fumadocs/ui@16.4.6(@types/react@19.2.17)(fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(tailwindcss@4.3.3)':
dependencies:
- fumadocs-core: 16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76)
+ fumadocs-core: 16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76)
next-themes: 0.4.6(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
postcss-selector-parser: 7.1.4
react: 19.2.7
@@ -11207,7 +11259,7 @@ snapshots:
tailwind-merge: 3.6.0
optionalDependencies:
'@types/react': 19.2.17
- next: 16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
+ next: 16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
tailwindcss: 4.3.3
'@grpc/grpc-js@1.14.4':
@@ -11265,19 +11317,14 @@ snapshots:
'@img/colour@1.1.0':
optional: true
- '@img/sharp-darwin-arm64@0.34.5':
- optionalDependencies:
- '@img/sharp-libvips-darwin-arm64': 1.2.4
- optional: true
-
'@img/sharp-darwin-arm64@0.35.3':
optionalDependencies:
'@img/sharp-libvips-darwin-arm64': 1.3.2
optional: true
- '@img/sharp-darwin-x64@0.34.5':
+ '@img/sharp-darwin-arm64@0.35.5':
optionalDependencies:
- '@img/sharp-libvips-darwin-x64': 1.2.4
+ '@img/sharp-libvips-darwin-arm64': 1.3.4
optional: true
'@img/sharp-darwin-x64@0.35.3':
@@ -11285,74 +11332,79 @@ snapshots:
'@img/sharp-libvips-darwin-x64': 1.3.2
optional: true
+ '@img/sharp-darwin-x64@0.35.5':
+ optionalDependencies:
+ '@img/sharp-libvips-darwin-x64': 1.3.4
+ optional: true
+
'@img/sharp-freebsd-wasm32@0.35.3':
dependencies:
'@img/sharp-wasm32': 0.35.3
optional: true
- '@img/sharp-libvips-darwin-arm64@1.2.4':
+ '@img/sharp-freebsd-wasm32@0.35.5':
+ dependencies:
+ '@img/sharp-wasm32': 0.35.5
optional: true
'@img/sharp-libvips-darwin-arm64@1.3.2':
optional: true
- '@img/sharp-libvips-darwin-x64@1.2.4':
+ '@img/sharp-libvips-darwin-arm64@1.3.4':
optional: true
'@img/sharp-libvips-darwin-x64@1.3.2':
optional: true
- '@img/sharp-libvips-linux-arm64@1.2.4':
+ '@img/sharp-libvips-darwin-x64@1.3.4':
optional: true
'@img/sharp-libvips-linux-arm64@1.3.2':
optional: true
- '@img/sharp-libvips-linux-arm@1.2.4':
+ '@img/sharp-libvips-linux-arm64@1.3.4':
optional: true
'@img/sharp-libvips-linux-arm@1.3.2':
optional: true
- '@img/sharp-libvips-linux-ppc64@1.2.4':
+ '@img/sharp-libvips-linux-arm@1.3.4':
optional: true
'@img/sharp-libvips-linux-ppc64@1.3.2':
optional: true
- '@img/sharp-libvips-linux-riscv64@1.2.4':
+ '@img/sharp-libvips-linux-ppc64@1.3.4':
optional: true
'@img/sharp-libvips-linux-riscv64@1.3.2':
optional: true
- '@img/sharp-libvips-linux-s390x@1.2.4':
+ '@img/sharp-libvips-linux-riscv64@1.3.4':
optional: true
'@img/sharp-libvips-linux-s390x@1.3.2':
optional: true
- '@img/sharp-libvips-linux-x64@1.2.4':
+ '@img/sharp-libvips-linux-s390x@1.3.4':
optional: true
'@img/sharp-libvips-linux-x64@1.3.2':
optional: true
- '@img/sharp-libvips-linuxmusl-arm64@1.2.4':
+ '@img/sharp-libvips-linux-x64@1.3.4':
optional: true
'@img/sharp-libvips-linuxmusl-arm64@1.3.2':
optional: true
- '@img/sharp-libvips-linuxmusl-x64@1.2.4':
+ '@img/sharp-libvips-linuxmusl-arm64@1.3.4':
optional: true
'@img/sharp-libvips-linuxmusl-x64@1.3.2':
optional: true
- '@img/sharp-linux-arm64@0.34.5':
- optionalDependencies:
- '@img/sharp-libvips-linux-arm64': 1.2.4
+ '@img/sharp-libvips-linuxmusl-x64@1.3.4':
optional: true
'@img/sharp-linux-arm64@0.35.3':
@@ -11360,9 +11412,9 @@ snapshots:
'@img/sharp-libvips-linux-arm64': 1.3.2
optional: true
- '@img/sharp-linux-arm@0.34.5':
+ '@img/sharp-linux-arm64@0.35.5':
optionalDependencies:
- '@img/sharp-libvips-linux-arm': 1.2.4
+ '@img/sharp-libvips-linux-arm64': 1.3.4
optional: true
'@img/sharp-linux-arm@0.35.3':
@@ -11370,9 +11422,9 @@ snapshots:
'@img/sharp-libvips-linux-arm': 1.3.2
optional: true
- '@img/sharp-linux-ppc64@0.34.5':
+ '@img/sharp-linux-arm@0.35.5':
optionalDependencies:
- '@img/sharp-libvips-linux-ppc64': 1.2.4
+ '@img/sharp-libvips-linux-arm': 1.3.4
optional: true
'@img/sharp-linux-ppc64@0.35.3':
@@ -11380,9 +11432,9 @@ snapshots:
'@img/sharp-libvips-linux-ppc64': 1.3.2
optional: true
- '@img/sharp-linux-riscv64@0.34.5':
+ '@img/sharp-linux-ppc64@0.35.5':
optionalDependencies:
- '@img/sharp-libvips-linux-riscv64': 1.2.4
+ '@img/sharp-libvips-linux-ppc64': 1.3.4
optional: true
'@img/sharp-linux-riscv64@0.35.3':
@@ -11390,9 +11442,9 @@ snapshots:
'@img/sharp-libvips-linux-riscv64': 1.3.2
optional: true
- '@img/sharp-linux-s390x@0.34.5':
+ '@img/sharp-linux-riscv64@0.35.5':
optionalDependencies:
- '@img/sharp-libvips-linux-s390x': 1.2.4
+ '@img/sharp-libvips-linux-riscv64': 1.3.4
optional: true
'@img/sharp-linux-s390x@0.35.3':
@@ -11400,9 +11452,9 @@ snapshots:
'@img/sharp-libvips-linux-s390x': 1.3.2
optional: true
- '@img/sharp-linux-x64@0.34.5':
+ '@img/sharp-linux-s390x@0.35.5':
optionalDependencies:
- '@img/sharp-libvips-linux-x64': 1.2.4
+ '@img/sharp-libvips-linux-s390x': 1.3.4
optional: true
'@img/sharp-linux-x64@0.35.3':
@@ -11410,9 +11462,9 @@ snapshots:
'@img/sharp-libvips-linux-x64': 1.3.2
optional: true
- '@img/sharp-linuxmusl-arm64@0.34.5':
+ '@img/sharp-linux-x64@0.35.5':
optionalDependencies:
- '@img/sharp-libvips-linuxmusl-arm64': 1.2.4
+ '@img/sharp-libvips-linux-x64': 1.3.4
optional: true
'@img/sharp-linuxmusl-arm64@0.35.3':
@@ -11420,9 +11472,9 @@ snapshots:
'@img/sharp-libvips-linuxmusl-arm64': 1.3.2
optional: true
- '@img/sharp-linuxmusl-x64@0.34.5':
+ '@img/sharp-linuxmusl-arm64@0.35.5':
optionalDependencies:
- '@img/sharp-libvips-linuxmusl-x64': 1.2.4
+ '@img/sharp-libvips-linuxmusl-arm64': 1.3.4
optional: true
'@img/sharp-linuxmusl-x64@0.35.3':
@@ -11430,9 +11482,9 @@ snapshots:
'@img/sharp-libvips-linuxmusl-x64': 1.3.2
optional: true
- '@img/sharp-wasm32@0.34.5':
- dependencies:
- '@emnapi/runtime': 1.11.2
+ '@img/sharp-linuxmusl-x64@0.35.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linuxmusl-x64': 1.3.4
optional: true
'@img/sharp-wasm32@0.35.3':
@@ -11440,29 +11492,39 @@ snapshots:
'@emnapi/runtime': 1.11.2
optional: true
+ '@img/sharp-wasm32@0.35.5':
+ dependencies:
+ '@emnapi/runtime': 1.11.3
+ optional: true
+
'@img/sharp-webcontainers-wasm32@0.35.3':
dependencies:
'@img/sharp-wasm32': 0.35.3
optional: true
- '@img/sharp-win32-arm64@0.34.5':
+ '@img/sharp-webcontainers-wasm32@0.35.5':
+ dependencies:
+ '@img/sharp-wasm32': 0.35.5
optional: true
'@img/sharp-win32-arm64@0.35.3':
optional: true
- '@img/sharp-win32-ia32@0.34.5':
+ '@img/sharp-win32-arm64@0.35.5':
optional: true
'@img/sharp-win32-ia32@0.35.3':
optional: true
- '@img/sharp-win32-x64@0.34.5':
+ '@img/sharp-win32-ia32@0.35.5':
optional: true
'@img/sharp-win32-x64@0.35.3':
optional: true
+ '@img/sharp-win32-x64@0.35.5':
+ optional: true
+
'@inquirer/external-editor@1.0.3(@types/node@25.0.3)':
dependencies:
chardet: 2.2.0
@@ -11683,30 +11745,37 @@ snapshots:
'@tybys/wasm-util': 0.10.3
optional: true
- '@next/env@16.2.10': {}
+ '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.3)':
+ dependencies:
+ '@emnapi/core': 1.11.2
+ '@emnapi/runtime': 1.11.3
+ '@tybys/wasm-util': 0.10.3
+ optional: true
- '@next/swc-darwin-arm64@16.2.10':
+ '@next/env@16.4.1': {}
+
+ '@next/swc-darwin-arm64@16.4.1':
optional: true
- '@next/swc-darwin-x64@16.2.10':
+ '@next/swc-darwin-x64@16.4.1':
optional: true
- '@next/swc-linux-arm64-gnu@16.2.10':
+ '@next/swc-linux-arm64-gnu@16.4.1':
optional: true
- '@next/swc-linux-arm64-musl@16.2.10':
+ '@next/swc-linux-arm64-musl@16.4.1':
optional: true
- '@next/swc-linux-x64-gnu@16.2.10':
+ '@next/swc-linux-x64-gnu@16.4.1':
optional: true
- '@next/swc-linux-x64-musl@16.2.10':
+ '@next/swc-linux-x64-musl@16.4.1':
optional: true
- '@next/swc-win32-arm64-msvc@16.2.10':
+ '@next/swc-win32-arm64-msvc@16.4.1':
optional: true
- '@next/swc-win32-x64-msvc@16.2.10':
+ '@next/swc-win32-x64-msvc@16.4.1':
optional: true
'@nodable/entities@3.0.0': {}
@@ -13292,7 +13361,7 @@ snapshots:
'@swc/core-win32-x64-msvc@1.15.46':
optional: true
- '@swc/core@1.15.46':
+ '@swc/core@1.15.46(@swc/helpers@0.5.23)':
dependencies:
'@swc/counter': 0.1.3
'@swc/types': 0.1.27
@@ -13309,10 +13378,11 @@ snapshots:
'@swc/core-win32-arm64-msvc': 1.15.46
'@swc/core-win32-ia32-msvc': 1.15.46
'@swc/core-win32-x64-msvc': 1.15.46
+ '@swc/helpers': 0.5.23
'@swc/counter@0.1.3': {}
- '@swc/helpers@0.5.15':
+ '@swc/helpers@0.5.23':
dependencies:
tslib: 2.8.1
@@ -14232,6 +14302,98 @@ snapshots:
- uploadthing
- yaml
+ astro@7.1.3(@azure/storage-blob@12.33.0(supports-color@9.4.0))(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.3)(@types/node@25.0.3)(db0@0.3.4)(jiti@2.7.0)(rollup@4.62.2)(tsx@4.23.1)(yaml@2.9.0):
+ dependencies:
+ '@astrojs/compiler-rs': 0.3.1(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.3)
+ '@astrojs/internal-helpers': 0.10.1
+ '@astrojs/markdown-satteri': 0.3.4
+ '@astrojs/telemetry': 3.3.3
+ '@capsizecss/unpack': 4.0.1
+ '@clack/prompts': 1.7.0
+ '@oslojs/encoding': 1.1.0
+ '@rollup/pluginutils': 5.4.0(rollup@4.62.2)
+ am-i-vibing: 0.4.0
+ aria-query: 5.3.2
+ axobject-query: 4.1.0
+ ci-info: 4.4.0
+ clsx: 2.1.1
+ common-ancestor-path: 2.0.0
+ cookie: 2.0.1
+ devalue: 5.8.2
+ diff: 8.0.4
+ dset: 3.1.4
+ es-module-lexer: 2.3.1
+ esbuild: 0.28.1
+ flattie: 1.1.1
+ fontace: 0.4.1
+ get-tsconfig: 5.0.0-beta.4
+ github-slugger: 2.0.0
+ html-escaper: 3.0.3
+ http-cache-semantics: 4.2.0
+ js-yaml: 4.3.0
+ jsonc-parser: 3.3.1
+ magic-string: 0.30.21
+ magicast: 0.5.3
+ mrmime: 2.0.1
+ neotraverse: 1.0.1
+ obug: 2.1.4
+ p-limit: 7.3.1
+ p-queue: 9.3.2
+ package-manager-detector: 1.8.0
+ piccolore: 0.1.3
+ picomatch: 4.0.5
+ semver: 7.8.5
+ shiki: 4.3.1
+ smol-toml: 1.7.0
+ svgo: 4.0.2
+ tinyclip: 0.1.15
+ tinyexec: 1.2.4
+ tinyglobby: 0.2.17
+ ultrahtml: 1.7.0
+ unifont: 0.7.4
+ unstorage: 1.17.5(@azure/storage-blob@12.33.0(supports-color@9.4.0))(db0@0.3.4)
+ vite: 8.1.5(@types/node@25.0.3)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)
+ vitefu: 1.1.3(vite@8.1.5(@types/node@25.0.3)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))
+ xxhash-wasm: 1.1.0
+ yargs-parser: 22.0.0
+ zod: 4.4.3
+ optionalDependencies:
+ sharp: 0.35.3(@types/node@25.0.3)
+ transitivePeerDependencies:
+ - '@azure/app-configuration'
+ - '@azure/cosmos'
+ - '@azure/data-tables'
+ - '@azure/identity'
+ - '@azure/keyvault-secrets'
+ - '@azure/storage-blob'
+ - '@capacitor/preferences'
+ - '@deno/kv'
+ - '@emnapi/core'
+ - '@emnapi/runtime'
+ - '@netlify/blobs'
+ - '@planetscale/database'
+ - '@types/node'
+ - '@upstash/redis'
+ - '@vercel/blob'
+ - '@vercel/functions'
+ - '@vercel/kv'
+ - '@vitejs/devtools'
+ - aws4fetch
+ - db0
+ - idb-keyval
+ - ioredis
+ - jiti
+ - less
+ - rollup
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - terser
+ - tsx
+ - uploadthing
+ - yaml
+
atomic-sleep@1.0.0: {}
atomically@1.7.0: {}
@@ -15419,7 +15581,7 @@ snapshots:
fsevents@2.3.3:
optional: true
- fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76):
+ fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76):
dependencies:
'@formatjs/intl-localematcher': 0.7.5
'@orama/orama': 3.1.18
@@ -15444,21 +15606,21 @@ snapshots:
'@tanstack/react-router': 1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
'@types/react': 19.2.17
lucide-react: 0.510.0(react@19.2.7)
- next: 16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
+ next: 16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
react: 19.2.7
react-dom: 19.2.7(react@19.2.7)
zod: 3.25.76
transitivePeerDependencies:
- supports-color
- fumadocs-mdx@14.2.4(18ab8919947fad7e1a46c05e2f7eb114):
+ fumadocs-mdx@14.2.4(7ef7f3fe088cf3dbc6b7b28a4923ccff):
dependencies:
'@mdx-js/mdx': 3.1.1(supports-color@9.4.0)
'@standard-schema/spec': 1.1.0
chokidar: 5.0.0
esbuild: 0.27.7
estree-util-value-to-estree: 3.5.0
- fumadocs-core: 16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76)
+ fumadocs-core: 16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76)
js-yaml: 4.3.0
mdast-util-to-markdown: 2.1.2
picocolors: 1.1.1
@@ -15472,19 +15634,19 @@ snapshots:
vfile: 6.0.3
zod: 4.4.3
optionalDependencies:
- '@fumadocs/mdx-remote': 1.4.4(@types/react@19.2.17)(fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76))(react@19.2.7)(supports-color@9.4.0)
+ '@fumadocs/mdx-remote': 1.4.4(@types/react@19.2.17)(fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76))(react@19.2.7)(supports-color@9.4.0)
'@types/react': 19.2.17
- next: 16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
+ next: 16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
react: 19.2.7
vite: 8.1.5(@types/node@25.0.3)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)
transitivePeerDependencies:
- supports-color
- fumadocs-twoslash@3.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(fumadocs-ui@16.4.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(tailwindcss@4.3.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(typescript@6.0.3):
+ fumadocs-twoslash@3.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(fumadocs-ui@16.4.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(tailwindcss@4.3.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(typescript@6.0.3):
dependencies:
'@radix-ui/react-popover': 1.1.20(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
'@shikijs/twoslash': 3.23.0(supports-color@9.4.0)(typescript@6.0.3)
- fumadocs-ui: 16.4.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(tailwindcss@4.3.3)
+ fumadocs-ui: 16.4.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(tailwindcss@4.3.3)
mdast-util-from-markdown: 2.0.3(supports-color@9.4.0)
mdast-util-gfm: 3.1.0(supports-color@9.4.0)
mdast-util-to-hast: 13.2.1
@@ -15500,9 +15662,9 @@ snapshots:
- supports-color
- typescript
- fumadocs-ui@16.4.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(tailwindcss@4.3.3):
+ fumadocs-ui@16.4.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(tailwindcss@4.3.3):
dependencies:
- '@fumadocs/ui': 16.4.6(@types/react@19.2.17)(fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(tailwindcss@4.3.3)
+ '@fumadocs/ui': 16.4.6(@types/react@19.2.17)(fumadocs-core@16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(tailwindcss@4.3.3)
'@radix-ui/react-accordion': 1.2.17(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
'@radix-ui/react-collapsible': 1.1.17(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
'@radix-ui/react-dialog': 1.1.20(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
@@ -15514,7 +15676,7 @@ snapshots:
'@radix-ui/react-slot': 1.3.0(@types/react@19.2.17)(react@19.2.7)
'@radix-ui/react-tabs': 1.1.18(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
class-variance-authority: 0.7.1
- fumadocs-core: 16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76)
+ fumadocs-core: 16.4.6(@tanstack/react-router@1.170.41(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/react@19.2.17)(lucide-react@0.510.0(react@19.2.7))(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(supports-color@9.4.0)(zod@3.25.76)
lucide-react: 0.562.0(react@19.2.7)
next-themes: 0.4.6(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
react: 19.2.7
@@ -15523,7 +15685,7 @@ snapshots:
scroll-into-view-if-needed: 3.1.0
optionalDependencies:
'@types/react': 19.2.17
- next: 16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
+ next: 16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
tailwindcss: 4.3.3
transitivePeerDependencies:
- '@types/react-dom'
@@ -16834,14 +16996,14 @@ snapshots:
next-intl-swc-plugin-extractor@4.13.3: {}
- next-intl@4.13.3(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(typescript@6.0.3):
+ next-intl@4.13.3(@swc/helpers@0.5.23)(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(typescript@6.0.3):
dependencies:
'@formatjs/intl-localematcher': 0.8.13
'@parcel/watcher': 2.6.0
- '@swc/core': 1.15.46
+ '@swc/core': 1.15.46(@swc/helpers@0.5.23)
icu-minify: 4.13.3
negotiator: 1.0.0
- next: 16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
+ next: 16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
next-intl-swc-plugin-extractor: 4.13.3
po-parser: 2.1.1
react: 19.2.7
@@ -16851,9 +17013,9 @@ snapshots:
transitivePeerDependencies:
- '@swc/helpers'
- next-themes@0.2.1(next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7):
+ next-themes@0.2.1(next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7):
dependencies:
- next: 16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
+ next: 16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
react: 19.2.7
react-dom: 19.2.7(react@19.2.7)
@@ -16862,29 +17024,30 @@ snapshots:
react: 19.2.7
react-dom: 19.2.7(react@19.2.7)
- next@16.2.10(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7):
+ next@16.4.1(@babel/core@7.29.7(supports-color@9.4.0))(@opentelemetry/api@1.9.1)(@types/node@25.0.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7):
dependencies:
- '@next/env': 16.2.10
- '@swc/helpers': 0.5.15
+ '@next/env': 16.4.1
+ '@swc/helpers': 0.5.23
baseline-browser-mapping: 2.10.44
caniuse-lite: 1.0.30001806
- postcss: 8.4.31
+ postcss: 8.5.23
react: 19.2.7
react-dom: 19.2.7(react@19.2.7)
styled-jsx: 5.1.6(@babel/core@7.29.7(supports-color@9.4.0))(react@19.2.7)
optionalDependencies:
- '@next/swc-darwin-arm64': 16.2.10
- '@next/swc-darwin-x64': 16.2.10
- '@next/swc-linux-arm64-gnu': 16.2.10
- '@next/swc-linux-arm64-musl': 16.2.10
- '@next/swc-linux-x64-gnu': 16.2.10
- '@next/swc-linux-x64-musl': 16.2.10
- '@next/swc-win32-arm64-msvc': 16.2.10
- '@next/swc-win32-x64-msvc': 16.2.10
+ '@next/swc-darwin-arm64': 16.4.1
+ '@next/swc-darwin-x64': 16.4.1
+ '@next/swc-linux-arm64-gnu': 16.4.1
+ '@next/swc-linux-arm64-musl': 16.4.1
+ '@next/swc-linux-x64-gnu': 16.4.1
+ '@next/swc-linux-x64-musl': 16.4.1
+ '@next/swc-win32-arm64-msvc': 16.4.1
+ '@next/swc-win32-x64-msvc': 16.4.1
'@opentelemetry/api': 1.9.1
- sharp: 0.34.5
+ sharp: 0.35.5(@types/node@25.0.3)
transitivePeerDependencies:
- '@babel/core'
+ - '@types/node'
- babel-plugin-macros
nf3@0.3.22: {}
@@ -17290,13 +17453,13 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
- postcss@8.4.31:
+ postcss@8.5.21:
dependencies:
nanoid: 3.3.16
picocolors: 1.1.1
source-map-js: 1.2.1
- postcss@8.5.21:
+ postcss@8.5.23:
dependencies:
nanoid: 3.3.16
picocolors: 1.1.1
@@ -17719,12 +17882,12 @@ snapshots:
rollup: 4.62.2
vite: 8.1.5(@types/node@25.0.3)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)
- rollup-plugin-swc3@0.12.1(@swc/core@1.15.46)(rollup@4.62.2):
+ rollup-plugin-swc3@0.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(rollup@4.62.2):
dependencies:
'@dual-bundle/import-meta-resolve': 4.2.1
'@fastify/deepmerge': 2.0.2
'@rollup/pluginutils': 5.4.0(rollup@4.62.2)
- '@swc/core': 1.15.46
+ '@swc/core': 1.15.46(@swc/helpers@0.5.23)
get-tsconfig: 4.14.0
rollup: 4.62.2
rollup-preserve-directives: 1.1.3(rollup@4.62.2)
@@ -17927,38 +18090,6 @@ snapshots:
- supports-color
- typescript
- sharp@0.34.5:
- dependencies:
- '@img/colour': 1.1.0
- detect-libc: 2.1.2
- semver: 7.8.5
- optionalDependencies:
- '@img/sharp-darwin-arm64': 0.34.5
- '@img/sharp-darwin-x64': 0.34.5
- '@img/sharp-libvips-darwin-arm64': 1.2.4
- '@img/sharp-libvips-darwin-x64': 1.2.4
- '@img/sharp-libvips-linux-arm': 1.2.4
- '@img/sharp-libvips-linux-arm64': 1.2.4
- '@img/sharp-libvips-linux-ppc64': 1.2.4
- '@img/sharp-libvips-linux-riscv64': 1.2.4
- '@img/sharp-libvips-linux-s390x': 1.2.4
- '@img/sharp-libvips-linux-x64': 1.2.4
- '@img/sharp-libvips-linuxmusl-arm64': 1.2.4
- '@img/sharp-libvips-linuxmusl-x64': 1.2.4
- '@img/sharp-linux-arm': 0.34.5
- '@img/sharp-linux-arm64': 0.34.5
- '@img/sharp-linux-ppc64': 0.34.5
- '@img/sharp-linux-riscv64': 0.34.5
- '@img/sharp-linux-s390x': 0.34.5
- '@img/sharp-linux-x64': 0.34.5
- '@img/sharp-linuxmusl-arm64': 0.34.5
- '@img/sharp-linuxmusl-x64': 0.34.5
- '@img/sharp-wasm32': 0.34.5
- '@img/sharp-win32-arm64': 0.34.5
- '@img/sharp-win32-ia32': 0.34.5
- '@img/sharp-win32-x64': 0.34.5
- optional: true
-
sharp@0.35.3(@types/node@25.0.3):
dependencies:
'@img/colour': 1.1.0
@@ -17993,6 +18124,40 @@ snapshots:
'@types/node': 25.0.3
optional: true
+ sharp@0.35.5(@types/node@25.0.3):
+ dependencies:
+ '@img/colour': 1.1.0
+ detect-libc: 2.1.2
+ semver: 7.8.5
+ optionalDependencies:
+ '@img/sharp-darwin-arm64': 0.35.5
+ '@img/sharp-darwin-x64': 0.35.5
+ '@img/sharp-freebsd-wasm32': 0.35.5
+ '@img/sharp-libvips-darwin-arm64': 1.3.4
+ '@img/sharp-libvips-darwin-x64': 1.3.4
+ '@img/sharp-libvips-linux-arm': 1.3.4
+ '@img/sharp-libvips-linux-arm64': 1.3.4
+ '@img/sharp-libvips-linux-ppc64': 1.3.4
+ '@img/sharp-libvips-linux-riscv64': 1.3.4
+ '@img/sharp-libvips-linux-s390x': 1.3.4
+ '@img/sharp-libvips-linux-x64': 1.3.4
+ '@img/sharp-libvips-linuxmusl-arm64': 1.3.4
+ '@img/sharp-libvips-linuxmusl-x64': 1.3.4
+ '@img/sharp-linux-arm': 0.35.5
+ '@img/sharp-linux-arm64': 0.35.5
+ '@img/sharp-linux-ppc64': 0.35.5
+ '@img/sharp-linux-riscv64': 0.35.5
+ '@img/sharp-linux-s390x': 0.35.5
+ '@img/sharp-linux-x64': 0.35.5
+ '@img/sharp-linuxmusl-arm64': 0.35.5
+ '@img/sharp-linuxmusl-x64': 0.35.5
+ '@img/sharp-webcontainers-wasm32': 0.35.5
+ '@img/sharp-win32-arm64': 0.35.5
+ '@img/sharp-win32-ia32': 0.35.5
+ '@img/sharp-win32-x64': 0.35.5
+ '@types/node': 25.0.3
+ optional: true
+
shebang-command@2.0.0:
dependencies:
shebang-regex: 3.0.0
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index 4f67cf94..12d8cdc6 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -17,7 +17,7 @@ catalog:
express: 5.2.1
fastify: 5.10.0
hono: 4.12.31
- next: 16.2.10
+ next: 16.4.1
react: 19.2.7
react-dom: 19.2.7
react-dropzone: 20.1.2
@@ -42,6 +42,19 @@ overrides:
'@edgestore/react': 'workspace:*'
minimumReleaseAgeStrict: true
+# Next.js 16.4.1 is the October 14, 2026 security release. Remove these once
+# it is older than the default one-day minimum release age.
+minimumReleaseAgeExclude:
+ - next@16.4.1
+ - '@next/env@16.4.1'
+ - '@next/swc-darwin-arm64@16.4.1'
+ - '@next/swc-darwin-x64@16.4.1'
+ - '@next/swc-linux-arm64-gnu@16.4.1'
+ - '@next/swc-linux-arm64-musl@16.4.1'
+ - '@next/swc-linux-x64-gnu@16.4.1'
+ - '@next/swc-linux-x64-musl@16.4.1'
+ - '@next/swc-win32-arm64-msvc@16.4.1'
+ - '@next/swc-win32-x64-msvc@16.4.1'
allowBuilds:
'@parcel/watcher': false
diff --git a/registry.json b/registry.json
index 9a5189c4..18f57379 100644
--- a/registry.json
+++ b/registry.json
@@ -48,6 +48,25 @@
}
]
},
+ {
+ "name": "file-list",
+ "type": "registry:component",
+ "title": "File List",
+ "description": "Lists the files of an UploaderProvider with their status, progress, retry, cancel and remove.",
+ "dependencies": ["lucide-react"],
+ "registryDependencies": [
+ "https://edgestore.dev/r/progress-bar.json",
+ "https://edgestore.dev/r/uploader-provider.json",
+ "https://edgestore.dev/r/upload-utils.json"
+ ],
+ "files": [
+ {
+ "path": "examples/components/src/components/upload/file-list.tsx",
+ "type": "registry:component",
+ "target": "components/upload/file-list.tsx"
+ }
+ ]
+ },
{
"name": "file-uploader",
"type": "registry:component",
@@ -57,7 +76,7 @@
"registryDependencies": [
"button",
"https://edgestore.dev/r/dropzone.json",
- "https://edgestore.dev/r/progress-bar.json",
+ "https://edgestore.dev/r/file-list.json",
"https://edgestore.dev/r/uploader-provider.json",
"https://edgestore.dev/r/upload-utils.json"
],
@@ -139,7 +158,7 @@
"dependencies": ["react-dropzone", "lucide-react"],
"registryDependencies": [
"https://edgestore.dev/r/dropzone.json",
- "https://edgestore.dev/r/file-uploader.json",
+ "https://edgestore.dev/r/file-list.json",
"https://edgestore.dev/r/uploader-provider.json",
"https://edgestore.dev/r/upload-utils.json"
],
@@ -208,8 +227,8 @@
"files": [
{
"path": "examples/components/src/components/upload/blocks/multi-file-block.tsx",
- "type": "registry:block",
- "target": "components/upload/blocks/multi-file-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
]
},
@@ -225,8 +244,8 @@
"files": [
{
"path": "examples/components/src/components/upload/blocks/single-image-block.tsx",
- "type": "registry:block",
- "target": "components/upload/blocks/single-image-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
]
},
@@ -242,8 +261,8 @@
"files": [
{
"path": "examples/components/src/components/upload/blocks/multi-image-block.tsx",
- "type": "registry:block",
- "target": "components/upload/blocks/multi-image-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
]
},
@@ -259,8 +278,8 @@
"files": [
{
"path": "examples/components/src/components/upload/blocks/avatar-block.tsx",
- "type": "registry:block",
- "target": "components/upload/blocks/avatar-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
]
},
@@ -277,8 +296,8 @@
"files": [
{
"path": "examples/components/src/components/upload/blocks/file-field-block.tsx",
- "type": "registry:block",
- "target": "components/upload/blocks/file-field-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
]
},
@@ -290,15 +309,15 @@
"dependencies": ["lucide-react"],
"registryDependencies": [
"https://edgestore.dev/r/upload-button.json",
- "https://edgestore.dev/r/file-uploader.json",
+ "https://edgestore.dev/r/file-list.json",
"https://edgestore.dev/r/dropzone.json",
"https://edgestore.dev/r/uploader-provider.json"
],
"files": [
{
"path": "examples/components/src/components/upload/blocks/upload-button-block.tsx",
- "type": "registry:block",
- "target": "components/upload/blocks/upload-button-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
]
},
@@ -311,8 +330,8 @@
"files": [
{
"path": "examples/components/src/components/upload/blocks/progress-bar-block.tsx",
- "type": "registry:block",
- "target": "components/upload/blocks/progress-bar-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
]
},
@@ -325,8 +344,8 @@
"files": [
{
"path": "examples/components/src/components/upload/blocks/progress-circle-block.tsx",
- "type": "registry:block",
- "target": "components/upload/blocks/progress-circle-block.tsx"
+ "type": "registry:page",
+ "target": "app/page.tsx"
}
]
}
diff --git a/scripts/agentDocs/selection.ts b/scripts/agentDocs/selection.ts
index c4ff0e1f..9ba1527f 100644
--- a/scripts/agentDocs/selection.ts
+++ b/scripts/agentDocs/selection.ts
@@ -60,6 +60,7 @@ export const references: Record = {
'avatar',
'file-field',
'upload-button',
+ 'file-list',
'uploader-provider',
].map((component) => ({
file: `${component}.md`,