{"_id":"@atom_design/upload","name":"@atom_design/upload","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@atom_design/upload","version":"1.0.0","description":"A React Native file upload component with progress indicator, image picker, and camera fallback. Part of the Atom Design System.","main":"index.js","types":"index.d.ts","author":{"name":"Atom Design"},"license":"MIT","keywords":["react-native","upload","file-upload","image-picker","progress","file-picker","ui-component","atom-design"],"peerDependencies":{"react":">=17.0.0","react-native":">=0.64.0","prop-types":">=15.0.0","react-native-image-picker":">=5.0.0","react-native-progress":">=5.0.0","react-native-vector-icons":">=9.0.0"},"_id":"@atom_design/upload@1.0.0","_nodeVersion":"20.19.5","_npmVersion":"10.8.2","dist":{"integrity":"sha512-wnSNQVYr8JDbEkNOWbb5S0/JZ1v19oFvboqnrxFxaPYUhXOT5gVl5lvUg6taIeZRXsAE/tmyxl6YJccJL93RGQ==","shasum":"c232d39dac9108b0b0784a4d3660f6baf394d8a3","tarball":"https://registry.npmjs.org/@atom_design/upload/-/upload-1.0.0.tgz","fileCount":5,"unpackedSize":23640,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCGwo+p03QQKAAvQwt3z4D+oyr8QWqlqQawgxIbz1WoIwIgZ/Rp9q9+N8jGhvsHqYIgCtVl+dNTUNPA+KI3RT/4xIc="}]},"_npmUser":{"name":"avi-moglix","email":"avi.gupta@moglix.com"},"directories":{},"maintainers":[{"name":"moglix","email":"devops@moglix.com"},{"name":"avi-moglix","email":"avi.gupta@moglix.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/upload_1.0.0_1764751454903_0.668947365809953"},"_hasShrinkwrap":false}},"time":{"created":"2025-12-03T08:44:14.785Z","1.0.0":"2025-12-03T08:44:15.105Z","modified":"2025-12-03T08:44:15.443Z"},"maintainers":[{"name":"moglix","email":"devops@moglix.com"},{"name":"avi-moglix","email":"avi.gupta@moglix.com"}],"description":"A React Native file upload component with progress indicator, image picker, and camera fallback. Part of the Atom Design System.","keywords":["react-native","upload","file-upload","image-picker","progress","file-picker","ui-component","atom-design"],"author":{"name":"Atom Design"},"license":"MIT","readme":"# @atom_design/upload\n\nA React Native file upload component with progress indicator, image picker, and camera fallback. Part of the Atom Design System.\n\n[![npm version](https://img.shields.io/npm/v/@atom_design/upload.svg)](https://www.npmjs.com/package/@atom_design/upload)\n[![license](https://img.shields.io/npm/l/@atom_design/upload.svg)](https://github.com/atom-design/upload/blob/main/LICENSE)\n\n## Features\n\n- 📁 **File Picker** - Select images/videos from library\n- 📷 **Camera Fallback** - Automatic camera fallback if library fails\n- 📊 **Progress Indicator** - Visual upload progress bar\n- 📏 **Size Validation** - Configurable max file size\n- 🎨 **Customizable** - Style all elements with custom props\n- ♿ **Accessible** - Full screen reader support\n- 💪 **TypeScript** - Full type definitions included\n\n---\n\n## 📦 Installation\n\n```bash\nnpm install @atom_design/upload\n# or\nyarn add @atom_design/upload\n```\n\n### Peer Dependencies\n\n```bash\nnpm install react-native-image-picker react-native-progress react-native-vector-icons prop-types\n```\n\n### Platform Setup\n\n**iOS:**\n```bash\ncd ios && pod install\n```\n\nAdd to `Info.plist`:\n```xml\n<key>NSPhotoLibraryUsageDescription</key>\n<string>We need access to your photo library to upload files</string>\n<key>NSCameraUsageDescription</key>\n<string>We need access to your camera to take photos</string>\n```\n\n**Android:**\nAdd to `AndroidManifest.xml`:\n```xml\n<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" />\n<uses-permission android:name=\"android.permission.CAMERA\" />\n```\n\n---\n\n## 🚀 Basic Usage\n\n```jsx\nimport React from 'react';\nimport { View } from 'react-native';\nimport UploadField from '@atom_design/upload';\n\nconst App = () => {\n  const handleFileSelected = (file) => {\n    console.log('Selected:', file);\n  };\n\n  const handleUploadComplete = (file) => {\n    console.log('Uploaded:', file);\n    // Call your upload API here\n  };\n\n  return (\n    <View style={{ flex: 1, padding: 20 }}>\n      <UploadField\n        title=\"Upload Document\"\n        maxSizeMB={10}\n        onFileSelected={handleFileSelected}\n        onUploadComplete={handleUploadComplete}\n      />\n    </View>\n  );\n};\n\nexport default App;\n```\n\n---\n\n## 🧩 Props\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `onFileSelected` | `(file) => void` | - | Callback when file is selected |\n| `onUploadComplete` | `(file) => void` | - | Callback when upload completes |\n| `onFileRemoved` | `(file) => void` | - | Callback when file is removed |\n| `maxSizeMB` | `number` | `50` | Maximum file size in MB |\n| `mediaType` | `'photo' \\| 'video' \\| 'mixed'` | `'mixed'` | Allowed media type |\n| `title` | `string` | `'Upload File'` | Title above upload field |\n| `placeholder` | `string` | `'Select a file'` | Placeholder text |\n| `uploadButtonText` | `string` | `'Upload'` | Button text |\n| `disabled` | `boolean` | `false` | Disable upload |\n| `showCamera` | `boolean` | `true` | Show camera fallback |\n| `containerStyle` | `ViewStyle` | - | Container style |\n| `uploadBoxStyle` | `ViewStyle` | - | Upload box style |\n| `progressColor` | `string` | `'#52B898'` | Progress bar color |\n| `testID` | `string` | - | Test ID |\n\n---\n\n## 📁 File Object\n\nWhen a file is selected, the component returns:\n\n```typescript\ninterface UploadedFile {\n  uri: string;      // File URI\n  name: string;     // File name\n  size: number;     // Size in bytes\n  type: string;     // MIME type\n  width?: number;   // Image/video width\n  height?: number;  // Image/video height\n  duration?: number; // Video duration\n}\n```\n\n---\n\n## 🧪 Test Screen Example\n\n```jsx\nimport React, { useState } from 'react';\nimport { SafeAreaView, ScrollView, Text, StyleSheet, View } from 'react-native';\nimport UploadField from '@atom_design/upload';\n\nconst UploadTestScreen = () => {\n  const [uploadedFile, setUploadedFile] = useState(null);\n\n  return (\n    <SafeAreaView style={styles.container}>\n      <ScrollView contentContainerStyle={styles.content}>\n        <Text style={styles.header}>@atom_design/upload</Text>\n\n        {/* Basic Upload */}\n        <UploadField\n          title=\"Profile Picture\"\n          placeholder=\"Select an image\"\n          mediaType=\"photo\"\n          maxSizeMB={5}\n          onFileSelected={(file) => console.log('Selected:', file.name)}\n          onUploadComplete={(file) => setUploadedFile(file)}\n        />\n\n        {/* Video Upload */}\n        <View style={styles.spacing} />\n        <UploadField\n          title=\"Upload Video\"\n          placeholder=\"Select a video\"\n          mediaType=\"video\"\n          maxSizeMB={100}\n          progressColor=\"#3498db\"\n          onFileSelected={(file) => console.log('Video:', file.name)}\n        />\n\n        {/* Custom Styled */}\n        <View style={styles.spacing} />\n        <UploadField\n          title=\"Upload Document\"\n          placeholder=\"Choose file\"\n          uploadButtonText=\"Browse\"\n          maxSizeMB={25}\n          progressColor=\"#d9232d\"\n          uploadBoxStyle={styles.customUpload}\n          onFileSelected={(file) => console.log('Doc:', file.name)}\n        />\n\n        {/* Disabled */}\n        <View style={styles.spacing} />\n        <UploadField\n          title=\"Disabled Upload\"\n          disabled\n        />\n\n        {/* Upload Status */}\n        {uploadedFile && (\n          <View style={styles.status}>\n            <Text style={styles.statusText}>\n              Last uploaded: {uploadedFile.name}\n            </Text>\n          </View>\n        )}\n      </ScrollView>\n    </SafeAreaView>\n  );\n};\n\nconst styles = StyleSheet.create({\n  container: {\n    flex: 1,\n    backgroundColor: '#f5f5f5',\n  },\n  content: {\n    padding: 20,\n  },\n  header: {\n    fontSize: 24,\n    fontWeight: 'bold',\n    textAlign: 'center',\n    marginBottom: 24,\n    color: '#333',\n  },\n  spacing: {\n    height: 24,\n  },\n  customUpload: {\n    borderStyle: 'dashed',\n    borderColor: '#d9232d',\n  },\n  status: {\n    marginTop: 24,\n    padding: 12,\n    backgroundColor: '#e8f5e9',\n    borderRadius: 8,\n  },\n  statusText: {\n    color: '#2e7d32',\n    fontSize: 14,\n  },\n});\n\nexport default UploadTestScreen;\n```\n\n---\n\n## 🔧 Real Upload Integration\n\nReplace the simulated upload with your API:\n\n```jsx\nimport UploadField from '@atom_design/upload';\n\nconst MyComponent = () => {\n  const uploadToServer = async (file) => {\n    const formData = new FormData();\n    formData.append('file', {\n      uri: file.uri,\n      type: file.type,\n      name: file.name,\n    });\n\n    const response = await fetch('https://api.example.com/upload', {\n      method: 'POST',\n      body: formData,\n      headers: {\n        'Content-Type': 'multipart/form-data',\n      },\n    });\n\n    return response.json();\n  };\n\n  return (\n    <UploadField\n      onFileSelected={async (file) => {\n        try {\n          const result = await uploadToServer(file);\n          console.log('Upload success:', result);\n        } catch (error) {\n          console.error('Upload failed:', error);\n        }\n      }}\n    />\n  );\n};\n```\n\n---\n\n## 📝 TypeScript\n\nFull TypeScript support included:\n\n```tsx\nimport UploadField, { UploadedFile, UploadFieldProps } from '@atom_design/upload';\n\nconst handleFile = (file: UploadedFile) => {\n  console.log(file.name, file.size);\n};\n\n<UploadField\n  title=\"Upload\"\n  onFileSelected={handleFile}\n/>\n```\n\n---\n\n## ♿ Accessibility\n\nThe component includes full accessibility support:\n\n- Proper `accessibilityRole` on all interactive elements\n- Descriptive labels for screen readers\n- Touch target sizes meet accessibility guidelines\n- Status announcements for upload progress\n\n---\n\n## 👤 Author\n\nAtom Design Team\n\n---\n\n## 📄 License\n\nMIT © [Atom Design](https://github.com/atom-design)\n","readmeFilename":"README.md","_rev":"1-cf4c1cd44428452d774c06830eaa8d18"}