feat: file upload by agent (first gen)#416
Open
lskramarov wants to merge 1 commit into
Open
Conversation
|
Visit the preview URL for this PR (updated for commit ab92fe8): https://react-koobiq-next--prs-416-8r0hrlqz.web.app (expires Wed, 15 Jul 2026 09:20:22 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 Sign: fc29847d4a9e5cb1adf458c76a9b681c76e2eeff |
There was a problem hiding this comment.
Pull request overview
This PR introduces a new FileUpload component suite to @koobiq/react-components, providing single- and multiple-file upload UIs plus supporting primitives (dropzones, input wrapper, hooks), localization, validators, and API extraction/guard wiring.
Changes:
- Adds
SingleFileUploadandMultipleFileUploadcomponents with drag-and-drop support, optional full-screen/local dropzones, progress display, and external-validation patterns. - Introduces supporting primitives and hooks (
FileInput,useFileDrop,useFileList,useFileUploadState, locale resolution, etc.) plus locale bundles and docs/stories. - Registers FileUpload in API Extractor and adds the generated public API report.
Reviewed changes
Copilot reviewed 58 out of 58 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/public_api_guard/components/FileUpload.api.md | New generated API report for FileUpload public surface |
| tools/api-extractor/config.json | Registers FileUpload for API extraction |
| packages/components/src/components/index.ts | Re-exports FileUpload from the components barrel |
| packages/components/src/components/FileUpload/validators.ts | Adds file validators (maxFileSize, isCorrectExtension) |
| packages/components/src/components/FileUpload/utils.ts | Shared utilities (data size formatting, DnD extraction, directory unwrap) |
| packages/components/src/components/FileUpload/types.ts | Public types for FileUpload components/primitives |
| packages/components/src/components/FileUpload/SingleFileUpload.tsx | Implements single-file uploader component |
| packages/components/src/components/FileUpload/SingleFileUpload.test.tsx | Tests for SingleFileUpload behavior and a11y basics |
| packages/components/src/components/FileUpload/SingleFileUpload.module.css | Single uploader style overrides via CSS custom properties |
| packages/components/src/components/FileUpload/primitives.test.tsx | Tests for primitives/hooks/utilities/validators |
| packages/components/src/components/FileUpload/MultipleFileUpload.tsx | Implements multiple-file uploader component |
| packages/components/src/components/FileUpload/MultipleFileUpload.test.tsx | Tests for MultipleFileUpload list behavior and interactions |
| packages/components/src/components/FileUpload/MultipleFileUpload.module.css | Multiple uploader layout/list styling |
| packages/components/src/components/FileUpload/locales.ts | Bundled locale configs + default/fallback mapping |
| packages/components/src/components/FileUpload/locales.test.tsx | Tests for locale resolution and overrides |
| packages/components/src/components/FileUpload/intl.json | Localized strings for dropzone overlay title / remove label |
| packages/components/src/components/FileUpload/index.ts | Public exports for FileUpload package surface |
| packages/components/src/components/FileUpload/hooks/useFullScreenDropzone/useFullScreenDropzone.ts | Hook for document-level full-screen dropzone behavior |
| packages/components/src/components/FileUpload/hooks/useFullScreenDropzone/index.ts | Barrel export for useFullScreenDropzone |
| packages/components/src/components/FileUpload/hooks/useFileUploadState/useFileUploadState.ts | Hook for touched/dirty/error visibility state |
| packages/components/src/components/FileUpload/hooks/useFileUploadState/index.ts | Barrel export for useFileUploadState |
| packages/components/src/components/FileUpload/hooks/useFileUploadLocale/useFileUploadLocale.ts | Hooks to resolve locale config + caption context |
| packages/components/src/components/FileUpload/hooks/useFileUploadLocale/index.ts | Barrel export for locale hooks |
| packages/components/src/components/FileUpload/hooks/useFileUploadItem/useFileUploadItem.ts | Hook deriving loading/progress display state |
| packages/components/src/components/FileUpload/hooks/useFileUploadItem/index.ts | Barrel export for useFileUploadItem |
| packages/components/src/components/FileUpload/hooks/useFileList/useFileList.ts | Headless list-state hook for upload items |
| packages/components/src/components/FileUpload/hooks/useFileList/index.ts | Barrel export for useFileList |
| packages/components/src/components/FileUpload/hooks/useFileInput/useFileInput.ts | Hook mapping props/context to a native file input + reset |
| packages/components/src/components/FileUpload/hooks/useFileInput/index.ts | Barrel export for useFileInput |
| packages/components/src/components/FileUpload/hooks/useFileDrop/useFileDrop.ts | Hook attaching native DnD listeners and dragover state |
| packages/components/src/components/FileUpload/hooks/useFileDrop/index.ts | Barrel export for useFileDrop |
| packages/components/src/components/FileUpload/hooks/index.ts | Aggregated hook exports |
| packages/components/src/components/FileUpload/FileUploadContext.ts | Context for upload primitives configuration |
| packages/components/src/components/FileUpload/FileUpload.stories.tsx | Storybook stories demonstrating features and patterns |
| packages/components/src/components/FileUpload/FileUpload.module.css | Shared base styling for the upload UI |
| packages/components/src/components/FileUpload/FileUpload.mdx | Documentation page for FileUpload |
| packages/components/src/components/FileUpload/errorPredicates.ts | Error-visibility predicate helpers |
| packages/components/src/components/FileUpload/dropzones.test.tsx | Tests for full-screen and local dropzone behavior |
| packages/components/src/components/FileUpload/constants.ts | Shared constants (name truncation tail length, focus return delay) |
| packages/components/src/components/FileUpload/components/LocalDropzone/LocalDropzone.tsx | Scoped/host-positioned dropzone overlay component |
| packages/components/src/components/FileUpload/components/LocalDropzone/LocalDropzone.module.css | Local dropzone overlay/host styling |
| packages/components/src/components/FileUpload/components/LocalDropzone/index.ts | Barrel export for LocalDropzone |
| packages/components/src/components/FileUpload/components/index.ts | Aggregated primitive component exports |
| packages/components/src/components/FileUpload/components/FullScreenDropzone/index.ts | Barrel export for FullScreenDropzone |
| packages/components/src/components/FileUpload/components/FullScreenDropzone/FullScreenDropzone.tsx | Portalled full-screen overlay component |
| packages/components/src/components/FileUpload/components/FullScreenDropzone/FullScreenDropzone.module.css | Full-screen overlay styling |
| packages/components/src/components/FileUpload/components/FileUploadProvider/index.ts | Barrel export for FileUploadProvider |
| packages/components/src/components/FileUpload/components/FileUploadProvider/FileUploadProvider.tsx | Provider for FileUploadContext values |
| packages/components/src/components/FileUpload/components/FileUploadItem/index.ts | Barrel export for FileUploadItem |
| packages/components/src/components/FileUpload/components/FileUploadItem/FileUploadItem.tsx | Renders a file row (icon/progress, name, size, remove) |
| packages/components/src/components/FileUpload/components/FileUploadItem/FileUploadItem.module.css | File item row styling |
| packages/components/src/components/FileUpload/components/FileUploadCaption/index.ts | Barrel export for FileUploadCaption |
| packages/components/src/components/FileUpload/components/FileUploadCaption/FileUploadCaption.tsx | Caption rendering (text + browse links) |
| packages/components/src/components/FileUpload/components/FileInput/index.ts | Barrel export for FileInput |
| packages/components/src/components/FileUpload/components/FileInput/FileInput.tsx | Label-wrapped hidden file input primitive |
| packages/components/src/components/FileUpload/components/DropzoneContent/index.ts | Barrel export for DropzoneContent |
| packages/components/src/components/FileUpload/components/DropzoneContent/DropzoneContent.tsx | Overlay content (icon/title/caption) with focus trapping |
| packages/components/src/components/FileUpload/components/DropzoneContent/DropzoneContent.module.css | DropzoneContent layout styling |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+171
to
+182
| export const extractDroppedFiles = async ( | ||
| dataTransfer: DataTransfer | ||
| ): Promise<FileWithPath[]> => { | ||
| const entries = Array.from(dataTransfer.items) | ||
| .filter((item) => item.kind === 'file') | ||
| .map((item) => item.webkitGetAsEntry()) | ||
| .filter((entry): entry is FileSystemEntry => entry != null); | ||
|
|
||
| const groups = await Promise.all(entries.map(unwrapDirectory)); | ||
|
|
||
| return groups.reduce<FileWithPath[]>((acc, group) => acc.concat(group), []); | ||
| }; |
Comment on lines
+141
to
+147
| const reader = next.createReader(); | ||
|
|
||
| queue.push( | ||
| new Promise<FileSystemEntry[]>((resolve, reject) => | ||
| reader.readEntries(resolve, reject) | ||
| ) | ||
| ); |
Comment on lines
+108
to
+112
| if (event.dataTransfer && event.dataTransfer.items.length > 0) { | ||
| void extractDroppedFiles(event.dataTransfer).then((files) => | ||
| onDropRef.current(files) | ||
| ); | ||
| } |
Comment on lines
+116
to
+120
| if (event.dataTransfer && event.dataTransfer.items.length > 0) { | ||
| void extractDroppedFiles(event.dataTransfer).then((files) => | ||
| onDropRef.current(files) | ||
| ); | ||
| } |
Comment on lines
+143
to
+147
| if (event.dataTransfer && event.dataTransfer.items.length > 0) { | ||
| void extractDroppedFiles(event.dataTransfer).then((files) => | ||
| connectedTo.current?.addFiles(files) | ||
| ); | ||
| } |
| disabled?: boolean; | ||
| }; | ||
|
|
||
| type SingleFileUploadOwnProps = FileUploadSharedProps & { |
| Omit<ComponentPropsWithoutRef<'div'>, 'onChange' | 'defaultValue' | 'color'> | ||
| >; | ||
|
|
||
| type MultipleFileUploadOwnProps = FileUploadSharedProps & { |
Comment on lines
+51
to
+55
| <FileInput | ||
| id={inputId} | ||
| accept={accept} | ||
| multiple | ||
| isDisabled={isDisabled} |
Comment on lines
+282
to
+286
| // Warning: (ae-forgotten-export) The symbol "MultipleFileUploadOwnProps" needs to be exported by the entry point index.d.ts | ||
| // | ||
| // @public (undocumented) | ||
| export type MultipleFileUploadProps = ExtendableProps<MultipleFileUploadOwnProps, Omit<ComponentPropsWithoutRef<'div'>, 'onChange' | 'defaultValue' | 'color'>>; | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.