@spark-ui/components 11.5.0 → 11.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/alert-dialog/index.mjs +4 -4
  2. package/dist/avatar/index.d.mts +2 -2
  3. package/dist/avatar/index.d.ts +2 -2
  4. package/dist/avatar/index.mjs +3 -3
  5. package/dist/button/index.mjs +1 -1
  6. package/dist/carousel/index.mjs +3 -3
  7. package/dist/{chunk-HEKSVWYW.mjs → chunk-2YM6GKWW.mjs} +2 -1
  8. package/dist/{chunk-XYK6V3JF.mjs → chunk-DCXWGQVZ.mjs} +2 -2
  9. package/dist/{chunk-D7YBYT5H.mjs → chunk-GPJMLIHC.mjs} +2 -2
  10. package/dist/{chunk-2BSBKLHG.mjs → chunk-WLI4EPS6.mjs} +2 -2
  11. package/dist/combobox/index.mjs +6 -6
  12. package/dist/dialog/index.mjs +4 -4
  13. package/dist/docgen.json +13 -2
  14. package/dist/drawer/index.mjs +3 -3
  15. package/dist/dropdown/index.mjs +4 -4
  16. package/dist/file-upload/index.d.mts +1 -1
  17. package/dist/file-upload/index.d.ts +1 -1
  18. package/dist/file-upload/index.js +52 -24
  19. package/dist/file-upload/index.js.map +1 -1
  20. package/dist/file-upload/index.mjs +59 -30
  21. package/dist/file-upload/index.mjs.map +1 -1
  22. package/dist/icon-button/index.mjs +2 -2
  23. package/dist/pagination/index.mjs +5 -5
  24. package/dist/popover/index.mjs +4 -4
  25. package/dist/scrolling-list/index.mjs +5 -5
  26. package/dist/snackbar/index.mjs +5 -5
  27. package/dist/stepper/index.mjs +3 -3
  28. package/dist/tabs/index.mjs +4 -4
  29. package/dist/toast/index.d.mts +6 -6
  30. package/dist/toast/index.d.ts +6 -6
  31. package/dist/toast/index.mjs +5 -5
  32. package/package.json +5 -5
  33. /package/dist/{chunk-HEKSVWYW.mjs.map → chunk-2YM6GKWW.mjs.map} +0 -0
  34. /package/dist/{chunk-XYK6V3JF.mjs.map → chunk-DCXWGQVZ.mjs.map} +0 -0
  35. /package/dist/{chunk-D7YBYT5H.mjs.map → chunk-GPJMLIHC.mjs.map} +0 -0
  36. /package/dist/{chunk-2BSBKLHG.mjs.map → chunk-WLI4EPS6.mjs.map} +0 -0
@@ -3,14 +3,15 @@ import {
3
3
  } from "../chunk-TKAU6SMC.mjs";
4
4
  import {
5
5
  IconButton
6
- } from "../chunk-XYK6V3JF.mjs";
6
+ } from "../chunk-DCXWGQVZ.mjs";
7
+ import {
8
+ Button,
9
+ buttonStyles
10
+ } from "../chunk-2YM6GKWW.mjs";
11
+ import "../chunk-GAK4SC2F.mjs";
7
12
  import {
8
13
  Icon
9
14
  } from "../chunk-UMUMFMFB.mjs";
10
- import {
11
- Button
12
- } from "../chunk-HEKSVWYW.mjs";
13
- import "../chunk-GAK4SC2F.mjs";
14
15
  import "../chunk-KEGAAGJW.mjs";
15
16
  import {
16
17
  Slot
@@ -149,7 +150,8 @@ var FileUpload = ({
149
150
  isRequired,
150
151
  description,
151
152
  disabled: fieldDisabled,
152
- readOnly: fieldReadOnly
153
+ readOnly: fieldReadOnly,
154
+ labelId
153
155
  } = field;
154
156
  const defaultLocale = locale || (typeof navigator !== "undefined" && navigator.language ? navigator.language : "en");
155
157
  const internalId = useId();
@@ -368,6 +370,7 @@ var FileUpload = ({
368
370
  required: isRequired,
369
371
  "aria-invalid": isInvalid,
370
372
  "aria-describedby": description,
373
+ "aria-label": !labelId ? "Upload files test" : void 0,
371
374
  className: "sr-only",
372
375
  onChange: (e) => {
373
376
  if (e.target.files && !disabled && !readOnly) {
@@ -517,8 +520,10 @@ Context.displayName = "FileUpload.Context";
517
520
 
518
521
  // src/file-upload/FileUploadDropzone.tsx
519
522
  import { cx as cx3 } from "class-variance-authority";
520
- import { useRef as useRef3 } from "react";
523
+ import { createContext as createContext2, useContext as useContext2, useRef as useRef3 } from "react";
521
524
  import { jsx as jsx5 } from "react/jsx-runtime";
525
+ var DropzoneContext = createContext2(false);
526
+ var useDropzoneContext = () => useContext2(DropzoneContext);
522
527
  function Dropzone({
523
528
  children,
524
529
  className,
@@ -557,7 +562,7 @@ function Dropzone({
557
562
  }
558
563
  };
559
564
  const isDisabled = ctx.disabled || ctx.readOnly;
560
- return /* @__PURE__ */ jsx5(
565
+ return /* @__PURE__ */ jsx5(DropzoneContext.Provider, { value: true, children: /* @__PURE__ */ jsx5(
561
566
  "div",
562
567
  {
563
568
  ref: (node) => {
@@ -601,7 +606,7 @@ function Dropzone({
601
606
  },
602
607
  children
603
608
  }
604
- );
609
+ ) });
605
610
  }
606
611
  Dropzone.displayName = "FileUploadDropzone";
607
612
 
@@ -765,10 +770,13 @@ var Trigger = ({
765
770
  unstyled = false,
766
771
  design = "filled",
767
772
  intent = "basic",
773
+ size = "md",
774
+ shape = "rounded",
768
775
  ref,
769
776
  ...props
770
777
  }) => {
771
778
  const { inputRef, triggerRef, disabled, readOnly, description, isInvalid, isRequired } = useFileUploadContext();
779
+ const isInsideDropzone = useDropzoneContext();
772
780
  const handleClick = (e) => {
773
781
  e.stopPropagation();
774
782
  e.preventDefault();
@@ -776,26 +784,47 @@ var Trigger = ({
776
784
  inputRef.current?.click();
777
785
  }
778
786
  };
779
- const buttonComponent = unstyled ? "button" : Button;
780
- const Comp = asChild ? Slot : buttonComponent;
781
- return /* @__PURE__ */ jsx9(
782
- Comp,
783
- {
787
+ const handleRef = (node) => {
788
+ if (triggerRef) {
789
+ triggerRef.current = node;
790
+ }
791
+ if (ref) {
792
+ if (typeof ref === "function") {
793
+ ref(node);
794
+ } else {
795
+ ref.current = node;
796
+ }
797
+ }
798
+ };
799
+ let Component;
800
+ let componentProps;
801
+ if (isInsideDropzone) {
802
+ Component = "span";
803
+ const spanStyles = unstyled ? className : buttonStyles({
804
+ design,
805
+ intent,
806
+ size,
807
+ shape,
808
+ disabled: disabled || readOnly,
809
+ className
810
+ });
811
+ componentProps = {
812
+ ref: handleRef,
813
+ "data-spark-component": "file-upload-trigger",
814
+ className: spanStyles
815
+ // No onClick, no role, no tabIndex - Dropzone handles interaction
816
+ // No aria attributes here - they're on the Dropzone
817
+ };
818
+ } else {
819
+ const buttonComponent = unstyled ? "button" : Button;
820
+ Component = asChild ? Slot : buttonComponent;
821
+ componentProps = {
822
+ ref: handleRef,
784
823
  type: "button",
785
- ref: (node) => {
786
- if (triggerRef) {
787
- triggerRef.current = node;
788
- }
789
- if (ref) {
790
- if (typeof ref === "function") {
791
- ref(node);
792
- } else {
793
- ref.current = node;
794
- }
795
- }
796
- },
797
824
  design,
798
825
  intent,
826
+ size,
827
+ shape,
799
828
  "data-spark-component": "file-upload-trigger",
800
829
  className: cx7(className),
801
830
  disabled: disabled || readOnly,
@@ -803,10 +832,10 @@ var Trigger = ({
803
832
  "aria-describedby": description,
804
833
  "aria-invalid": isInvalid,
805
834
  "aria-required": isRequired,
806
- ...props,
807
- children
808
- }
809
- );
835
+ ...props
836
+ };
837
+ }
838
+ return /* @__PURE__ */ jsx9(Component, { ...componentProps, children });
810
839
  };
811
840
  Trigger.displayName = "FileUpload.Trigger";
812
841
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/file-upload/FileUpload.tsx","../../src/file-upload/utils.ts","../../src/file-upload/FileUploadAcceptedFile.tsx","../../src/file-upload/FileUploadItemDeleteTrigger.tsx","../../src/file-upload/FileUploadContext.tsx","../../src/file-upload/FileUploadDropzone.tsx","../../src/file-upload/FileUploadPreviewImage.tsx","../../src/file-upload/FileUploadRejectedFile.tsx","../../src/file-upload/FileUploadRejectedFileDeleteTrigger.tsx","../../src/file-upload/FileUploadTrigger.tsx","../../src/file-upload/index.ts"],"sourcesContent":["/* eslint-disable max-lines */\n/* eslint-disable max-lines-per-function */\nimport { useFormFieldControl } from '@spark-ui/components/form-field'\nimport { useCombinedState } from '@spark-ui/hooks/use-combined-state'\nimport { createContext, ReactNode, Ref, useContext, useId, useRef, useState } from 'react'\n\nimport { validateFileAccept, validateFileSize } from './utils'\n\nexport interface FileUploadProps {\n /**\n * Change the default rendered element for the one passed as a child, merging their props and behavior.\n */\n asChild?: boolean\n ref?: Ref<HTMLDivElement>\n children: ReactNode\n className?: string\n /**\n * Initial files to display when the component mounts (uncontrolled mode)\n */\n defaultValue?: File[]\n /**\n * Controlled files value (controlled mode)\n * When provided, the component becomes controlled\n */\n value?: File[]\n /**\n * Callback when files are accepted\n * @param details - Details about the accepted files\n */\n onFileAccept?: (details: FileAcceptDetails) => void\n /**\n * Callback when files are rejected\n * @param details - Details about the rejected files and their errors\n */\n onFileReject?: (details: FileRejectDetails) => void\n /**\n * Callback when files change (both accepted and rejected)\n * For controlled mode, use this to update the value prop by extracting details.acceptedFiles\n * @param details - Details about both accepted and rejected files\n */\n onFileChange?: (details: FileChangeDetails) => void\n /**\n * Whether multiple files can be selected\n * @default true\n */\n multiple?: boolean\n /**\n * Comma-separated list of accepted file types\n * Supports MIME types (e.g., \"image/*\", \"image/png\", \"application/pdf\")\n * and file extensions (e.g., \".pdf\", \".doc\", \".jpg\")\n * @example \"image/*\"\n * @example \".pdf,.doc\"\n * @example \"image/png,image/jpeg,.pdf\"\n */\n accept?: string\n /**\n * Maximum number of files that can be uploaded\n * Files beyond this limit will be rejected\n */\n maxFiles?: number\n /**\n * Maximum file size in bytes\n * Files larger than this will be rejected\n */\n maxFileSize?: number\n /**\n * Minimum file size in bytes\n * Files smaller than this will be rejected\n */\n minFileSize?: number\n /**\n * When `true`, prevents the user from interacting with the file upload\n */\n disabled?: boolean\n /**\n * When `true`, sets the file upload to read-only mode\n */\n readOnly?: boolean\n /**\n * The [BCP47](https://www.ietf.org/rfc/bcp/bcp47.txt) language code for the locale.\n * Used for formatting file sizes and error messages.\n * @default Browser locale or 'en' if not available\n */\n locale?: string\n}\n\nexport type FileUploadFileError =\n | 'TOO_MANY_FILES'\n | 'FILE_INVALID_TYPE'\n | 'FILE_TOO_LARGE'\n | 'FILE_TOO_SMALL'\n | 'FILE_INVALID'\n | 'FILE_EXISTS'\n\nexport interface RejectedFile {\n file: File\n errors: FileUploadFileError[]\n}\n\nexport interface FileAcceptDetails {\n files: File[]\n}\n\nexport interface FileRejectDetails {\n files: RejectedFile[]\n}\n\nexport interface FileChangeDetails {\n acceptedFiles: File[]\n rejectedFiles: RejectedFile[]\n}\n\nexport const FileUploadContext = createContext<{\n inputRef: React.RefObject<HTMLInputElement | null>\n files: File[]\n rejectedFiles: RejectedFile[]\n addFiles: (files: File[]) => void\n removeFile: (index: number) => void\n removeRejectedFile: (index: number) => void\n clearFiles: () => void\n clearRejectedFiles: () => void\n triggerRef: React.RefObject<HTMLElement | null>\n dropzoneRef: React.RefObject<HTMLElement | null>\n deleteButtonRefs: React.MutableRefObject<HTMLButtonElement[]>\n multiple: boolean\n maxFiles?: number\n maxFilesReached: boolean\n disabled: boolean\n readOnly: boolean\n locale: string\n description?: string\n isInvalid?: boolean\n isRequired?: boolean\n} | null>(null)\n\nconst ID_PREFIX = ':file-upload'\n\nexport const FileUpload = ({\n asChild: _asChild = false,\n children,\n defaultValue = [],\n value: controlledValue,\n onFileAccept,\n onFileReject,\n onFileChange,\n multiple = true,\n accept,\n maxFiles,\n maxFileSize,\n minFileSize,\n disabled: disabledProp = false,\n readOnly: readOnlyProp = false,\n locale,\n}: FileUploadProps) => {\n const field = useFormFieldControl()\n const {\n id: fieldId,\n name: fieldName,\n isInvalid,\n isRequired,\n description,\n disabled: fieldDisabled,\n readOnly: fieldReadOnly,\n } = field\n\n // Get default locale from browser or fallback to 'en'\n const defaultLocale =\n locale || (typeof navigator !== 'undefined' && navigator.language ? navigator.language : 'en')\n\n // Generate unique ID if none provided by FormField\n const internalId = useId()\n const inputId = fieldId || `${ID_PREFIX}-${internalId}`\n\n // Use FormField name or undefined (no hardcoded fallback)\n const inputName = fieldName\n\n const inputRef = useRef<HTMLInputElement>(null)\n const triggerRef = useRef<HTMLElement>(null)\n const dropzoneRef = useRef<HTMLElement>(null)\n const deleteButtonRefs = useRef<HTMLButtonElement[]>([])\n\n // Merge FormField props with component props (FormField takes precedence)\n const disabled = fieldDisabled ?? disabledProp\n const readOnly = fieldReadOnly ?? readOnlyProp\n\n // For controlled mode, use onFileChange to update value prop\n // useCombinedState doesn't need a callback - we'll call onFileChange manually in addFiles/removeFile\n const [filesState, setFilesState, ,] = useCombinedState(controlledValue, defaultValue)\n const files = filesState ?? []\n const setFiles = setFilesState as (value: File[] | ((prev: File[]) => File[])) => void\n const [rejectedFiles, setRejectedFiles] = useState<RejectedFile[]>([])\n\n const addFiles = (newFiles: File[]) => {\n // Don't allow adding files when disabled or readOnly\n if (disabled || readOnly) {\n return\n }\n\n // Reset rejectedFiles at the start of each new file addition attempt\n setRejectedFiles([])\n\n const newRejectedFiles: RejectedFile[] = []\n\n // Helper function to check if a file already exists\n // Compares by name and size to detect duplicates (lastModified can differ when re-selecting the same file)\n const fileExists = (file: File, existingFiles: File[]): boolean => {\n return existingFiles.some(\n existingFile => existingFile.name === file.name && existingFile.size === file.size\n )\n }\n\n // Helper function to add or update rejected file\n const addRejectedFile = (file: File, error: FileUploadFileError) => {\n const existingRejection = newRejectedFiles.find(\n rejected => rejected.file.name === file.name && rejected.file.size === file.size\n )\n\n if (existingRejection) {\n // Add error to existing rejection if not already present\n if (!existingRejection.errors.includes(error)) {\n existingRejection.errors.push(error)\n }\n } else {\n // Create new rejection\n newRejectedFiles.push({\n file,\n errors: [error],\n })\n }\n }\n\n setFiles((prev: File[]) => {\n const currentFiles = prev ?? []\n // Check maxFiles limit FIRST for all files (even if they will be rejected by other validations)\n // This allows a file to have multiple error codes (e.g., FILE_INVALID_TYPE + TOO_MANY_FILES)\n if (maxFiles !== undefined) {\n const currentCount = currentFiles.length\n const remainingSlots = maxFiles - currentCount\n\n if (remainingSlots <= 0) {\n // Already at max, mark all new files with TOO_MANY_FILES error\n newFiles.forEach(file => {\n addRejectedFile(file, 'TOO_MANY_FILES')\n })\n }\n }\n\n // Track files rejected by accept pattern\n let filteredFiles = newFiles\n if (accept) {\n const rejectedByAccept = newFiles.filter(file => !validateFileAccept(file, accept))\n rejectedByAccept.forEach(file => {\n addRejectedFile(file, 'FILE_INVALID_TYPE')\n })\n filteredFiles = newFiles.filter(file => validateFileAccept(file, accept))\n }\n\n // Track files rejected by size\n let validSizeFiles = filteredFiles\n if (minFileSize !== undefined || maxFileSize !== undefined) {\n validSizeFiles = filteredFiles.filter(file => {\n const validation = validateFileSize(file, minFileSize, maxFileSize, defaultLocale)\n if (!validation.valid) {\n if (maxFileSize !== undefined && file.size > maxFileSize) {\n addRejectedFile(file, 'FILE_TOO_LARGE')\n } else if (minFileSize !== undefined && file.size < minFileSize) {\n addRejectedFile(file, 'FILE_TOO_SMALL')\n } else {\n addRejectedFile(file, 'FILE_INVALID')\n }\n\n return false\n }\n\n return true\n })\n }\n\n // Check for duplicate files (both against existing files and within the current batch)\n // This must be done AFTER size validation but BEFORE maxFiles check\n const seenFiles = new Map<string, File>()\n const duplicateFiles: File[] = []\n const uniqueFiles = validSizeFiles.filter(file => {\n // Create a unique key for the file (name + size)\n // Using name and size only, as lastModified can differ when re-selecting the same file\n const fileKey = `${file.name}-${file.size}`\n\n // Check if file already exists in previously accepted files\n const existsInPrev = fileExists(file, currentFiles)\n if (existsInPrev) {\n duplicateFiles.push(file)\n addRejectedFile(file, 'FILE_EXISTS')\n\n return false\n }\n\n // Check if file already exists in the current batch\n if (seenFiles.has(fileKey)) {\n duplicateFiles.push(file)\n addRejectedFile(file, 'FILE_EXISTS')\n\n return false\n }\n\n // Mark this file as seen\n seenFiles.set(fileKey, file)\n\n return true\n })\n\n // If multiple is false, replace existing files with only the first new file\n let filesToAdd = multiple ? uniqueFiles : uniqueFiles.slice(0, 1)\n\n // Track files rejected by maxFiles limit (only for files that passed other validations)\n // Note: We already checked maxFiles at the beginning for ALL files to allow multiple error codes\n // This second check is to prevent adding files when we're at the limit\n if (maxFiles !== undefined) {\n const currentCount = currentFiles.length\n const remainingSlots = maxFiles - currentCount\n\n if (remainingSlots <= 0) {\n // Already at max, reject all new files (they should already have TOO_MANY_FILES error from the first check)\n filesToAdd.forEach(file => {\n addRejectedFile(file, 'TOO_MANY_FILES')\n })\n filesToAdd = []\n } else if (filesToAdd.length > remainingSlots) {\n // Reject all files if batch exceeds limit (\"all or nothing\" approach)\n filesToAdd.forEach(file => {\n addRejectedFile(file, 'TOO_MANY_FILES')\n })\n filesToAdd = []\n }\n }\n\n const updated = multiple ? [...currentFiles, ...filesToAdd] : filesToAdd\n\n // Add rejected files to state synchronously\n // Note: newRejectedFiles is mutated inside this setFiles callback, so it should be populated by now\n // Copy the array to avoid closure issues\n const rejectedFilesToAdd = [...newRejectedFiles]\n // Replace rejectedFiles completely (not accumulate)\n setRejectedFiles(rejectedFilesToAdd)\n\n // Call callbacks with the calculated values\n // Note: These callbacks are called synchronously with the new values\n // React will update the state asynchronously, but the callbacks receive the correct new values\n if (filesToAdd.length > 0 && onFileAccept) {\n onFileAccept({ files: filesToAdd })\n }\n\n if (rejectedFilesToAdd.length > 0 && onFileReject) {\n onFileReject({ files: rejectedFilesToAdd })\n }\n\n if (onFileChange) {\n onFileChange({\n acceptedFiles: updated,\n rejectedFiles: rejectedFilesToAdd,\n })\n }\n\n return updated\n })\n }\n\n const removeFile = (index: number) => {\n // Don't allow removing files when disabled or readOnly\n if (disabled || readOnly) {\n return\n }\n\n setFiles((prev: File[]) => {\n const currentFiles = prev ?? []\n const updated = currentFiles.filter((_: File, i: number) => i !== index)\n\n // Clean up TOO_MANY_FILES errors if we're now below the maxFiles limit\n let updatedRejectedFiles = rejectedFiles\n if (maxFiles !== undefined && updated.length < maxFiles) {\n updatedRejectedFiles = rejectedFiles.filter(\n rejected => !rejected.errors.includes('TOO_MANY_FILES')\n )\n setRejectedFiles(updatedRejectedFiles)\n }\n\n // Call onFileChange for controlled mode\n if (onFileChange) {\n onFileChange({\n acceptedFiles: updated,\n rejectedFiles: updatedRejectedFiles,\n })\n }\n\n return updated\n })\n }\n\n const clearFiles = () => {\n // Don't allow clearing files when disabled or readOnly\n if (disabled || readOnly) {\n return\n }\n\n setFiles([])\n setRejectedFiles([])\n deleteButtonRefs.current = []\n\n // Call onFileChange for controlled mode\n if (onFileChange) {\n onFileChange({\n acceptedFiles: [],\n rejectedFiles: [],\n })\n }\n }\n\n const removeRejectedFile = (index: number) => {\n // Don't allow removing rejected files when disabled or readOnly\n if (disabled || readOnly) {\n return\n }\n\n setRejectedFiles(prev => prev.filter((_, i) => i !== index))\n }\n\n const clearRejectedFiles = () => {\n setRejectedFiles([])\n }\n\n const maxFilesReached = maxFiles !== undefined && files.length >= maxFiles\n\n return (\n <FileUploadContext.Provider\n value={{\n inputRef,\n files,\n rejectedFiles,\n addFiles,\n removeFile,\n removeRejectedFile,\n clearFiles,\n clearRejectedFiles,\n triggerRef,\n dropzoneRef,\n deleteButtonRefs,\n multiple,\n maxFiles,\n maxFilesReached,\n disabled,\n readOnly,\n locale: defaultLocale,\n description,\n isInvalid,\n isRequired,\n }}\n >\n {/* <Comp data-spark-component=\"file-upload\" className={cx('relative', className)} {...props}> */}\n <div className=\"relative\">\n {children}\n <input\n ref={inputRef}\n type=\"file\"\n tabIndex={-1}\n id={inputId}\n multiple={multiple}\n name={inputName}\n accept={accept}\n disabled={disabled}\n readOnly={readOnly && !disabled}\n required={isRequired}\n aria-invalid={isInvalid}\n aria-describedby={description}\n className=\"sr-only\"\n onChange={e => {\n if (e.target.files && !disabled && !readOnly) {\n addFiles(Array.from(e.target.files))\n // Reset input value to allow selecting the same file again\n try {\n e.target.value = ''\n } catch {\n // Ignore error if value is read-only (e.g., in tests)\n }\n }\n }}\n />\n </div>\n {/* </Comp> */}\n </FileUploadContext.Provider>\n )\n}\n\nFileUpload.displayName = 'FileUpload'\n\nexport const useFileUploadContext = () => {\n const context = useContext(FileUploadContext)\n\n if (!context) {\n throw Error('useFileUploadContext must be used within a FileUpload provider')\n }\n\n return context\n}\n","import { CvOutline } from '@spark-ui/icons/CvOutline'\nimport { FilePdfOutline } from '@spark-ui/icons/FilePdfOutline'\nimport { ImageOutline } from '@spark-ui/icons/ImageOutline'\nimport { PlayOutline } from '@spark-ui/icons/PlayOutline'\nimport { createElement, ReactElement } from 'react'\n\n/**\n * Validates if a file matches the accept patterns\n * Supports MIME types (e.g., \"image/*\", \"image/png\", \"application/pdf\")\n * and file extensions (e.g., \".pdf\", \".doc\", \".jpg\")\n */\nexport function validateFileAccept(file: File, accept: string): boolean {\n if (!accept) {\n return true\n }\n\n const patterns = accept.split(',').map(pattern => pattern.trim())\n\n return patterns.some(pattern => {\n // Handle MIME type patterns (e.g., \"image/*\", \"image/png\")\n if (pattern.includes('/')) {\n if (pattern.endsWith('/*')) {\n // Wildcard MIME type (e.g., \"image/*\")\n const baseType = pattern.slice(0, -2)\n\n return file.type.startsWith(baseType + '/')\n }\n // Exact MIME type (e.g., \"image/png\")\n\n return file.type === pattern\n }\n\n // Handle file extension patterns (e.g., \".pdf\", \".doc\")\n if (pattern.startsWith('.')) {\n const extension = pattern.toLowerCase()\n const fileName = file.name.toLowerCase()\n\n return fileName.endsWith(extension)\n }\n\n // Handle extension without dot (e.g., \"pdf\", \"doc\")\n const extension = '.' + pattern.toLowerCase()\n const fileName = file.name.toLowerCase()\n\n return fileName.endsWith(extension)\n })\n}\n\n/**\n * Validates if a file size is within the allowed range\n * @param file - The file to validate\n * @param minFileSize - Minimum file size in bytes\n * @param maxFileSize - Maximum file size in bytes\n * @param locale - Locale code for error messages. Defaults to browser locale or 'en'\n * @returns Object with validation result and error message if invalid\n */\nexport function validateFileSize(\n file: File,\n minFileSize?: number,\n maxFileSize?: number,\n locale?: string\n): { valid: boolean; error?: string } {\n const defaultLocale = locale || getDefaultLocale()\n if (minFileSize !== undefined && file.size < minFileSize) {\n const errorMessage = `File \"${file.name}\" is too small. Minimum size is ${formatFileSize(minFileSize, defaultLocale)}.`\n\n return {\n valid: false,\n error: errorMessage,\n }\n }\n\n if (maxFileSize !== undefined && file.size > maxFileSize) {\n const errorMessage = `File \"${file.name}\" is too large. Maximum size is ${formatFileSize(maxFileSize, defaultLocale)}.`\n\n return {\n valid: false,\n error: errorMessage,\n }\n }\n\n return { valid: true }\n}\n\n/**\n * Gets the default locale from the browser or falls back to 'en'\n * @returns The browser's locale or 'en' as fallback\n */\nfunction getDefaultLocale(): string {\n if (typeof navigator !== 'undefined' && navigator.language) {\n return navigator.language\n }\n\n return 'en'\n}\n\n/**\n * Formats file size in bytes to human-readable format\n * @param bytes - File size in bytes\n * @param locale - Locale code (e.g., 'en', 'fr'). Defaults to browser locale or 'en'\n * @returns Formatted file size string with appropriate unit\n */\nexport function formatFileSize(bytes: number, locale?: string): string {\n const defaultLocale = locale || getDefaultLocale()\n // Normalize locale (e.g., 'fr' -> 'fr-FR', 'en' -> 'en-US')\n let normalizedLocale = defaultLocale\n if (defaultLocale.length === 2) {\n normalizedLocale = defaultLocale === 'fr' ? 'fr-FR' : 'en-US'\n }\n\n if (bytes === 0) {\n const formatter = new Intl.NumberFormat(normalizedLocale, {\n style: 'unit',\n unit: 'byte',\n unitDisplay: 'long',\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n })\n\n return formatter.format(0)\n }\n\n const k = 1024\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n\n // Map to Intl.NumberFormat supported units\n const units = ['byte', 'kilobyte', 'megabyte', 'gigabyte'] as const\n const unit = units[i] || 'byte'\n\n const size = bytes / Math.pow(k, i)\n\n // Use 'long' display for bytes to get proper pluralization (bytes/octets)\n // Use 'short' display for other units (KB/MB/GB, Ko/Mo/Go)\n const unitDisplay = i === 0 ? 'long' : 'short'\n\n // Use Intl.NumberFormat with unit style to format number and unit according to locale\n const formatter = new Intl.NumberFormat(normalizedLocale, {\n style: 'unit',\n unit,\n unitDisplay,\n minimumFractionDigits: 0,\n maximumFractionDigits: 2,\n })\n\n return formatter.format(size)\n}\n\n/**\n * Returns the appropriate icon component based on the file type\n * @param file - The file to get the icon for\n * @returns React element representing the icon component\n */\nexport function getFileIcon(file: File): ReactElement {\n const fileType = file.type.toLowerCase()\n const fileName = file.name.toLowerCase()\n\n // Check for images\n if (fileType.startsWith('image/') || /\\.(jpg|jpeg|png|gif|bmp|webp|svg|ico)$/i.test(fileName)) {\n return createElement(ImageOutline)\n }\n\n // Check for PDFs\n if (fileType === 'application/pdf' || fileName.endsWith('.pdf')) {\n return createElement(FilePdfOutline)\n }\n\n // Check for videos\n if (fileType.startsWith('video/') || /\\.(mp4|avi|mov|wmv|flv|webm|mkv)$/i.test(fileName)) {\n return createElement(PlayOutline)\n }\n\n // Default icon for other file types\n return createElement(CvOutline)\n}\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, Ref } from 'react'\n\nimport { Icon } from '../icon'\nimport { Progress } from '../progress'\nimport { useFileUploadContext } from './FileUpload'\nimport { ItemDeleteTrigger } from './FileUploadItemDeleteTrigger'\nimport { formatFileSize, getFileIcon } from './utils'\n\nexport interface FileUploadAcceptedFileProps extends ComponentPropsWithoutRef<'li'> {\n /**\n * Change the default rendered element for the one passed as a child, merging their props and behavior.\n */\n asChild?: boolean\n ref?: Ref<HTMLLIElement>\n /**\n * The file to display\n */\n file: File\n /**\n * Upload progress value (0-100). When provided, displays a progress bar at the bottom of the file item.\n */\n uploadProgress?: number\n /**\n * Accessible label for the delete button\n */\n deleteButtonAriaLabel: string\n /**\n * Accessible label for the progress bar. Required when uploadProgress is provided.\n */\n progressAriaLabel?: string\n className?: string\n}\n\nexport const AcceptedFile = ({\n asChild: _asChild = false,\n className,\n file,\n uploadProgress,\n deleteButtonAriaLabel,\n progressAriaLabel,\n ...props\n}: FileUploadAcceptedFileProps) => {\n const { locale } = useFileUploadContext()\n\n return (\n <li\n data-spark-component=\"file-upload-accepted-file\"\n className={cx(\n 'relative',\n 'default:bg-surface default:border-sm default:border-outline default:p-md default:rounded-md',\n 'gap-md flex items-center justify-between default:w-full',\n className\n )}\n {...props}\n >\n <div className=\"size-sz-40 bg-support-container flex items-center justify-center rounded-md\">\n <Icon size=\"md\">{getFileIcon(file)}</Icon>\n </div>\n\n <div className=\"min-w-0 flex-1\">\n <div className=\"gap-md flex flex-row items-center justify-between\">\n <p className=\"text-body-2 truncate font-medium\">{file.name}</p>\n <p className=\"text-caption opacity-dim-1\">{formatFileSize(file.size, locale)}</p>\n </div>\n {uploadProgress !== undefined && (\n <div className=\"mt-md\">\n <Progress value={uploadProgress} max={100} aria-label={progressAriaLabel} />\n </div>\n )}\n </div>\n\n <ItemDeleteTrigger aria-label={deleteButtonAriaLabel} file={file} />\n </li>\n )\n}\n\nAcceptedFile.displayName = 'FileUpload.AcceptedFile'\n","import { Close } from '@spark-ui/icons/Close'\nimport { cx } from 'class-variance-authority'\nimport { useRef } from 'react'\n\nimport { Icon } from '../icon'\nimport { IconButton } from '../icon-button'\nimport { useFileUploadContext } from './FileUpload'\n\nexport interface FileUploadItemDeleteTriggerProps extends React.ComponentProps<typeof IconButton> {\n /**\n * The file to delete\n */\n file: File\n}\n\nexport const ItemDeleteTrigger = ({\n className,\n file,\n onClick,\n ...props\n}: FileUploadItemDeleteTriggerProps) => {\n const { removeFile, triggerRef, dropzoneRef, deleteButtonRefs, disabled, readOnly, files } =\n useFileUploadContext()\n const buttonRef = useRef<HTMLButtonElement>(null)\n\n // Find the index of the file using name + size (consistent with duplicate detection logic)\n const fileIndex = files.findIndex(f => f.name === file.name && f.size === file.size)\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n // Don't allow removing files when disabled or readOnly\n if (disabled || readOnly) {\n return\n }\n\n // Remove the file\n removeFile(fileIndex)\n\n // Handle focus after removal\n setTimeout(() => {\n // Get all remaining delete buttons from the refs array\n const remainingButtons = deleteButtonRefs.current.filter(Boolean)\n\n if (remainingButtons.length > 0) {\n // Find the button that should receive focus\n // We want to focus on the button that takes the same position as the removed one\n // If that position doesn't exist (we removed the last item), focus on the previous one\n const targetIndex = Math.min(fileIndex, remainingButtons.length - 1)\n const nextButton = remainingButtons[targetIndex]\n\n if (nextButton) {\n nextButton.focus()\n }\n } else {\n // No more files, focus on trigger or dropzone\n const focusTarget = triggerRef.current || dropzoneRef.current\n if (focusTarget) {\n focusTarget.focus()\n }\n }\n }, 0)\n\n onClick?.(e)\n }\n\n const setRef = (node: HTMLButtonElement | null) => {\n buttonRef.current = node\n if (node) {\n // Ensure the array is large enough\n while (deleteButtonRefs.current.length <= fileIndex) {\n deleteButtonRefs.current.push(null as any)\n }\n deleteButtonRefs.current[fileIndex] = node\n } else {\n // Remove the ref when component unmounts\n if (deleteButtonRefs.current[fileIndex]) {\n deleteButtonRefs.current[fileIndex] = null as any\n }\n }\n }\n\n return (\n <IconButton\n ref={setRef}\n data-spark-component=\"file-upload-item-delete-trigger\"\n className={cx(className)}\n onClick={handleClick}\n disabled={disabled || readOnly}\n size=\"sm\"\n design=\"contrast\"\n intent=\"surface\"\n {...props}\n >\n <Icon size=\"sm\">\n <Close />\n </Icon>\n </IconButton>\n )\n}\n\nItemDeleteTrigger.displayName = 'FileUpload.ItemDeleteTrigger'\n","import { ReactNode } from 'react'\n\nimport { type RejectedFile, useFileUploadContext } from './FileUpload'\nimport { formatFileSize } from './utils'\n\nexport interface FileUploadContextProps {\n /**\n * Render prop that receives acceptedFiles, rejectedFiles, formatFileSize, and locale\n */\n children: (props: {\n acceptedFiles: File[]\n rejectedFiles: RejectedFile[]\n formatFileSize: (bytes: number, locale?: string) => string\n locale?: string\n }) => ReactNode\n}\n\nexport const Context = ({ children }: FileUploadContextProps) => {\n const { files = [], rejectedFiles = [], locale } = useFileUploadContext()\n\n return (\n <>\n {children({\n acceptedFiles: files,\n rejectedFiles,\n formatFileSize,\n locale,\n })}\n </>\n )\n}\n\nContext.displayName = 'FileUpload.Context'\n","import { cx } from 'class-variance-authority'\nimport { useRef } from 'react'\n\nimport { useFileUploadContext } from './FileUpload'\n\nexport function Dropzone({\n children,\n className,\n unstyled = false,\n}: {\n children?: React.ReactNode\n className?: string\n unstyled?: boolean\n}) {\n const ctx = useFileUploadContext()\n const dropzoneRef = useRef<HTMLDivElement>(null)\n\n if (!ctx) throw new Error('FileUploadDropzone must be used inside <FileUpload>')\n\n const handleDrop = (e: React.DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n e.currentTarget.setAttribute('data-drag-over', 'false')\n\n // Don't allow dropping files when disabled or readOnly\n if (ctx.disabled || ctx.readOnly) {\n return\n }\n\n const files = e.dataTransfer.files\n\n // Add files to the context\n // Convert to array - handle both FileList and array (for tests)\n let filesArray: File[] = []\n if (files) {\n filesArray = Array.isArray(files) ? [...files] : Array.from(files)\n }\n\n if (filesArray.length > 0) {\n ctx.addFiles(filesArray)\n }\n }\n\n const handleClick = () => {\n if (!ctx.disabled && !ctx.readOnly) {\n ctx.inputRef.current?.click()\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n if (!ctx.disabled && !ctx.readOnly) {\n ctx.inputRef.current?.click()\n }\n }\n }\n\n const isDisabled = ctx.disabled || ctx.readOnly\n\n return (\n <div\n ref={node => {\n dropzoneRef.current = node\n if (ctx.dropzoneRef) {\n ctx.dropzoneRef.current = node\n }\n }}\n role=\"button\"\n tabIndex={isDisabled ? -1 : 0}\n aria-disabled={ctx.disabled ? true : undefined}\n aria-describedby={ctx.description}\n aria-invalid={ctx.isInvalid}\n aria-required={ctx.isRequired}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n onDrop={handleDrop}\n onDragOver={e => {\n e.preventDefault()\n }}\n className={\n unstyled\n ? className\n : cx(\n 'default:bg-surface default:border-sm default:border-outline default:relative default:rounded-lg default:border-dashed',\n 'gap-lg flex flex-col items-center justify-center text-center',\n 'default:p-xl',\n 'transition-colors duration-200',\n !isDisabled && 'default:hover:bg-surface-hovered',\n 'data-[drag-over=true]:border-outline-high data-[drag-over=true]:bg-surface-hovered data-[drag-over=true]:border-solid',\n // Disabled: more visually disabled (opacity + cursor)\n ctx.disabled && 'cursor-not-allowed opacity-50',\n // ReadOnly: less visually disabled (just cursor, no opacity)\n ctx.readOnly && !ctx.disabled && 'cursor-default',\n className\n )\n }\n onDragEnter={e => {\n if (!isDisabled) {\n e.currentTarget.setAttribute('data-drag-over', 'true')\n }\n }}\n onDragLeave={e => {\n e.currentTarget.setAttribute('data-drag-over', 'false')\n }}\n >\n {children}\n </div>\n )\n}\n\nDropzone.displayName = 'FileUploadDropzone'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, Ref, useEffect, useState } from 'react'\n\nexport interface FileUploadPreviewImageProps extends ComponentPropsWithoutRef<'div'> {\n /**\n * Change the default rendered element for the one passed as a child, merging their props and behavior.\n */\n asChild?: boolean\n ref?: Ref<HTMLDivElement>\n className?: string\n /**\n * The file to preview\n */\n file: File\n /**\n * Fallback content when file is not an image or preview fails\n */\n fallback?: React.ReactNode\n}\n\nexport const PreviewImage = ({\n asChild: _asChild = false,\n className,\n file,\n fallback = '📄',\n ...props\n}: FileUploadPreviewImageProps) => {\n const [imageError, setImageError] = useState(false)\n const [imageLoaded, setImageLoaded] = useState(false)\n\n const isImage = file.type.startsWith('image/')\n const imageUrl = isImage ? URL.createObjectURL(file) : null\n\n // Clean up the object URL when component unmounts or file changes\n useEffect(() => {\n return () => {\n if (imageUrl) {\n URL.revokeObjectURL(imageUrl)\n }\n }\n }, [imageUrl])\n\n if (!isImage || imageError) {\n return (\n <div\n data-spark-component=\"file-upload-preview-image\"\n className={cx(\n 'bg-neutral-container flex items-center justify-center rounded-md',\n className\n )}\n {...props}\n >\n {fallback}\n </div>\n )\n }\n\n return (\n <div\n data-spark-component=\"file-upload-preview-image\"\n className={cx('bg-neutral-container overflow-hidden', className)}\n {...props}\n >\n <img\n src={imageUrl!}\n alt={file.name}\n className={cx('size-full object-cover', !imageLoaded && 'opacity-0')}\n onLoad={() => setImageLoaded(true)}\n onError={() => setImageError(true)}\n />\n {!imageLoaded && (\n <div className=\"absolute inset-0 flex items-center justify-center\">{fallback}</div>\n )}\n </div>\n )\n}\n\nPreviewImage.displayName = 'FileUpload.PreviewImage'\n","import { WarningOutline } from '@spark-ui/icons/WarningOutline'\nimport { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, Ref } from 'react'\n\nimport { Icon } from '../icon'\nimport {\n type FileUploadFileError,\n type RejectedFile as RejectedFileType,\n useFileUploadContext,\n} from './FileUpload'\nimport { RejectedFileDeleteTrigger } from './FileUploadRejectedFileDeleteTrigger'\nimport { formatFileSize } from './utils'\n\nexport interface FileUploadRejectedFileProps extends ComponentPropsWithoutRef<'li'> {\n /**\n * Change the default rendered element for the one passed as a child, merging their props and behavior.\n */\n asChild?: boolean\n ref?: Ref<HTMLLIElement>\n /**\n * The rejected file to display\n */\n rejectedFile: RejectedFileType\n /**\n * Function to render the error message for each error code\n * @param error - The error code\n * @returns The error message to display\n */\n renderError: (error: FileUploadFileError) => string\n /**\n * Accessible label for the delete button\n */\n deleteButtonAriaLabel: string\n className?: string\n}\n\nexport const RejectedFile = ({\n asChild: _asChild = false,\n className,\n rejectedFile,\n renderError,\n deleteButtonAriaLabel,\n ...props\n}: FileUploadRejectedFileProps) => {\n const { locale } = useFileUploadContext()\n\n return (\n <li\n data-spark-component=\"file-upload-rejected-file\"\n className={cx(\n 'relative',\n 'default:bg-surface default:border-sm default:border-outline default:p-md default:rounded-md',\n 'gap-md flex items-center justify-between default:w-full',\n 'border-error border-md',\n className\n )}\n {...props}\n >\n <div className=\"size-sz-40 bg-error-container flex items-center justify-center rounded-md\">\n <Icon size=\"md\" className=\"text-error\">\n <WarningOutline />\n </Icon>\n </div>\n\n <div className=\"min-w-0 flex-1\">\n <div className=\"gap-md flex flex-col\">\n <div className=\"gap-md flex flex-row items-center justify-between\">\n <p className=\"text-body-2 truncate font-medium\">{rejectedFile.file.name}</p>\n <p className=\"text-caption opacity-dim-1\">\n {formatFileSize(rejectedFile.file.size, locale)}\n </p>\n </div>\n <div className=\"gap-xs flex flex-col\">\n {rejectedFile.errors.map((error, errorIndex) => (\n <div key={errorIndex} className=\"text-caption text-error\" data-error-code={error}>\n {renderError(error)}\n </div>\n ))}\n </div>\n </div>\n </div>\n\n <RejectedFileDeleteTrigger aria-label={deleteButtonAriaLabel} rejectedFile={rejectedFile} />\n </li>\n )\n}\n\nRejectedFile.displayName = 'FileUpload.RejectedFile'\n","import { Close } from '@spark-ui/icons/Close'\nimport { cx } from 'class-variance-authority'\nimport { useRef } from 'react'\n\nimport { Icon } from '../icon'\nimport { IconButton } from '../icon-button'\nimport { type RejectedFile as RejectedFileType, useFileUploadContext } from './FileUpload'\n\nexport interface FileUploadRejectedFileDeleteTriggerProps\n extends React.ComponentProps<typeof IconButton> {\n /**\n * The rejected file to remove\n */\n rejectedFile: RejectedFileType\n}\n\nexport const RejectedFileDeleteTrigger = ({\n className,\n rejectedFile,\n onClick,\n ...props\n}: FileUploadRejectedFileDeleteTriggerProps) => {\n const { removeRejectedFile, triggerRef, dropzoneRef, disabled, readOnly, rejectedFiles } =\n useFileUploadContext()\n const buttonRef = useRef<HTMLButtonElement>(null)\n\n // Find the index of the rejected file using name + size (consistent with duplicate detection logic)\n const rejectedFileIndex = rejectedFiles.findIndex(\n rf => rf.file.name === rejectedFile.file.name && rf.file.size === rejectedFile.file.size\n )\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n // Don't allow removing rejected files when disabled or readOnly\n if (disabled || readOnly) {\n return\n }\n\n // Remove the rejected file\n removeRejectedFile(rejectedFileIndex)\n\n // Handle focus after removal\n setTimeout(() => {\n // Try to focus on trigger or dropzone if available\n const focusTarget = triggerRef.current || dropzoneRef.current\n if (focusTarget) {\n focusTarget.focus()\n }\n }, 0)\n\n onClick?.(e)\n }\n\n return (\n <IconButton\n ref={buttonRef}\n data-spark-component=\"file-upload-rejected-file-delete-trigger\"\n className={cx(className)}\n onClick={handleClick}\n disabled={disabled || readOnly}\n size=\"sm\"\n design=\"contrast\"\n intent=\"surface\"\n {...props}\n >\n <Icon size=\"sm\">\n <Close />\n </Icon>\n </IconButton>\n )\n}\n\nRejectedFileDeleteTrigger.displayName = 'FileUpload.RejectedFileDeleteTrigger'\n","import { cx } from 'class-variance-authority'\nimport React, { ReactNode, Ref } from 'react'\n\nimport { Button, type ButtonProps } from '../button'\nimport { Slot } from '../slot'\nimport { useFileUploadContext } from './FileUpload'\n\nexport interface FileUploadTriggerProps extends Omit<ButtonProps, 'children' | 'disabled'> {\n ref?: Ref<HTMLButtonElement>\n className?: string\n children: ReactNode\n unstyled?: boolean\n}\n\nexport const Trigger = ({\n className,\n children,\n asChild = false,\n unstyled = false,\n design = 'filled',\n intent = 'basic',\n ref,\n ...props\n}: FileUploadTriggerProps) => {\n const { inputRef, triggerRef, disabled, readOnly, description, isInvalid, isRequired } =\n useFileUploadContext()\n\n const handleClick = (e: React.MouseEvent) => {\n e.stopPropagation()\n e.preventDefault()\n if (!disabled && !readOnly) {\n inputRef.current?.click()\n }\n }\n\n const buttonComponent = unstyled ? 'button' : Button\n const Comp = asChild ? Slot : buttonComponent\n\n return (\n <Comp\n type=\"button\"\n ref={(node: HTMLElement | null) => {\n // Forward ref to both the context ref and the user ref\n if (triggerRef) {\n triggerRef.current = node\n }\n if (ref) {\n if (typeof ref === 'function') {\n ref(node as HTMLButtonElement)\n } else {\n ref.current = node as HTMLButtonElement\n }\n }\n }}\n design={design}\n intent={intent}\n data-spark-component=\"file-upload-trigger\"\n className={cx(className)}\n disabled={disabled || readOnly}\n onClick={handleClick}\n aria-describedby={description}\n aria-invalid={isInvalid}\n aria-required={isRequired}\n {...props}\n >\n {children}\n </Comp>\n )\n}\n\nTrigger.displayName = 'FileUpload.Trigger'\n","import {\n type FileAcceptDetails,\n type FileChangeDetails,\n type FileRejectDetails,\n FileUpload as Root,\n type FileUploadFileError,\n type RejectedFile,\n} from './FileUpload'\nimport { AcceptedFile } from './FileUploadAcceptedFile'\nimport { Context } from './FileUploadContext'\nimport { Dropzone } from './FileUploadDropzone'\nimport { ItemDeleteTrigger } from './FileUploadItemDeleteTrigger'\nimport { PreviewImage } from './FileUploadPreviewImage'\nimport { RejectedFile as RejectedFileComponent } from './FileUploadRejectedFile'\nimport { RejectedFileDeleteTrigger } from './FileUploadRejectedFileDeleteTrigger'\nimport { Trigger } from './FileUploadTrigger'\n\nexport type {\n FileAcceptDetails,\n FileChangeDetails,\n FileRejectDetails,\n RejectedFile,\n FileUploadFileError,\n}\n\nexport const FileUpload: typeof Root & {\n Trigger: typeof Trigger\n Dropzone: typeof Dropzone\n Context: typeof Context\n ItemDeleteTrigger: typeof ItemDeleteTrigger\n PreviewImage: typeof PreviewImage\n AcceptedFile: typeof AcceptedFile\n RejectedFile: typeof RejectedFileComponent\n RejectedFileDeleteTrigger: typeof RejectedFileDeleteTrigger\n} = Object.assign(Root, {\n // Main input components\n Trigger,\n Dropzone,\n // Context components\n Context,\n AcceptedFile,\n RejectedFile: RejectedFileComponent,\n // Helpers for custom renders\n PreviewImage,\n ItemDeleteTrigger,\n RejectedFileDeleteTrigger,\n})\n\nFileUpload.displayName = 'FileUpload'\nTrigger.displayName = 'FileUpload.Trigger'\nDropzone.displayName = 'FileUpload.Dropzone'\nContext.displayName = 'FileUpload.Context'\nItemDeleteTrigger.displayName = 'FileUpload.ItemDeleteTrigger'\nPreviewImage.displayName = 'FileUpload.PreviewImage'\nAcceptedFile.displayName = 'FileUpload.AcceptedFile'\nRejectedFileComponent.displayName = 'FileUpload.RejectedFile'\nRejectedFileDeleteTrigger.displayName = 'FileUpload.RejectedFileDeleteTrigger'\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAEA,SAAS,2BAA2B;AACpC,SAAS,wBAAwB;AACjC,SAAS,eAA+B,YAAY,OAAO,QAAQ,gBAAgB;;;ACJnF,SAAS,iBAAiB;AAC1B,SAAS,sBAAsB;AAC/B,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAC5B,SAAS,qBAAmC;AAOrC,SAAS,mBAAmB,MAAY,QAAyB;AACtE,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,OAAO,MAAM,GAAG,EAAE,IAAI,aAAW,QAAQ,KAAK,CAAC;AAEhE,SAAO,SAAS,KAAK,aAAW;AAE9B,QAAI,QAAQ,SAAS,GAAG,GAAG;AACzB,UAAI,QAAQ,SAAS,IAAI,GAAG;AAE1B,cAAM,WAAW,QAAQ,MAAM,GAAG,EAAE;AAEpC,eAAO,KAAK,KAAK,WAAW,WAAW,GAAG;AAAA,MAC5C;AAGA,aAAO,KAAK,SAAS;AAAA,IACvB;AAGA,QAAI,QAAQ,WAAW,GAAG,GAAG;AAC3B,YAAMA,aAAY,QAAQ,YAAY;AACtC,YAAMC,YAAW,KAAK,KAAK,YAAY;AAEvC,aAAOA,UAAS,SAASD,UAAS;AAAA,IACpC;AAGA,UAAM,YAAY,MAAM,QAAQ,YAAY;AAC5C,UAAM,WAAW,KAAK,KAAK,YAAY;AAEvC,WAAO,SAAS,SAAS,SAAS;AAAA,EACpC,CAAC;AACH;AAUO,SAAS,iBACd,MACA,aACA,aACA,QACoC;AACpC,QAAM,gBAAgB,UAAU,iBAAiB;AACjD,MAAI,gBAAgB,UAAa,KAAK,OAAO,aAAa;AACxD,UAAM,eAAe,SAAS,KAAK,IAAI,mCAAmC,eAAe,aAAa,aAAa,CAAC;AAEpH,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI,gBAAgB,UAAa,KAAK,OAAO,aAAa;AACxD,UAAM,eAAe,SAAS,KAAK,IAAI,mCAAmC,eAAe,aAAa,aAAa,CAAC;AAEpH,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,KAAK;AACvB;AAMA,SAAS,mBAA2B;AAClC,MAAI,OAAO,cAAc,eAAe,UAAU,UAAU;AAC1D,WAAO,UAAU;AAAA,EACnB;AAEA,SAAO;AACT;AAQO,SAAS,eAAe,OAAe,QAAyB;AACrE,QAAM,gBAAgB,UAAU,iBAAiB;AAEjD,MAAI,mBAAmB;AACvB,MAAI,cAAc,WAAW,GAAG;AAC9B,uBAAmB,kBAAkB,OAAO,UAAU;AAAA,EACxD;AAEA,MAAI,UAAU,GAAG;AACf,UAAME,aAAY,IAAI,KAAK,aAAa,kBAAkB;AAAA,MACxD,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,uBAAuB;AAAA,MACvB,uBAAuB;AAAA,IACzB,CAAC;AAED,WAAOA,WAAU,OAAO,CAAC;AAAA,EAC3B;AAEA,QAAM,IAAI;AACV,QAAM,IAAI,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,CAAC,CAAC;AAGlD,QAAM,QAAQ,CAAC,QAAQ,YAAY,YAAY,UAAU;AACzD,QAAM,OAAO,MAAM,CAAC,KAAK;AAEzB,QAAM,OAAO,QAAQ,KAAK,IAAI,GAAG,CAAC;AAIlC,QAAM,cAAc,MAAM,IAAI,SAAS;AAGvC,QAAM,YAAY,IAAI,KAAK,aAAa,kBAAkB;AAAA,IACxD,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA,uBAAuB;AAAA,IACvB,uBAAuB;AAAA,EACzB,CAAC;AAED,SAAO,UAAU,OAAO,IAAI;AAC9B;AAOO,SAAS,YAAY,MAA0B;AACpD,QAAM,WAAW,KAAK,KAAK,YAAY;AACvC,QAAM,WAAW,KAAK,KAAK,YAAY;AAGvC,MAAI,SAAS,WAAW,QAAQ,KAAK,0CAA0C,KAAK,QAAQ,GAAG;AAC7F,WAAO,cAAc,YAAY;AAAA,EACnC;AAGA,MAAI,aAAa,qBAAqB,SAAS,SAAS,MAAM,GAAG;AAC/D,WAAO,cAAc,cAAc;AAAA,EACrC;AAGA,MAAI,SAAS,WAAW,QAAQ,KAAK,qCAAqC,KAAK,QAAQ,GAAG;AACxF,WAAO,cAAc,WAAW;AAAA,EAClC;AAGA,SAAO,cAAc,SAAS;AAChC;;;AD4RM,SAEE,KAFF;AAzVC,IAAM,oBAAoB,cAqBvB,IAAI;AAEd,IAAM,YAAY;AAEX,IAAM,aAAa,CAAC;AAAA,EACzB,SAAS,WAAW;AAAA,EACpB;AAAA,EACA,eAAe,CAAC;AAAA,EAChB,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU,eAAe;AAAA,EACzB,UAAU,eAAe;AAAA,EACzB;AACF,MAAuB;AACrB,QAAM,QAAQ,oBAAoB;AAClC,QAAM;AAAA,IACJ,IAAI;AAAA,IACJ,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,EACZ,IAAI;AAGJ,QAAM,gBACJ,WAAW,OAAO,cAAc,eAAe,UAAU,WAAW,UAAU,WAAW;AAG3F,QAAM,aAAa,MAAM;AACzB,QAAM,UAAU,WAAW,GAAG,SAAS,IAAI,UAAU;AAGrD,QAAM,YAAY;AAElB,QAAM,WAAW,OAAyB,IAAI;AAC9C,QAAM,aAAa,OAAoB,IAAI;AAC3C,QAAM,cAAc,OAAoB,IAAI;AAC5C,QAAM,mBAAmB,OAA4B,CAAC,CAAC;AAGvD,QAAM,WAAW,iBAAiB;AAClC,QAAM,WAAW,iBAAiB;AAIlC,QAAM,CAAC,YAAY,eAAe,CAAC,IAAI,iBAAiB,iBAAiB,YAAY;AACrF,QAAM,QAAQ,cAAc,CAAC;AAC7B,QAAM,WAAW;AACjB,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAyB,CAAC,CAAC;AAErE,QAAM,WAAW,CAAC,aAAqB;AAErC,QAAI,YAAY,UAAU;AACxB;AAAA,IACF;AAGA,qBAAiB,CAAC,CAAC;AAEnB,UAAM,mBAAmC,CAAC;AAI1C,UAAM,aAAa,CAAC,MAAY,kBAAmC;AACjE,aAAO,cAAc;AAAA,QACnB,kBAAgB,aAAa,SAAS,KAAK,QAAQ,aAAa,SAAS,KAAK;AAAA,MAChF;AAAA,IACF;AAGA,UAAM,kBAAkB,CAAC,MAAY,UAA+B;AAClE,YAAM,oBAAoB,iBAAiB;AAAA,QACzC,cAAY,SAAS,KAAK,SAAS,KAAK,QAAQ,SAAS,KAAK,SAAS,KAAK;AAAA,MAC9E;AAEA,UAAI,mBAAmB;AAErB,YAAI,CAAC,kBAAkB,OAAO,SAAS,KAAK,GAAG;AAC7C,4BAAkB,OAAO,KAAK,KAAK;AAAA,QACrC;AAAA,MACF,OAAO;AAEL,yBAAiB,KAAK;AAAA,UACpB;AAAA,UACA,QAAQ,CAAC,KAAK;AAAA,QAChB,CAAC;AAAA,MACH;AAAA,IACF;AAEA,aAAS,CAAC,SAAiB;AACzB,YAAM,eAAe,QAAQ,CAAC;AAG9B,UAAI,aAAa,QAAW;AAC1B,cAAM,eAAe,aAAa;AAClC,cAAM,iBAAiB,WAAW;AAElC,YAAI,kBAAkB,GAAG;AAEvB,mBAAS,QAAQ,UAAQ;AACvB,4BAAgB,MAAM,gBAAgB;AAAA,UACxC,CAAC;AAAA,QACH;AAAA,MACF;AAGA,UAAI,gBAAgB;AACpB,UAAI,QAAQ;AACV,cAAM,mBAAmB,SAAS,OAAO,UAAQ,CAAC,mBAAmB,MAAM,MAAM,CAAC;AAClF,yBAAiB,QAAQ,UAAQ;AAC/B,0BAAgB,MAAM,mBAAmB;AAAA,QAC3C,CAAC;AACD,wBAAgB,SAAS,OAAO,UAAQ,mBAAmB,MAAM,MAAM,CAAC;AAAA,MAC1E;AAGA,UAAI,iBAAiB;AACrB,UAAI,gBAAgB,UAAa,gBAAgB,QAAW;AAC1D,yBAAiB,cAAc,OAAO,UAAQ;AAC5C,gBAAM,aAAa,iBAAiB,MAAM,aAAa,aAAa,aAAa;AACjF,cAAI,CAAC,WAAW,OAAO;AACrB,gBAAI,gBAAgB,UAAa,KAAK,OAAO,aAAa;AACxD,8BAAgB,MAAM,gBAAgB;AAAA,YACxC,WAAW,gBAAgB,UAAa,KAAK,OAAO,aAAa;AAC/D,8BAAgB,MAAM,gBAAgB;AAAA,YACxC,OAAO;AACL,8BAAgB,MAAM,cAAc;AAAA,YACtC;AAEA,mBAAO;AAAA,UACT;AAEA,iBAAO;AAAA,QACT,CAAC;AAAA,MACH;AAIA,YAAM,YAAY,oBAAI,IAAkB;AACxC,YAAM,iBAAyB,CAAC;AAChC,YAAM,cAAc,eAAe,OAAO,UAAQ;AAGhD,cAAM,UAAU,GAAG,KAAK,IAAI,IAAI,KAAK,IAAI;AAGzC,cAAM,eAAe,WAAW,MAAM,YAAY;AAClD,YAAI,cAAc;AAChB,yBAAe,KAAK,IAAI;AACxB,0BAAgB,MAAM,aAAa;AAEnC,iBAAO;AAAA,QACT;AAGA,YAAI,UAAU,IAAI,OAAO,GAAG;AAC1B,yBAAe,KAAK,IAAI;AACxB,0BAAgB,MAAM,aAAa;AAEnC,iBAAO;AAAA,QACT;AAGA,kBAAU,IAAI,SAAS,IAAI;AAE3B,eAAO;AAAA,MACT,CAAC;AAGD,UAAI,aAAa,WAAW,cAAc,YAAY,MAAM,GAAG,CAAC;AAKhE,UAAI,aAAa,QAAW;AAC1B,cAAM,eAAe,aAAa;AAClC,cAAM,iBAAiB,WAAW;AAElC,YAAI,kBAAkB,GAAG;AAEvB,qBAAW,QAAQ,UAAQ;AACzB,4BAAgB,MAAM,gBAAgB;AAAA,UACxC,CAAC;AACD,uBAAa,CAAC;AAAA,QAChB,WAAW,WAAW,SAAS,gBAAgB;AAE7C,qBAAW,QAAQ,UAAQ;AACzB,4BAAgB,MAAM,gBAAgB;AAAA,UACxC,CAAC;AACD,uBAAa,CAAC;AAAA,QAChB;AAAA,MACF;AAEA,YAAM,UAAU,WAAW,CAAC,GAAG,cAAc,GAAG,UAAU,IAAI;AAK9D,YAAM,qBAAqB,CAAC,GAAG,gBAAgB;AAE/C,uBAAiB,kBAAkB;AAKnC,UAAI,WAAW,SAAS,KAAK,cAAc;AACzC,qBAAa,EAAE,OAAO,WAAW,CAAC;AAAA,MACpC;AAEA,UAAI,mBAAmB,SAAS,KAAK,cAAc;AACjD,qBAAa,EAAE,OAAO,mBAAmB,CAAC;AAAA,MAC5C;AAEA,UAAI,cAAc;AAChB,qBAAa;AAAA,UACX,eAAe;AAAA,UACf,eAAe;AAAA,QACjB,CAAC;AAAA,MACH;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,QAAM,aAAa,CAAC,UAAkB;AAEpC,QAAI,YAAY,UAAU;AACxB;AAAA,IACF;AAEA,aAAS,CAAC,SAAiB;AACzB,YAAM,eAAe,QAAQ,CAAC;AAC9B,YAAM,UAAU,aAAa,OAAO,CAAC,GAAS,MAAc,MAAM,KAAK;AAGvE,UAAI,uBAAuB;AAC3B,UAAI,aAAa,UAAa,QAAQ,SAAS,UAAU;AACvD,+BAAuB,cAAc;AAAA,UACnC,cAAY,CAAC,SAAS,OAAO,SAAS,gBAAgB;AAAA,QACxD;AACA,yBAAiB,oBAAoB;AAAA,MACvC;AAGA,UAAI,cAAc;AAChB,qBAAa;AAAA,UACX,eAAe;AAAA,UACf,eAAe;AAAA,QACjB,CAAC;AAAA,MACH;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,QAAM,aAAa,MAAM;AAEvB,QAAI,YAAY,UAAU;AACxB;AAAA,IACF;AAEA,aAAS,CAAC,CAAC;AACX,qBAAiB,CAAC,CAAC;AACnB,qBAAiB,UAAU,CAAC;AAG5B,QAAI,cAAc;AAChB,mBAAa;AAAA,QACX,eAAe,CAAC;AAAA,QAChB,eAAe,CAAC;AAAA,MAClB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,qBAAqB,CAAC,UAAkB;AAE5C,QAAI,YAAY,UAAU;AACxB;AAAA,IACF;AAEA,qBAAiB,UAAQ,KAAK,OAAO,CAAC,GAAG,MAAM,MAAM,KAAK,CAAC;AAAA,EAC7D;AAEA,QAAM,qBAAqB,MAAM;AAC/B,qBAAiB,CAAC,CAAC;AAAA,EACrB;AAEA,QAAM,kBAAkB,aAAa,UAAa,MAAM,UAAU;AAElE,SACE;AAAA,IAAC,kBAAkB;AAAA,IAAlB;AAAA,MACC,OAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MAGA,+BAAC,SAAI,WAAU,YACZ;AAAA;AAAA,QACD;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,MAAK;AAAA,YACL,UAAU;AAAA,YACV,IAAI;AAAA,YACJ;AAAA,YACA,MAAM;AAAA,YACN;AAAA,YACA;AAAA,YACA,UAAU,YAAY,CAAC;AAAA,YACvB,UAAU;AAAA,YACV,gBAAc;AAAA,YACd,oBAAkB;AAAA,YAClB,WAAU;AAAA,YACV,UAAU,OAAK;AACb,kBAAI,EAAE,OAAO,SAAS,CAAC,YAAY,CAAC,UAAU;AAC5C,yBAAS,MAAM,KAAK,EAAE,OAAO,KAAK,CAAC;AAEnC,oBAAI;AACF,oBAAE,OAAO,QAAQ;AAAA,gBACnB,QAAQ;AAAA,gBAER;AAAA,cACF;AAAA,YACF;AAAA;AAAA,QACF;AAAA,SACF;AAAA;AAAA,EAEF;AAEJ;AAEA,WAAW,cAAc;AAElB,IAAM,uBAAuB,MAAM;AACxC,QAAM,UAAU,WAAW,iBAAiB;AAE5C,MAAI,CAAC,SAAS;AACZ,UAAM,MAAM,gEAAgE;AAAA,EAC9E;AAEA,SAAO;AACT;;;AErfA,SAAS,MAAAC,WAAU;;;ACAnB,SAAS,aAAa;AACtB,SAAS,UAAU;AACnB,SAAS,UAAAC,eAAc;AA2Ff,gBAAAC,YAAA;AA9ED,IAAM,oBAAoB,CAAC;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAwC;AACtC,QAAM,EAAE,YAAY,YAAY,aAAa,kBAAkB,UAAU,UAAU,MAAM,IACvF,qBAAqB;AACvB,QAAM,YAAYC,QAA0B,IAAI;AAGhD,QAAM,YAAY,MAAM,UAAU,OAAK,EAAE,SAAS,KAAK,QAAQ,EAAE,SAAS,KAAK,IAAI;AAEnF,QAAM,cAAc,CAAC,MAA2C;AAE9D,QAAI,YAAY,UAAU;AACxB;AAAA,IACF;AAGA,eAAW,SAAS;AAGpB,eAAW,MAAM;AAEf,YAAM,mBAAmB,iBAAiB,QAAQ,OAAO,OAAO;AAEhE,UAAI,iBAAiB,SAAS,GAAG;AAI/B,cAAM,cAAc,KAAK,IAAI,WAAW,iBAAiB,SAAS,CAAC;AACnE,cAAM,aAAa,iBAAiB,WAAW;AAE/C,YAAI,YAAY;AACd,qBAAW,MAAM;AAAA,QACnB;AAAA,MACF,OAAO;AAEL,cAAM,cAAc,WAAW,WAAW,YAAY;AACtD,YAAI,aAAa;AACf,sBAAY,MAAM;AAAA,QACpB;AAAA,MACF;AAAA,IACF,GAAG,CAAC;AAEJ,cAAU,CAAC;AAAA,EACb;AAEA,QAAM,SAAS,CAAC,SAAmC;AACjD,cAAU,UAAU;AACpB,QAAI,MAAM;AAER,aAAO,iBAAiB,QAAQ,UAAU,WAAW;AACnD,yBAAiB,QAAQ,KAAK,IAAW;AAAA,MAC3C;AACA,uBAAiB,QAAQ,SAAS,IAAI;AAAA,IACxC,OAAO;AAEL,UAAI,iBAAiB,QAAQ,SAAS,GAAG;AACvC,yBAAiB,QAAQ,SAAS,IAAI;AAAA,MACxC;AAAA,IACF;AAAA,EACF;AAEA,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,wBAAqB;AAAA,MACrB,WAAW,GAAG,SAAS;AAAA,MACvB,SAAS;AAAA,MACT,UAAU,YAAY;AAAA,MACtB,MAAK;AAAA,MACL,QAAO;AAAA,MACP,QAAO;AAAA,MACN,GAAG;AAAA,MAEJ,0BAAAA,KAAC,QAAK,MAAK,MACT,0BAAAA,KAAC,SAAM,GACT;AAAA;AAAA,EACF;AAEJ;AAEA,kBAAkB,cAAc;;;AD1CxB,gBAAAE,MAIA,QAAAC,aAJA;AAvBD,IAAM,eAAe,CAAC;AAAA,EAC3B,SAAS,WAAW;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAmC;AACjC,QAAM,EAAE,OAAO,IAAI,qBAAqB;AAExC,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,wBAAqB;AAAA,MACrB,WAAWC;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEJ;AAAA,wBAAAF,KAAC,SAAI,WAAU,+EACb,0BAAAA,KAAC,QAAK,MAAK,MAAM,sBAAY,IAAI,GAAE,GACrC;AAAA,QAEA,gBAAAC,MAAC,SAAI,WAAU,kBACb;AAAA,0BAAAA,MAAC,SAAI,WAAU,qDACb;AAAA,4BAAAD,KAAC,OAAE,WAAU,oCAAoC,eAAK,MAAK;AAAA,YAC3D,gBAAAA,KAAC,OAAE,WAAU,8BAA8B,yBAAe,KAAK,MAAM,MAAM,GAAE;AAAA,aAC/E;AAAA,UACC,mBAAmB,UAClB,gBAAAA,KAAC,SAAI,WAAU,SACb,0BAAAA,KAAC,YAAS,OAAO,gBAAgB,KAAK,KAAK,cAAY,mBAAmB,GAC5E;AAAA,WAEJ;AAAA,QAEA,gBAAAA,KAAC,qBAAkB,cAAY,uBAAuB,MAAY;AAAA;AAAA;AAAA,EACpE;AAEJ;AAEA,aAAa,cAAc;;;AExDvB,0BAAAG,YAAA;AAJG,IAAM,UAAU,CAAC,EAAE,SAAS,MAA8B;AAC/D,QAAM,EAAE,QAAQ,CAAC,GAAG,gBAAgB,CAAC,GAAG,OAAO,IAAI,qBAAqB;AAExE,SACE,gBAAAA,KAAA,YACG,mBAAS;AAAA,IACR,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC,GACH;AAEJ;AAEA,QAAQ,cAAc;;;AChCtB,SAAS,MAAAC,WAAU;AACnB,SAAS,UAAAC,eAAc;AA4DnB,gBAAAC,YAAA;AAxDG,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA,WAAW;AACb,GAIG;AACD,QAAM,MAAM,qBAAqB;AACjC,QAAM,cAAcC,QAAuB,IAAI;AAE/C,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,qDAAqD;AAE/E,QAAM,aAAa,CAAC,MAAuB;AACzC,MAAE,eAAe;AACjB,MAAE,gBAAgB;AAClB,MAAE,cAAc,aAAa,kBAAkB,OAAO;AAGtD,QAAI,IAAI,YAAY,IAAI,UAAU;AAChC;AAAA,IACF;AAEA,UAAM,QAAQ,EAAE,aAAa;AAI7B,QAAI,aAAqB,CAAC;AAC1B,QAAI,OAAO;AACT,mBAAa,MAAM,QAAQ,KAAK,IAAI,CAAC,GAAG,KAAK,IAAI,MAAM,KAAK,KAAK;AAAA,IACnE;AAEA,QAAI,WAAW,SAAS,GAAG;AACzB,UAAI,SAAS,UAAU;AAAA,IACzB;AAAA,EACF;AAEA,QAAM,cAAc,MAAM;AACxB,QAAI,CAAC,IAAI,YAAY,CAAC,IAAI,UAAU;AAClC,UAAI,SAAS,SAAS,MAAM;AAAA,IAC9B;AAAA,EACF;AAEA,QAAM,gBAAgB,CAAC,MAA2B;AAChD,QAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,QAAE,eAAe;AACjB,UAAI,CAAC,IAAI,YAAY,CAAC,IAAI,UAAU;AAClC,YAAI,SAAS,SAAS,MAAM;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,IAAI,YAAY,IAAI;AAEvC,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,KAAK,UAAQ;AACX,oBAAY,UAAU;AACtB,YAAI,IAAI,aAAa;AACnB,cAAI,YAAY,UAAU;AAAA,QAC5B;AAAA,MACF;AAAA,MACA,MAAK;AAAA,MACL,UAAU,aAAa,KAAK;AAAA,MAC5B,iBAAe,IAAI,WAAW,OAAO;AAAA,MACrC,oBAAkB,IAAI;AAAA,MACtB,gBAAc,IAAI;AAAA,MAClB,iBAAe,IAAI;AAAA,MACnB,SAAS;AAAA,MACT,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,YAAY,OAAK;AACf,UAAE,eAAe;AAAA,MACnB;AAAA,MACA,WACE,WACI,YACAE;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,CAAC,cAAc;AAAA,QACf;AAAA;AAAA,QAEA,IAAI,YAAY;AAAA;AAAA,QAEhB,IAAI,YAAY,CAAC,IAAI,YAAY;AAAA,QACjC;AAAA,MACF;AAAA,MAEN,aAAa,OAAK;AAChB,YAAI,CAAC,YAAY;AACf,YAAE,cAAc,aAAa,kBAAkB,MAAM;AAAA,QACvD;AAAA,MACF;AAAA,MACA,aAAa,OAAK;AAChB,UAAE,cAAc,aAAa,kBAAkB,OAAO;AAAA,MACxD;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;AAEA,SAAS,cAAc;;;AC/GvB,SAAS,MAAAC,WAAU;AACnB,SAAwC,WAAW,YAAAC,iBAAgB;AA2C7D,gBAAAC,MAcF,QAAAC,aAdE;AAxBC,IAAM,eAAe,CAAC;AAAA,EAC3B,SAAS,WAAW;AAAA,EACpB;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,GAAG;AACL,MAAmC;AACjC,QAAM,CAAC,YAAY,aAAa,IAAIF,UAAS,KAAK;AAClD,QAAM,CAAC,aAAa,cAAc,IAAIA,UAAS,KAAK;AAEpD,QAAM,UAAU,KAAK,KAAK,WAAW,QAAQ;AAC7C,QAAM,WAAW,UAAU,IAAI,gBAAgB,IAAI,IAAI;AAGvD,YAAU,MAAM;AACd,WAAO,MAAM;AACX,UAAI,UAAU;AACZ,YAAI,gBAAgB,QAAQ;AAAA,MAC9B;AAAA,IACF;AAAA,EACF,GAAG,CAAC,QAAQ,CAAC;AAEb,MAAI,CAAC,WAAW,YAAY;AAC1B,WACE,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC,wBAAqB;AAAA,QACrB,WAAWF;AAAA,UACT;AAAA,UACA;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QAEH;AAAA;AAAA,IACH;AAAA,EAEJ;AAEA,SACE,gBAAAG;AAAA,IAAC;AAAA;AAAA,MACC,wBAAqB;AAAA,MACrB,WAAWH,IAAG,wCAAwC,SAAS;AAAA,MAC9D,GAAG;AAAA,MAEJ;AAAA,wBAAAE;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,KAAK,KAAK;AAAA,YACV,WAAWF,IAAG,0BAA0B,CAAC,eAAe,WAAW;AAAA,YACnE,QAAQ,MAAM,eAAe,IAAI;AAAA,YACjC,SAAS,MAAM,cAAc,IAAI;AAAA;AAAA,QACnC;AAAA,QACC,CAAC,eACA,gBAAAE,KAAC,SAAI,WAAU,qDAAqD,oBAAS;AAAA;AAAA;AAAA,EAEjF;AAEJ;AAEA,aAAa,cAAc;;;AC7E3B,SAAS,sBAAsB;AAC/B,SAAS,MAAAE,WAAU;;;ACDnB,SAAS,SAAAC,cAAa;AACtB,SAAS,MAAAC,WAAU;AACnB,SAAS,UAAAC,eAAc;AA+Df,gBAAAC,YAAA;AAjDD,IAAM,4BAA4B,CAAC;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAgD;AAC9C,QAAM,EAAE,oBAAoB,YAAY,aAAa,UAAU,UAAU,cAAc,IACrF,qBAAqB;AACvB,QAAM,YAAYC,QAA0B,IAAI;AAGhD,QAAM,oBAAoB,cAAc;AAAA,IACtC,QAAM,GAAG,KAAK,SAAS,aAAa,KAAK,QAAQ,GAAG,KAAK,SAAS,aAAa,KAAK;AAAA,EACtF;AAEA,QAAM,cAAc,CAAC,MAA2C;AAE9D,QAAI,YAAY,UAAU;AACxB;AAAA,IACF;AAGA,uBAAmB,iBAAiB;AAGpC,eAAW,MAAM;AAEf,YAAM,cAAc,WAAW,WAAW,YAAY;AACtD,UAAI,aAAa;AACf,oBAAY,MAAM;AAAA,MACpB;AAAA,IACF,GAAG,CAAC;AAEJ,cAAU,CAAC;AAAA,EACb;AAEA,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,wBAAqB;AAAA,MACrB,WAAWE,IAAG,SAAS;AAAA,MACvB,SAAS;AAAA,MACT,UAAU,YAAY;AAAA,MACtB,MAAK;AAAA,MACL,QAAO;AAAA,MACP,QAAO;AAAA,MACN,GAAG;AAAA,MAEJ,0BAAAF,KAAC,QAAK,MAAK,MACT,0BAAAA,KAACG,QAAA,EAAM,GACT;AAAA;AAAA,EACF;AAEJ;AAEA,0BAA0B,cAAc;;;ADX9B,gBAAAC,MAMA,QAAAC,aANA;AAxBH,IAAM,eAAe,CAAC;AAAA,EAC3B,SAAS,WAAW;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAmC;AACjC,QAAM,EAAE,OAAO,IAAI,qBAAqB;AAExC,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,wBAAqB;AAAA,MACrB,WAAWC;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEJ;AAAA,wBAAAF,KAAC,SAAI,WAAU,6EACb,0BAAAA,KAAC,QAAK,MAAK,MAAK,WAAU,cACxB,0BAAAA,KAAC,kBAAe,GAClB,GACF;AAAA,QAEA,gBAAAA,KAAC,SAAI,WAAU,kBACb,0BAAAC,MAAC,SAAI,WAAU,wBACb;AAAA,0BAAAA,MAAC,SAAI,WAAU,qDACb;AAAA,4BAAAD,KAAC,OAAE,WAAU,oCAAoC,uBAAa,KAAK,MAAK;AAAA,YACxE,gBAAAA,KAAC,OAAE,WAAU,8BACV,yBAAe,aAAa,KAAK,MAAM,MAAM,GAChD;AAAA,aACF;AAAA,UACA,gBAAAA,KAAC,SAAI,WAAU,wBACZ,uBAAa,OAAO,IAAI,CAAC,OAAO,eAC/B,gBAAAA,KAAC,SAAqB,WAAU,2BAA0B,mBAAiB,OACxE,sBAAY,KAAK,KADV,UAEV,CACD,GACH;AAAA,WACF,GACF;AAAA,QAEA,gBAAAA,KAAC,6BAA0B,cAAY,uBAAuB,cAA4B;AAAA;AAAA;AAAA,EAC5F;AAEJ;AAEA,aAAa,cAAc;;;AEvF3B,SAAS,MAAAG,WAAU;AAuCf,gBAAAC,YAAA;AAzBG,IAAM,UAAU,CAAC;AAAA,EACtB;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,WAAW;AAAA,EACX,SAAS;AAAA,EACT,SAAS;AAAA,EACT;AAAA,EACA,GAAG;AACL,MAA8B;AAC5B,QAAM,EAAE,UAAU,YAAY,UAAU,UAAU,aAAa,WAAW,WAAW,IACnF,qBAAqB;AAEvB,QAAM,cAAc,CAAC,MAAwB;AAC3C,MAAE,gBAAgB;AAClB,MAAE,eAAe;AACjB,QAAI,CAAC,YAAY,CAAC,UAAU;AAC1B,eAAS,SAAS,MAAM;AAAA,IAC1B;AAAA,EACF;AAEA,QAAM,kBAAkB,WAAW,WAAW;AAC9C,QAAM,OAAO,UAAU,OAAO;AAE9B,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,KAAK,CAAC,SAA6B;AAEjC,YAAI,YAAY;AACd,qBAAW,UAAU;AAAA,QACvB;AACA,YAAI,KAAK;AACP,cAAI,OAAO,QAAQ,YAAY;AAC7B,gBAAI,IAAyB;AAAA,UAC/B,OAAO;AACL,gBAAI,UAAU;AAAA,UAChB;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,MACA,wBAAqB;AAAA,MACrB,WAAWC,IAAG,SAAS;AAAA,MACvB,UAAU,YAAY;AAAA,MACtB,SAAS;AAAA,MACT,oBAAkB;AAAA,MAClB,gBAAc;AAAA,MACd,iBAAe;AAAA,MACd,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ;AAEA,QAAQ,cAAc;;;AC7Cf,IAAMC,cAST,OAAO,OAAO,YAAM;AAAA;AAAA,EAEtB;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEDA,YAAW,cAAc;AACzB,QAAQ,cAAc;AACtB,SAAS,cAAc;AACvB,QAAQ,cAAc;AACtB,kBAAkB,cAAc;AAChC,aAAa,cAAc;AAC3B,aAAa,cAAc;AAC3B,aAAsB,cAAc;AACpC,0BAA0B,cAAc;","names":["extension","fileName","formatter","cx","useRef","jsx","useRef","jsx","jsxs","cx","jsx","cx","useRef","jsx","useRef","cx","cx","useState","jsx","jsxs","cx","Close","cx","useRef","jsx","useRef","cx","Close","jsx","jsxs","cx","cx","jsx","cx","FileUpload"]}
1
+ {"version":3,"sources":["../../src/file-upload/FileUpload.tsx","../../src/file-upload/utils.ts","../../src/file-upload/FileUploadAcceptedFile.tsx","../../src/file-upload/FileUploadItemDeleteTrigger.tsx","../../src/file-upload/FileUploadContext.tsx","../../src/file-upload/FileUploadDropzone.tsx","../../src/file-upload/FileUploadPreviewImage.tsx","../../src/file-upload/FileUploadRejectedFile.tsx","../../src/file-upload/FileUploadRejectedFileDeleteTrigger.tsx","../../src/file-upload/FileUploadTrigger.tsx","../../src/file-upload/index.ts"],"sourcesContent":["/* eslint-disable max-lines */\n/* eslint-disable max-lines-per-function */\nimport { useFormFieldControl } from '@spark-ui/components/form-field'\nimport { useCombinedState } from '@spark-ui/hooks/use-combined-state'\nimport { createContext, ReactNode, Ref, useContext, useId, useRef, useState } from 'react'\n\nimport { validateFileAccept, validateFileSize } from './utils'\n\nexport interface FileUploadProps {\n /**\n * Change the default rendered element for the one passed as a child, merging their props and behavior.\n */\n asChild?: boolean\n ref?: Ref<HTMLDivElement>\n children: ReactNode\n className?: string\n /**\n * Initial files to display when the component mounts (uncontrolled mode)\n */\n defaultValue?: File[]\n /**\n * Controlled files value (controlled mode)\n * When provided, the component becomes controlled\n */\n value?: File[]\n /**\n * Callback when files are accepted\n * @param details - Details about the accepted files\n */\n onFileAccept?: (details: FileAcceptDetails) => void\n /**\n * Callback when files are rejected\n * @param details - Details about the rejected files and their errors\n */\n onFileReject?: (details: FileRejectDetails) => void\n /**\n * Callback when files change (both accepted and rejected)\n * For controlled mode, use this to update the value prop by extracting details.acceptedFiles\n * @param details - Details about both accepted and rejected files\n */\n onFileChange?: (details: FileChangeDetails) => void\n /**\n * Whether multiple files can be selected\n * @default true\n */\n multiple?: boolean\n /**\n * Comma-separated list of accepted file types\n * Supports MIME types (e.g., \"image/*\", \"image/png\", \"application/pdf\")\n * and file extensions (e.g., \".pdf\", \".doc\", \".jpg\")\n * @example \"image/*\"\n * @example \".pdf,.doc\"\n * @example \"image/png,image/jpeg,.pdf\"\n */\n accept?: string\n /**\n * Maximum number of files that can be uploaded\n * Files beyond this limit will be rejected\n */\n maxFiles?: number\n /**\n * Maximum file size in bytes\n * Files larger than this will be rejected\n */\n maxFileSize?: number\n /**\n * Minimum file size in bytes\n * Files smaller than this will be rejected\n */\n minFileSize?: number\n /**\n * When `true`, prevents the user from interacting with the file upload\n */\n disabled?: boolean\n /**\n * When `true`, sets the file upload to read-only mode\n */\n readOnly?: boolean\n /**\n * The [BCP47](https://www.ietf.org/rfc/bcp/bcp47.txt) language code for the locale.\n * Used for formatting file sizes and error messages.\n * @default Browser locale or 'en' if not available\n */\n locale?: string\n}\n\nexport type FileUploadFileError =\n | 'TOO_MANY_FILES'\n | 'FILE_INVALID_TYPE'\n | 'FILE_TOO_LARGE'\n | 'FILE_TOO_SMALL'\n | 'FILE_INVALID'\n | 'FILE_EXISTS'\n\nexport interface RejectedFile {\n file: File\n errors: FileUploadFileError[]\n}\n\nexport interface FileAcceptDetails {\n files: File[]\n}\n\nexport interface FileRejectDetails {\n files: RejectedFile[]\n}\n\nexport interface FileChangeDetails {\n acceptedFiles: File[]\n rejectedFiles: RejectedFile[]\n}\n\nexport const FileUploadContext = createContext<{\n inputRef: React.RefObject<HTMLInputElement | null>\n files: File[]\n rejectedFiles: RejectedFile[]\n addFiles: (files: File[]) => void\n removeFile: (index: number) => void\n removeRejectedFile: (index: number) => void\n clearFiles: () => void\n clearRejectedFiles: () => void\n triggerRef: React.RefObject<HTMLElement | null>\n dropzoneRef: React.RefObject<HTMLElement | null>\n deleteButtonRefs: React.MutableRefObject<HTMLButtonElement[]>\n multiple: boolean\n maxFiles?: number\n maxFilesReached: boolean\n disabled: boolean\n readOnly: boolean\n locale: string\n description?: string\n isInvalid?: boolean\n isRequired?: boolean\n} | null>(null)\n\nconst ID_PREFIX = ':file-upload'\n\nexport const FileUpload = ({\n asChild: _asChild = false,\n children,\n defaultValue = [],\n value: controlledValue,\n onFileAccept,\n onFileReject,\n onFileChange,\n multiple = true,\n accept,\n maxFiles,\n maxFileSize,\n minFileSize,\n disabled: disabledProp = false,\n readOnly: readOnlyProp = false,\n locale,\n}: FileUploadProps) => {\n const field = useFormFieldControl()\n const {\n id: fieldId,\n name: fieldName,\n isInvalid,\n isRequired,\n description,\n disabled: fieldDisabled,\n readOnly: fieldReadOnly,\n labelId,\n } = field\n\n // Get default locale from browser or fallback to 'en'\n const defaultLocale =\n locale || (typeof navigator !== 'undefined' && navigator.language ? navigator.language : 'en')\n\n // Generate unique ID if none provided by FormField\n const internalId = useId()\n const inputId = fieldId || `${ID_PREFIX}-${internalId}`\n\n // Use FormField name or undefined (no hardcoded fallback)\n const inputName = fieldName\n\n const inputRef = useRef<HTMLInputElement>(null)\n const triggerRef = useRef<HTMLElement>(null)\n const dropzoneRef = useRef<HTMLElement>(null)\n const deleteButtonRefs = useRef<HTMLButtonElement[]>([])\n\n // Merge FormField props with component props (FormField takes precedence)\n const disabled = fieldDisabled ?? disabledProp\n const readOnly = fieldReadOnly ?? readOnlyProp\n\n // For controlled mode, use onFileChange to update value prop\n // useCombinedState doesn't need a callback - we'll call onFileChange manually in addFiles/removeFile\n const [filesState, setFilesState, ,] = useCombinedState(controlledValue, defaultValue)\n const files = filesState ?? []\n const setFiles = setFilesState as (value: File[] | ((prev: File[]) => File[])) => void\n const [rejectedFiles, setRejectedFiles] = useState<RejectedFile[]>([])\n\n const addFiles = (newFiles: File[]) => {\n // Don't allow adding files when disabled or readOnly\n if (disabled || readOnly) {\n return\n }\n\n // Reset rejectedFiles at the start of each new file addition attempt\n setRejectedFiles([])\n\n const newRejectedFiles: RejectedFile[] = []\n\n // Helper function to check if a file already exists\n // Compares by name and size to detect duplicates (lastModified can differ when re-selecting the same file)\n const fileExists = (file: File, existingFiles: File[]): boolean => {\n return existingFiles.some(\n existingFile => existingFile.name === file.name && existingFile.size === file.size\n )\n }\n\n // Helper function to add or update rejected file\n const addRejectedFile = (file: File, error: FileUploadFileError) => {\n const existingRejection = newRejectedFiles.find(\n rejected => rejected.file.name === file.name && rejected.file.size === file.size\n )\n\n if (existingRejection) {\n // Add error to existing rejection if not already present\n if (!existingRejection.errors.includes(error)) {\n existingRejection.errors.push(error)\n }\n } else {\n // Create new rejection\n newRejectedFiles.push({\n file,\n errors: [error],\n })\n }\n }\n\n setFiles((prev: File[]) => {\n const currentFiles = prev ?? []\n // Check maxFiles limit FIRST for all files (even if they will be rejected by other validations)\n // This allows a file to have multiple error codes (e.g., FILE_INVALID_TYPE + TOO_MANY_FILES)\n if (maxFiles !== undefined) {\n const currentCount = currentFiles.length\n const remainingSlots = maxFiles - currentCount\n\n if (remainingSlots <= 0) {\n // Already at max, mark all new files with TOO_MANY_FILES error\n newFiles.forEach(file => {\n addRejectedFile(file, 'TOO_MANY_FILES')\n })\n }\n }\n\n // Track files rejected by accept pattern\n let filteredFiles = newFiles\n if (accept) {\n const rejectedByAccept = newFiles.filter(file => !validateFileAccept(file, accept))\n rejectedByAccept.forEach(file => {\n addRejectedFile(file, 'FILE_INVALID_TYPE')\n })\n filteredFiles = newFiles.filter(file => validateFileAccept(file, accept))\n }\n\n // Track files rejected by size\n let validSizeFiles = filteredFiles\n if (minFileSize !== undefined || maxFileSize !== undefined) {\n validSizeFiles = filteredFiles.filter(file => {\n const validation = validateFileSize(file, minFileSize, maxFileSize, defaultLocale)\n if (!validation.valid) {\n if (maxFileSize !== undefined && file.size > maxFileSize) {\n addRejectedFile(file, 'FILE_TOO_LARGE')\n } else if (minFileSize !== undefined && file.size < minFileSize) {\n addRejectedFile(file, 'FILE_TOO_SMALL')\n } else {\n addRejectedFile(file, 'FILE_INVALID')\n }\n\n return false\n }\n\n return true\n })\n }\n\n // Check for duplicate files (both against existing files and within the current batch)\n // This must be done AFTER size validation but BEFORE maxFiles check\n const seenFiles = new Map<string, File>()\n const duplicateFiles: File[] = []\n const uniqueFiles = validSizeFiles.filter(file => {\n // Create a unique key for the file (name + size)\n // Using name and size only, as lastModified can differ when re-selecting the same file\n const fileKey = `${file.name}-${file.size}`\n\n // Check if file already exists in previously accepted files\n const existsInPrev = fileExists(file, currentFiles)\n if (existsInPrev) {\n duplicateFiles.push(file)\n addRejectedFile(file, 'FILE_EXISTS')\n\n return false\n }\n\n // Check if file already exists in the current batch\n if (seenFiles.has(fileKey)) {\n duplicateFiles.push(file)\n addRejectedFile(file, 'FILE_EXISTS')\n\n return false\n }\n\n // Mark this file as seen\n seenFiles.set(fileKey, file)\n\n return true\n })\n\n // If multiple is false, replace existing files with only the first new file\n let filesToAdd = multiple ? uniqueFiles : uniqueFiles.slice(0, 1)\n\n // Track files rejected by maxFiles limit (only for files that passed other validations)\n // Note: We already checked maxFiles at the beginning for ALL files to allow multiple error codes\n // This second check is to prevent adding files when we're at the limit\n if (maxFiles !== undefined) {\n const currentCount = currentFiles.length\n const remainingSlots = maxFiles - currentCount\n\n if (remainingSlots <= 0) {\n // Already at max, reject all new files (they should already have TOO_MANY_FILES error from the first check)\n filesToAdd.forEach(file => {\n addRejectedFile(file, 'TOO_MANY_FILES')\n })\n filesToAdd = []\n } else if (filesToAdd.length > remainingSlots) {\n // Reject all files if batch exceeds limit (\"all or nothing\" approach)\n filesToAdd.forEach(file => {\n addRejectedFile(file, 'TOO_MANY_FILES')\n })\n filesToAdd = []\n }\n }\n\n const updated = multiple ? [...currentFiles, ...filesToAdd] : filesToAdd\n\n // Add rejected files to state synchronously\n // Note: newRejectedFiles is mutated inside this setFiles callback, so it should be populated by now\n // Copy the array to avoid closure issues\n const rejectedFilesToAdd = [...newRejectedFiles]\n // Replace rejectedFiles completely (not accumulate)\n setRejectedFiles(rejectedFilesToAdd)\n\n // Call callbacks with the calculated values\n // Note: These callbacks are called synchronously with the new values\n // React will update the state asynchronously, but the callbacks receive the correct new values\n if (filesToAdd.length > 0 && onFileAccept) {\n onFileAccept({ files: filesToAdd })\n }\n\n if (rejectedFilesToAdd.length > 0 && onFileReject) {\n onFileReject({ files: rejectedFilesToAdd })\n }\n\n if (onFileChange) {\n onFileChange({\n acceptedFiles: updated,\n rejectedFiles: rejectedFilesToAdd,\n })\n }\n\n return updated\n })\n }\n\n const removeFile = (index: number) => {\n // Don't allow removing files when disabled or readOnly\n if (disabled || readOnly) {\n return\n }\n\n setFiles((prev: File[]) => {\n const currentFiles = prev ?? []\n const updated = currentFiles.filter((_: File, i: number) => i !== index)\n\n // Clean up TOO_MANY_FILES errors if we're now below the maxFiles limit\n let updatedRejectedFiles = rejectedFiles\n if (maxFiles !== undefined && updated.length < maxFiles) {\n updatedRejectedFiles = rejectedFiles.filter(\n rejected => !rejected.errors.includes('TOO_MANY_FILES')\n )\n setRejectedFiles(updatedRejectedFiles)\n }\n\n // Call onFileChange for controlled mode\n if (onFileChange) {\n onFileChange({\n acceptedFiles: updated,\n rejectedFiles: updatedRejectedFiles,\n })\n }\n\n return updated\n })\n }\n\n const clearFiles = () => {\n // Don't allow clearing files when disabled or readOnly\n if (disabled || readOnly) {\n return\n }\n\n setFiles([])\n setRejectedFiles([])\n deleteButtonRefs.current = []\n\n // Call onFileChange for controlled mode\n if (onFileChange) {\n onFileChange({\n acceptedFiles: [],\n rejectedFiles: [],\n })\n }\n }\n\n const removeRejectedFile = (index: number) => {\n // Don't allow removing rejected files when disabled or readOnly\n if (disabled || readOnly) {\n return\n }\n\n setRejectedFiles(prev => prev.filter((_, i) => i !== index))\n }\n\n const clearRejectedFiles = () => {\n setRejectedFiles([])\n }\n\n const maxFilesReached = maxFiles !== undefined && files.length >= maxFiles\n\n return (\n <FileUploadContext.Provider\n value={{\n inputRef,\n files,\n rejectedFiles,\n addFiles,\n removeFile,\n removeRejectedFile,\n clearFiles,\n clearRejectedFiles,\n triggerRef,\n dropzoneRef,\n deleteButtonRefs,\n multiple,\n maxFiles,\n maxFilesReached,\n disabled,\n readOnly,\n locale: defaultLocale,\n description,\n isInvalid,\n isRequired,\n }}\n >\n {/* <Comp data-spark-component=\"file-upload\" className={cx('relative', className)} {...props}> */}\n <div className=\"relative\">\n {children}\n <input\n ref={inputRef}\n type=\"file\"\n tabIndex={-1}\n id={inputId}\n multiple={multiple}\n name={inputName}\n accept={accept}\n disabled={disabled}\n readOnly={readOnly && !disabled}\n required={isRequired}\n aria-invalid={isInvalid}\n aria-describedby={description}\n // Hardcoded aria-label is acceptable here because:\n // 1. The input is visually hidden (sr-only) and not keyboard accessible (tabIndex={-1})\n // 2. Users never interact directly with this input - they interact via Trigger/Dropzone\n // 3. Screen readers will announce the Trigger/Dropzone content (which can be translated) instead\n // 4. This is only used as a fallback when no FormField.Label is present\n aria-label={!labelId ? 'Upload files test' : undefined}\n className=\"sr-only\"\n onChange={e => {\n if (e.target.files && !disabled && !readOnly) {\n addFiles(Array.from(e.target.files))\n // Reset input value to allow selecting the same file again\n try {\n e.target.value = ''\n } catch {\n // Ignore error if value is read-only (e.g., in tests)\n }\n }\n }}\n />\n </div>\n {/* </Comp> */}\n </FileUploadContext.Provider>\n )\n}\n\nFileUpload.displayName = 'FileUpload'\n\nexport const useFileUploadContext = () => {\n const context = useContext(FileUploadContext)\n\n if (!context) {\n throw Error('useFileUploadContext must be used within a FileUpload provider')\n }\n\n return context\n}\n","import { CvOutline } from '@spark-ui/icons/CvOutline'\nimport { FilePdfOutline } from '@spark-ui/icons/FilePdfOutline'\nimport { ImageOutline } from '@spark-ui/icons/ImageOutline'\nimport { PlayOutline } from '@spark-ui/icons/PlayOutline'\nimport { createElement, ReactElement } from 'react'\n\n/**\n * Validates if a file matches the accept patterns\n * Supports MIME types (e.g., \"image/*\", \"image/png\", \"application/pdf\")\n * and file extensions (e.g., \".pdf\", \".doc\", \".jpg\")\n */\nexport function validateFileAccept(file: File, accept: string): boolean {\n if (!accept) {\n return true\n }\n\n const patterns = accept.split(',').map(pattern => pattern.trim())\n\n return patterns.some(pattern => {\n // Handle MIME type patterns (e.g., \"image/*\", \"image/png\")\n if (pattern.includes('/')) {\n if (pattern.endsWith('/*')) {\n // Wildcard MIME type (e.g., \"image/*\")\n const baseType = pattern.slice(0, -2)\n\n return file.type.startsWith(baseType + '/')\n }\n // Exact MIME type (e.g., \"image/png\")\n\n return file.type === pattern\n }\n\n // Handle file extension patterns (e.g., \".pdf\", \".doc\")\n if (pattern.startsWith('.')) {\n const extension = pattern.toLowerCase()\n const fileName = file.name.toLowerCase()\n\n return fileName.endsWith(extension)\n }\n\n // Handle extension without dot (e.g., \"pdf\", \"doc\")\n const extension = '.' + pattern.toLowerCase()\n const fileName = file.name.toLowerCase()\n\n return fileName.endsWith(extension)\n })\n}\n\n/**\n * Validates if a file size is within the allowed range\n * @param file - The file to validate\n * @param minFileSize - Minimum file size in bytes\n * @param maxFileSize - Maximum file size in bytes\n * @param locale - Locale code for error messages. Defaults to browser locale or 'en'\n * @returns Object with validation result and error message if invalid\n */\nexport function validateFileSize(\n file: File,\n minFileSize?: number,\n maxFileSize?: number,\n locale?: string\n): { valid: boolean; error?: string } {\n const defaultLocale = locale || getDefaultLocale()\n if (minFileSize !== undefined && file.size < minFileSize) {\n const errorMessage = `File \"${file.name}\" is too small. Minimum size is ${formatFileSize(minFileSize, defaultLocale)}.`\n\n return {\n valid: false,\n error: errorMessage,\n }\n }\n\n if (maxFileSize !== undefined && file.size > maxFileSize) {\n const errorMessage = `File \"${file.name}\" is too large. Maximum size is ${formatFileSize(maxFileSize, defaultLocale)}.`\n\n return {\n valid: false,\n error: errorMessage,\n }\n }\n\n return { valid: true }\n}\n\n/**\n * Gets the default locale from the browser or falls back to 'en'\n * @returns The browser's locale or 'en' as fallback\n */\nfunction getDefaultLocale(): string {\n if (typeof navigator !== 'undefined' && navigator.language) {\n return navigator.language\n }\n\n return 'en'\n}\n\n/**\n * Formats file size in bytes to human-readable format\n * @param bytes - File size in bytes\n * @param locale - Locale code (e.g., 'en', 'fr'). Defaults to browser locale or 'en'\n * @returns Formatted file size string with appropriate unit\n */\nexport function formatFileSize(bytes: number, locale?: string): string {\n const defaultLocale = locale || getDefaultLocale()\n // Normalize locale (e.g., 'fr' -> 'fr-FR', 'en' -> 'en-US')\n let normalizedLocale = defaultLocale\n if (defaultLocale.length === 2) {\n normalizedLocale = defaultLocale === 'fr' ? 'fr-FR' : 'en-US'\n }\n\n if (bytes === 0) {\n const formatter = new Intl.NumberFormat(normalizedLocale, {\n style: 'unit',\n unit: 'byte',\n unitDisplay: 'long',\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n })\n\n return formatter.format(0)\n }\n\n const k = 1024\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n\n // Map to Intl.NumberFormat supported units\n const units = ['byte', 'kilobyte', 'megabyte', 'gigabyte'] as const\n const unit = units[i] || 'byte'\n\n const size = bytes / Math.pow(k, i)\n\n // Use 'long' display for bytes to get proper pluralization (bytes/octets)\n // Use 'short' display for other units (KB/MB/GB, Ko/Mo/Go)\n const unitDisplay = i === 0 ? 'long' : 'short'\n\n // Use Intl.NumberFormat with unit style to format number and unit according to locale\n const formatter = new Intl.NumberFormat(normalizedLocale, {\n style: 'unit',\n unit,\n unitDisplay,\n minimumFractionDigits: 0,\n maximumFractionDigits: 2,\n })\n\n return formatter.format(size)\n}\n\n/**\n * Returns the appropriate icon component based on the file type\n * @param file - The file to get the icon for\n * @returns React element representing the icon component\n */\nexport function getFileIcon(file: File): ReactElement {\n const fileType = file.type.toLowerCase()\n const fileName = file.name.toLowerCase()\n\n // Check for images\n if (fileType.startsWith('image/') || /\\.(jpg|jpeg|png|gif|bmp|webp|svg|ico)$/i.test(fileName)) {\n return createElement(ImageOutline)\n }\n\n // Check for PDFs\n if (fileType === 'application/pdf' || fileName.endsWith('.pdf')) {\n return createElement(FilePdfOutline)\n }\n\n // Check for videos\n if (fileType.startsWith('video/') || /\\.(mp4|avi|mov|wmv|flv|webm|mkv)$/i.test(fileName)) {\n return createElement(PlayOutline)\n }\n\n // Default icon for other file types\n return createElement(CvOutline)\n}\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, Ref } from 'react'\n\nimport { Icon } from '../icon'\nimport { Progress } from '../progress'\nimport { useFileUploadContext } from './FileUpload'\nimport { ItemDeleteTrigger } from './FileUploadItemDeleteTrigger'\nimport { formatFileSize, getFileIcon } from './utils'\n\nexport interface FileUploadAcceptedFileProps extends ComponentPropsWithoutRef<'li'> {\n /**\n * Change the default rendered element for the one passed as a child, merging their props and behavior.\n */\n asChild?: boolean\n ref?: Ref<HTMLLIElement>\n /**\n * The file to display\n */\n file: File\n /**\n * Upload progress value (0-100). When provided, displays a progress bar at the bottom of the file item.\n */\n uploadProgress?: number\n /**\n * Accessible label for the delete button\n */\n deleteButtonAriaLabel: string\n /**\n * Accessible label for the progress bar. Required when uploadProgress is provided.\n */\n progressAriaLabel?: string\n className?: string\n}\n\nexport const AcceptedFile = ({\n asChild: _asChild = false,\n className,\n file,\n uploadProgress,\n deleteButtonAriaLabel,\n progressAriaLabel,\n ...props\n}: FileUploadAcceptedFileProps) => {\n const { locale } = useFileUploadContext()\n\n return (\n <li\n data-spark-component=\"file-upload-accepted-file\"\n className={cx(\n 'relative',\n 'default:bg-surface default:border-sm default:border-outline default:p-md default:rounded-md',\n 'gap-md flex items-center justify-between default:w-full',\n className\n )}\n {...props}\n >\n <div className=\"size-sz-40 bg-support-container flex items-center justify-center rounded-md\">\n <Icon size=\"md\">{getFileIcon(file)}</Icon>\n </div>\n\n <div className=\"min-w-0 flex-1\">\n <div className=\"gap-md flex flex-row items-center justify-between\">\n <p className=\"text-body-2 truncate font-medium\">{file.name}</p>\n <p className=\"text-caption opacity-dim-1\">{formatFileSize(file.size, locale)}</p>\n </div>\n {uploadProgress !== undefined && (\n <div className=\"mt-md\">\n <Progress value={uploadProgress} max={100} aria-label={progressAriaLabel} />\n </div>\n )}\n </div>\n\n <ItemDeleteTrigger aria-label={deleteButtonAriaLabel} file={file} />\n </li>\n )\n}\n\nAcceptedFile.displayName = 'FileUpload.AcceptedFile'\n","import { Close } from '@spark-ui/icons/Close'\nimport { cx } from 'class-variance-authority'\nimport { useRef } from 'react'\n\nimport { Icon } from '../icon'\nimport { IconButton } from '../icon-button'\nimport { useFileUploadContext } from './FileUpload'\n\nexport interface FileUploadItemDeleteTriggerProps extends React.ComponentProps<typeof IconButton> {\n /**\n * The file to delete\n */\n file: File\n}\n\nexport const ItemDeleteTrigger = ({\n className,\n file,\n onClick,\n ...props\n}: FileUploadItemDeleteTriggerProps) => {\n const { removeFile, triggerRef, dropzoneRef, deleteButtonRefs, disabled, readOnly, files } =\n useFileUploadContext()\n const buttonRef = useRef<HTMLButtonElement>(null)\n\n // Find the index of the file using name + size (consistent with duplicate detection logic)\n const fileIndex = files.findIndex(f => f.name === file.name && f.size === file.size)\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n // Don't allow removing files when disabled or readOnly\n if (disabled || readOnly) {\n return\n }\n\n // Remove the file\n removeFile(fileIndex)\n\n // Handle focus after removal\n setTimeout(() => {\n // Get all remaining delete buttons from the refs array\n const remainingButtons = deleteButtonRefs.current.filter(Boolean)\n\n if (remainingButtons.length > 0) {\n // Find the button that should receive focus\n // We want to focus on the button that takes the same position as the removed one\n // If that position doesn't exist (we removed the last item), focus on the previous one\n const targetIndex = Math.min(fileIndex, remainingButtons.length - 1)\n const nextButton = remainingButtons[targetIndex]\n\n if (nextButton) {\n nextButton.focus()\n }\n } else {\n // No more files, focus on trigger or dropzone\n const focusTarget = triggerRef.current || dropzoneRef.current\n if (focusTarget) {\n focusTarget.focus()\n }\n }\n }, 0)\n\n onClick?.(e)\n }\n\n const setRef = (node: HTMLButtonElement | null) => {\n buttonRef.current = node\n if (node) {\n // Ensure the array is large enough\n while (deleteButtonRefs.current.length <= fileIndex) {\n deleteButtonRefs.current.push(null as any)\n }\n deleteButtonRefs.current[fileIndex] = node\n } else {\n // Remove the ref when component unmounts\n if (deleteButtonRefs.current[fileIndex]) {\n deleteButtonRefs.current[fileIndex] = null as any\n }\n }\n }\n\n return (\n <IconButton\n ref={setRef}\n data-spark-component=\"file-upload-item-delete-trigger\"\n className={cx(className)}\n onClick={handleClick}\n disabled={disabled || readOnly}\n size=\"sm\"\n design=\"contrast\"\n intent=\"surface\"\n {...props}\n >\n <Icon size=\"sm\">\n <Close />\n </Icon>\n </IconButton>\n )\n}\n\nItemDeleteTrigger.displayName = 'FileUpload.ItemDeleteTrigger'\n","import { ReactNode } from 'react'\n\nimport { type RejectedFile, useFileUploadContext } from './FileUpload'\nimport { formatFileSize } from './utils'\n\nexport interface FileUploadContextProps {\n /**\n * Render prop that receives acceptedFiles, rejectedFiles, formatFileSize, and locale\n */\n children: (props: {\n acceptedFiles: File[]\n rejectedFiles: RejectedFile[]\n formatFileSize: (bytes: number, locale?: string) => string\n locale?: string\n }) => ReactNode\n}\n\nexport const Context = ({ children }: FileUploadContextProps) => {\n const { files = [], rejectedFiles = [], locale } = useFileUploadContext()\n\n return (\n <>\n {children({\n acceptedFiles: files,\n rejectedFiles,\n formatFileSize,\n locale,\n })}\n </>\n )\n}\n\nContext.displayName = 'FileUpload.Context'\n","import { cx } from 'class-variance-authority'\nimport { createContext, useContext, useRef } from 'react'\n\nimport { useFileUploadContext } from './FileUpload'\n\n// Context to signal that we're inside a Dropzone\nexport const DropzoneContext = createContext<boolean>(false)\n\nexport const useDropzoneContext = () => useContext(DropzoneContext)\n\nexport function Dropzone({\n children,\n className,\n unstyled = false,\n}: {\n children?: React.ReactNode\n className?: string\n unstyled?: boolean\n}) {\n const ctx = useFileUploadContext()\n const dropzoneRef = useRef<HTMLDivElement>(null)\n\n if (!ctx) throw new Error('FileUploadDropzone must be used inside <FileUpload>')\n\n const handleDrop = (e: React.DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n e.currentTarget.setAttribute('data-drag-over', 'false')\n\n // Don't allow dropping files when disabled or readOnly\n if (ctx.disabled || ctx.readOnly) {\n return\n }\n\n const files = e.dataTransfer.files\n\n // Add files to the context\n // Convert to array - handle both FileList and array (for tests)\n let filesArray: File[] = []\n if (files) {\n filesArray = Array.isArray(files) ? [...files] : Array.from(files)\n }\n\n if (filesArray.length > 0) {\n ctx.addFiles(filesArray)\n }\n }\n\n const handleClick = () => {\n if (!ctx.disabled && !ctx.readOnly) {\n ctx.inputRef.current?.click()\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n if (!ctx.disabled && !ctx.readOnly) {\n ctx.inputRef.current?.click()\n }\n }\n }\n\n const isDisabled = ctx.disabled || ctx.readOnly\n\n return (\n <DropzoneContext.Provider value={true}>\n <div\n ref={node => {\n dropzoneRef.current = node\n if (ctx.dropzoneRef) {\n ctx.dropzoneRef.current = node\n }\n }}\n role=\"button\"\n tabIndex={isDisabled ? -1 : 0}\n aria-disabled={ctx.disabled ? true : undefined}\n aria-describedby={ctx.description}\n aria-invalid={ctx.isInvalid}\n aria-required={ctx.isRequired}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n onDrop={handleDrop}\n onDragOver={e => {\n e.preventDefault()\n }}\n className={\n unstyled\n ? className\n : cx(\n 'default:bg-surface default:border-sm default:border-outline default:relative default:rounded-lg default:border-dashed',\n 'gap-lg flex flex-col items-center justify-center text-center',\n 'default:p-xl',\n 'transition-colors duration-200',\n !isDisabled && 'default:hover:bg-surface-hovered',\n 'data-[drag-over=true]:border-outline-high data-[drag-over=true]:bg-surface-hovered data-[drag-over=true]:border-solid',\n // Disabled: more visually disabled (opacity + cursor)\n ctx.disabled && 'cursor-not-allowed opacity-50',\n // ReadOnly: less visually disabled (just cursor, no opacity)\n ctx.readOnly && !ctx.disabled && 'cursor-default',\n className\n )\n }\n onDragEnter={e => {\n if (!isDisabled) {\n e.currentTarget.setAttribute('data-drag-over', 'true')\n }\n }}\n onDragLeave={e => {\n e.currentTarget.setAttribute('data-drag-over', 'false')\n }}\n >\n {children}\n </div>\n </DropzoneContext.Provider>\n )\n}\n\nDropzone.displayName = 'FileUploadDropzone'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, Ref, useEffect, useState } from 'react'\n\nexport interface FileUploadPreviewImageProps extends ComponentPropsWithoutRef<'div'> {\n /**\n * Change the default rendered element for the one passed as a child, merging their props and behavior.\n */\n asChild?: boolean\n ref?: Ref<HTMLDivElement>\n className?: string\n /**\n * The file to preview\n */\n file: File\n /**\n * Fallback content when file is not an image or preview fails\n */\n fallback?: React.ReactNode\n}\n\nexport const PreviewImage = ({\n asChild: _asChild = false,\n className,\n file,\n fallback = '📄',\n ...props\n}: FileUploadPreviewImageProps) => {\n const [imageError, setImageError] = useState(false)\n const [imageLoaded, setImageLoaded] = useState(false)\n\n const isImage = file.type.startsWith('image/')\n const imageUrl = isImage ? URL.createObjectURL(file) : null\n\n // Clean up the object URL when component unmounts or file changes\n useEffect(() => {\n return () => {\n if (imageUrl) {\n URL.revokeObjectURL(imageUrl)\n }\n }\n }, [imageUrl])\n\n if (!isImage || imageError) {\n return (\n <div\n data-spark-component=\"file-upload-preview-image\"\n className={cx(\n 'bg-neutral-container flex items-center justify-center rounded-md',\n className\n )}\n {...props}\n >\n {fallback}\n </div>\n )\n }\n\n return (\n <div\n data-spark-component=\"file-upload-preview-image\"\n className={cx('bg-neutral-container overflow-hidden', className)}\n {...props}\n >\n <img\n src={imageUrl!}\n alt={file.name}\n className={cx('size-full object-cover', !imageLoaded && 'opacity-0')}\n onLoad={() => setImageLoaded(true)}\n onError={() => setImageError(true)}\n />\n {!imageLoaded && (\n <div className=\"absolute inset-0 flex items-center justify-center\">{fallback}</div>\n )}\n </div>\n )\n}\n\nPreviewImage.displayName = 'FileUpload.PreviewImage'\n","import { WarningOutline } from '@spark-ui/icons/WarningOutline'\nimport { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, Ref } from 'react'\n\nimport { Icon } from '../icon'\nimport {\n type FileUploadFileError,\n type RejectedFile as RejectedFileType,\n useFileUploadContext,\n} from './FileUpload'\nimport { RejectedFileDeleteTrigger } from './FileUploadRejectedFileDeleteTrigger'\nimport { formatFileSize } from './utils'\n\nexport interface FileUploadRejectedFileProps extends ComponentPropsWithoutRef<'li'> {\n /**\n * Change the default rendered element for the one passed as a child, merging their props and behavior.\n */\n asChild?: boolean\n ref?: Ref<HTMLLIElement>\n /**\n * The rejected file to display\n */\n rejectedFile: RejectedFileType\n /**\n * Function to render the error message for each error code\n * @param error - The error code\n * @returns The error message to display\n */\n renderError: (error: FileUploadFileError) => string\n /**\n * Accessible label for the delete button\n */\n deleteButtonAriaLabel: string\n className?: string\n}\n\nexport const RejectedFile = ({\n asChild: _asChild = false,\n className,\n rejectedFile,\n renderError,\n deleteButtonAriaLabel,\n ...props\n}: FileUploadRejectedFileProps) => {\n const { locale } = useFileUploadContext()\n\n return (\n <li\n data-spark-component=\"file-upload-rejected-file\"\n className={cx(\n 'relative',\n 'default:bg-surface default:border-sm default:border-outline default:p-md default:rounded-md',\n 'gap-md flex items-center justify-between default:w-full',\n 'border-error border-md',\n className\n )}\n {...props}\n >\n <div className=\"size-sz-40 bg-error-container flex items-center justify-center rounded-md\">\n <Icon size=\"md\" className=\"text-error\">\n <WarningOutline />\n </Icon>\n </div>\n\n <div className=\"min-w-0 flex-1\">\n <div className=\"gap-md flex flex-col\">\n <div className=\"gap-md flex flex-row items-center justify-between\">\n <p className=\"text-body-2 truncate font-medium\">{rejectedFile.file.name}</p>\n <p className=\"text-caption opacity-dim-1\">\n {formatFileSize(rejectedFile.file.size, locale)}\n </p>\n </div>\n <div className=\"gap-xs flex flex-col\">\n {rejectedFile.errors.map((error, errorIndex) => (\n <div key={errorIndex} className=\"text-caption text-error\" data-error-code={error}>\n {renderError(error)}\n </div>\n ))}\n </div>\n </div>\n </div>\n\n <RejectedFileDeleteTrigger aria-label={deleteButtonAriaLabel} rejectedFile={rejectedFile} />\n </li>\n )\n}\n\nRejectedFile.displayName = 'FileUpload.RejectedFile'\n","import { Close } from '@spark-ui/icons/Close'\nimport { cx } from 'class-variance-authority'\nimport { useRef } from 'react'\n\nimport { Icon } from '../icon'\nimport { IconButton } from '../icon-button'\nimport { type RejectedFile as RejectedFileType, useFileUploadContext } from './FileUpload'\n\nexport interface FileUploadRejectedFileDeleteTriggerProps\n extends React.ComponentProps<typeof IconButton> {\n /**\n * The rejected file to remove\n */\n rejectedFile: RejectedFileType\n}\n\nexport const RejectedFileDeleteTrigger = ({\n className,\n rejectedFile,\n onClick,\n ...props\n}: FileUploadRejectedFileDeleteTriggerProps) => {\n const { removeRejectedFile, triggerRef, dropzoneRef, disabled, readOnly, rejectedFiles } =\n useFileUploadContext()\n const buttonRef = useRef<HTMLButtonElement>(null)\n\n // Find the index of the rejected file using name + size (consistent with duplicate detection logic)\n const rejectedFileIndex = rejectedFiles.findIndex(\n rf => rf.file.name === rejectedFile.file.name && rf.file.size === rejectedFile.file.size\n )\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n // Don't allow removing rejected files when disabled or readOnly\n if (disabled || readOnly) {\n return\n }\n\n // Remove the rejected file\n removeRejectedFile(rejectedFileIndex)\n\n // Handle focus after removal\n setTimeout(() => {\n // Try to focus on trigger or dropzone if available\n const focusTarget = triggerRef.current || dropzoneRef.current\n if (focusTarget) {\n focusTarget.focus()\n }\n }, 0)\n\n onClick?.(e)\n }\n\n return (\n <IconButton\n ref={buttonRef}\n data-spark-component=\"file-upload-rejected-file-delete-trigger\"\n className={cx(className)}\n onClick={handleClick}\n disabled={disabled || readOnly}\n size=\"sm\"\n design=\"contrast\"\n intent=\"surface\"\n {...props}\n >\n <Icon size=\"sm\">\n <Close />\n </Icon>\n </IconButton>\n )\n}\n\nRejectedFileDeleteTrigger.displayName = 'FileUpload.RejectedFileDeleteTrigger'\n","import { cx } from 'class-variance-authority'\nimport React, { ReactNode, Ref } from 'react'\n\nimport { Button, type ButtonProps } from '../button'\nimport { buttonStyles } from '../button/Button.styles'\nimport { Slot } from '../slot'\nimport { useFileUploadContext } from './FileUpload'\nimport { useDropzoneContext } from './FileUploadDropzone'\n\nexport interface FileUploadTriggerProps extends Omit<ButtonProps, 'children' | 'disabled'> {\n ref?: Ref<HTMLButtonElement>\n className?: string\n children: ReactNode\n unstyled?: boolean\n}\n\nexport const Trigger = ({\n className,\n children,\n asChild = false,\n unstyled = false,\n design = 'filled',\n intent = 'basic',\n size = 'md',\n shape = 'rounded',\n ref,\n ...props\n}: FileUploadTriggerProps) => {\n const { inputRef, triggerRef, disabled, readOnly, description, isInvalid, isRequired } =\n useFileUploadContext()\n const isInsideDropzone = useDropzoneContext()\n\n const handleClick = (e: React.MouseEvent) => {\n e.stopPropagation()\n e.preventDefault()\n if (!disabled && !readOnly) {\n inputRef.current?.click()\n }\n }\n\n // Shared ref forwarding logic\n const handleRef = (node: HTMLElement | null) => {\n // Forward ref to both the context ref and the user ref\n if (triggerRef) {\n triggerRef.current = node\n }\n if (ref) {\n if (typeof ref === 'function') {\n ref(node as HTMLButtonElement)\n } else {\n ref.current = node as HTMLButtonElement\n }\n }\n }\n\n // Determine component and props based on context\n // If inside a Dropzone, render as a non-interactive span\n // The Dropzone handles all interactions\n let Component: React.ElementType\n let componentProps: Record<string, unknown>\n\n if (isInsideDropzone) {\n // Don't use asChild when inside Dropzone - we always want a span\n Component = 'span'\n const spanStyles = unstyled\n ? className\n : buttonStyles({\n design,\n intent,\n size,\n shape,\n disabled: disabled || readOnly,\n className,\n })\n\n componentProps = {\n ref: handleRef,\n 'data-spark-component': 'file-upload-trigger',\n className: spanStyles,\n // No onClick, no role, no tabIndex - Dropzone handles interaction\n // No aria attributes here - they're on the Dropzone\n }\n } else {\n // Normal behavior when not inside Dropzone\n const buttonComponent = unstyled ? 'button' : Button\n Component = asChild ? Slot : buttonComponent\n\n componentProps = {\n ref: handleRef,\n type: 'button',\n design,\n intent,\n size,\n shape,\n 'data-spark-component': 'file-upload-trigger',\n className: cx(className),\n disabled: disabled || readOnly,\n onClick: handleClick,\n 'aria-describedby': description,\n 'aria-invalid': isInvalid,\n 'aria-required': isRequired,\n ...props,\n }\n }\n\n return <Component {...componentProps}>{children}</Component>\n}\n\nTrigger.displayName = 'FileUpload.Trigger'\n","import {\n type FileAcceptDetails,\n type FileChangeDetails,\n type FileRejectDetails,\n FileUpload as Root,\n type FileUploadFileError,\n type RejectedFile,\n} from './FileUpload'\nimport { AcceptedFile } from './FileUploadAcceptedFile'\nimport { Context } from './FileUploadContext'\nimport { Dropzone } from './FileUploadDropzone'\nimport { ItemDeleteTrigger } from './FileUploadItemDeleteTrigger'\nimport { PreviewImage } from './FileUploadPreviewImage'\nimport { RejectedFile as RejectedFileComponent } from './FileUploadRejectedFile'\nimport { RejectedFileDeleteTrigger } from './FileUploadRejectedFileDeleteTrigger'\nimport { Trigger } from './FileUploadTrigger'\n\nexport type {\n FileAcceptDetails,\n FileChangeDetails,\n FileRejectDetails,\n RejectedFile,\n FileUploadFileError,\n}\n\nexport const FileUpload: typeof Root & {\n Trigger: typeof Trigger\n Dropzone: typeof Dropzone\n Context: typeof Context\n ItemDeleteTrigger: typeof ItemDeleteTrigger\n PreviewImage: typeof PreviewImage\n AcceptedFile: typeof AcceptedFile\n RejectedFile: typeof RejectedFileComponent\n RejectedFileDeleteTrigger: typeof RejectedFileDeleteTrigger\n} = Object.assign(Root, {\n // Main input components\n Trigger,\n Dropzone,\n // Context components\n Context,\n AcceptedFile,\n RejectedFile: RejectedFileComponent,\n // Helpers for custom renders\n PreviewImage,\n ItemDeleteTrigger,\n RejectedFileDeleteTrigger,\n})\n\nFileUpload.displayName = 'FileUpload'\nTrigger.displayName = 'FileUpload.Trigger'\nDropzone.displayName = 'FileUpload.Dropzone'\nContext.displayName = 'FileUpload.Context'\nItemDeleteTrigger.displayName = 'FileUpload.ItemDeleteTrigger'\nPreviewImage.displayName = 'FileUpload.PreviewImage'\nAcceptedFile.displayName = 'FileUpload.AcceptedFile'\nRejectedFileComponent.displayName = 'FileUpload.RejectedFile'\nRejectedFileDeleteTrigger.displayName = 'FileUpload.RejectedFileDeleteTrigger'\n"],"mappings":"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","names":["extension","fileName","formatter","cx","useRef","jsx","useRef","jsx","jsxs","cx","jsx","cx","createContext","useContext","useRef","jsx","createContext","useContext","useRef","cx","cx","useState","jsx","jsxs","cx","Close","cx","useRef","jsx","useRef","cx","Close","jsx","jsxs","cx","cx","jsx","cx","FileUpload"]}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IconButton
3
- } from "../chunk-XYK6V3JF.mjs";
4
- import "../chunk-HEKSVWYW.mjs";
3
+ } from "../chunk-DCXWGQVZ.mjs";
4
+ import "../chunk-2YM6GKWW.mjs";
5
5
  import "../chunk-GAK4SC2F.mjs";
6
6
  import "../chunk-KEGAAGJW.mjs";
7
7
  import "../chunk-6QCEPQ3U.mjs";
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  IconButton
3
- } from "../chunk-XYK6V3JF.mjs";
4
- import {
5
- Icon
6
- } from "../chunk-UMUMFMFB.mjs";
3
+ } from "../chunk-DCXWGQVZ.mjs";
7
4
  import {
8
5
  Button
9
- } from "../chunk-HEKSVWYW.mjs";
6
+ } from "../chunk-2YM6GKWW.mjs";
10
7
  import "../chunk-GAK4SC2F.mjs";
8
+ import {
9
+ Icon
10
+ } from "../chunk-UMUMFMFB.mjs";
11
11
  import "../chunk-KEGAAGJW.mjs";
12
12
  import "../chunk-6QCEPQ3U.mjs";
13
13
 
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  Popover
3
- } from "../chunk-D7YBYT5H.mjs";
4
- import "../chunk-XYK6V3JF.mjs";
5
- import "../chunk-UMUMFMFB.mjs";
6
- import "../chunk-HEKSVWYW.mjs";
3
+ } from "../chunk-GPJMLIHC.mjs";
4
+ import "../chunk-DCXWGQVZ.mjs";
5
+ import "../chunk-2YM6GKWW.mjs";
7
6
  import "../chunk-GAK4SC2F.mjs";
7
+ import "../chunk-UMUMFMFB.mjs";
8
8
  import "../chunk-KEGAAGJW.mjs";
9
9
  import "../chunk-6QCEPQ3U.mjs";
10
10
  export {
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  IconButton
3
- } from "../chunk-XYK6V3JF.mjs";
4
- import {
5
- Icon
6
- } from "../chunk-UMUMFMFB.mjs";
3
+ } from "../chunk-DCXWGQVZ.mjs";
7
4
  import {
8
5
  Button
9
- } from "../chunk-HEKSVWYW.mjs";
6
+ } from "../chunk-2YM6GKWW.mjs";
10
7
  import "../chunk-GAK4SC2F.mjs";
8
+ import {
9
+ Icon
10
+ } from "../chunk-UMUMFMFB.mjs";
11
11
  import "../chunk-KEGAAGJW.mjs";
12
12
  import {
13
13
  Slot
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  IconButton
3
- } from "../chunk-XYK6V3JF.mjs";
4
- import {
5
- Icon
6
- } from "../chunk-UMUMFMFB.mjs";
3
+ } from "../chunk-DCXWGQVZ.mjs";
7
4
  import {
8
5
  Button
9
- } from "../chunk-HEKSVWYW.mjs";
6
+ } from "../chunk-2YM6GKWW.mjs";
10
7
  import "../chunk-GAK4SC2F.mjs";
8
+ import {
9
+ Icon
10
+ } from "../chunk-UMUMFMFB.mjs";
11
11
  import "../chunk-KEGAAGJW.mjs";
12
12
  import "../chunk-6QCEPQ3U.mjs";
13
13
 
@@ -4,12 +4,12 @@ import {
4
4
  } from "../chunk-VBX7BTNU.mjs";
5
5
  import {
6
6
  IconButton
7
- } from "../chunk-XYK6V3JF.mjs";
7
+ } from "../chunk-DCXWGQVZ.mjs";
8
+ import "../chunk-2YM6GKWW.mjs";
9
+ import "../chunk-GAK4SC2F.mjs";
8
10
  import {
9
11
  Icon
10
12
  } from "../chunk-UMUMFMFB.mjs";
11
- import "../chunk-HEKSVWYW.mjs";
12
- import "../chunk-GAK4SC2F.mjs";
13
13
  import "../chunk-KEGAAGJW.mjs";
14
14
  import "../chunk-6QCEPQ3U.mjs";
15
15
 
@@ -1,10 +1,10 @@
1
- import {
2
- Icon
3
- } from "../chunk-UMUMFMFB.mjs";
4
1
  import {
5
2
  Button
6
- } from "../chunk-HEKSVWYW.mjs";
3
+ } from "../chunk-2YM6GKWW.mjs";
7
4
  import "../chunk-GAK4SC2F.mjs";
5
+ import {
6
+ Icon
7
+ } from "../chunk-UMUMFMFB.mjs";
8
8
  import "../chunk-KEGAAGJW.mjs";
9
9
  import "../chunk-6QCEPQ3U.mjs";
10
10
 
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { Toast } from '@base-ui-components/react/toast';
3
- import * as React from 'react';
3
+ import * as react from 'react';
4
4
  import { ButtonProps } from '../button/index.mjs';
5
5
  import 'class-variance-authority/types';
6
6
  import 'class-variance-authority';
@@ -8,7 +8,7 @@ import 'class-variance-authority';
8
8
  type ToastIntent = 'main' | 'support' | 'accent' | 'basic' | 'success' | 'alert' | 'error' | 'info' | 'neutral' | 'surface' | 'surfaceInverse';
9
9
  type ToastDesign = 'tinted' | 'filled';
10
10
  interface ToastData {
11
- icon?: React.ReactNode;
11
+ icon?: react.ReactNode;
12
12
  design?: ToastDesign;
13
13
  intent?: ToastIntent;
14
14
  isClosable?: boolean;
@@ -41,12 +41,12 @@ interface UseToastManagerReturnValue {
41
41
 
42
42
  declare function useToastManager(): UseToastManagerReturnValue;
43
43
 
44
- interface ToastProviderProps extends React.ComponentProps<typeof Toast.Provider> {
45
- children: React.ReactNode;
44
+ interface ToastProviderProps extends react.ComponentProps<typeof Toast.Provider> {
45
+ children: react.ReactNode;
46
46
  }
47
47
  declare function ToastProvider({ children, limit, ...props }: ToastProviderProps): react_jsx_runtime.JSX.Element;
48
- interface ToastTriggerProps extends React.ComponentPropsWithRef<'button'>, Pick<ToastObject, 'priority'>, Pick<ToastData, 'design' | 'intent' | 'icon' | 'isClosable' | 'action' | 'compact'> {
49
- children: React.ReactNode;
48
+ interface ToastTriggerProps extends react.ComponentPropsWithRef<'button'>, Pick<ToastObject, 'priority'>, Pick<ToastData, 'design' | 'intent' | 'icon' | 'isClosable' | 'action' | 'compact'> {
49
+ children: react.ReactNode;
50
50
  asChild?: boolean;
51
51
  title: string;
52
52
  description?: string;