diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml index 92456b97ae430c..20bf23a3c17731 100644 --- a/.github/workflows/cli.yml +++ b/.github/workflows/cli.yml @@ -16,6 +16,7 @@ on: - packages/@expo/prebuild-config/src/** - packages/@expo/router-server/** - packages/@expo/log-box/** + - packages/@expo/metro-file-map/** - packages/create-expo/** - packages/eslint-config-expo/** - packages/eslint-plugin-expo/** @@ -37,6 +38,7 @@ on: - packages/@expo/prebuild-config/src/** - packages/@expo/router-server/** - packages/@expo/log-box/** + - packages/@expo/metro-file-map/** - packages/create-expo/** - packages/eslint-config-expo/** - packages/eslint-plugin-expo/** diff --git a/apps/observe-tester/app/(tabs)/(sessions)/sessions/[id].tsx b/apps/observe-tester/app/(tabs)/(sessions)/sessions/[id].tsx index bb7a7667d25451..916fabbf5c75d4 100644 --- a/apps/observe-tester/app/(tabs)/(sessions)/sessions/[id].tsx +++ b/apps/observe-tester/app/(tabs)/(sessions)/sessions/[id].tsx @@ -22,10 +22,6 @@ export default function SessionDetail() { useFocusEffect( useCallback(() => { - if (Platform.OS !== 'ios') { - setLoaded(true); - return; - } AppMetrics.getAllSessions().then((sessions) => { setSession(sessions.find((s) => s.id === id) ?? null); setLoaded(true); diff --git a/apps/observe-tester/app/(tabs)/(sessions)/sessions/index.tsx b/apps/observe-tester/app/(tabs)/(sessions)/sessions/index.tsx index b78b508e5368c9..42e0c402d91a4a 100644 --- a/apps/observe-tester/app/(tabs)/(sessions)/sessions/index.tsx +++ b/apps/observe-tester/app/(tabs)/(sessions)/sessions/index.tsx @@ -41,11 +41,7 @@ export default function SessionsList() { useFocusEffect( useCallback(() => { - if (Platform.OS === 'ios') { - refresh(); - } else { - setLoaded(true); - } + refresh(); }, [refresh]) ); diff --git a/apps/test-suite/tests/Brightness.ts b/apps/test-suite/tests/Brightness.ts index 4786cd40bc8b0d..e6e24613c07df8 100644 --- a/apps/test-suite/tests/Brightness.ts +++ b/apps/test-suite/tests/Brightness.ts @@ -5,7 +5,22 @@ import * as TestUtils from '../TestUtils'; export const name = 'Brightness (device-only)'; -export const EPSILON = Math.pow(10, -5); +// Android system brightness is stored as an integer in the [1, 255] range +// This means the maximum error after mapping to the [0, 1] range can be half of the interval +const ANDROID_EPSILON = 1 / 254 / 2; +// Arbitrary precision, which compensates for floating-point inaccuracies +const IOS_EPSILON = Math.pow(10, -5); +const EPSILON = Platform.OS === 'android' ? ANDROID_EPSILON : IOS_EPSILON; +// Arbitrary delay to give the system time to set the brightness +const BRIGHTNESS_UPDATE_DELAY_MS = 400; + +function timeoutWrapper(fn: () => void | Promise, time: number): Promise { + return new Promise((resolve, reject) => { + setTimeout(() => { + Promise.resolve(fn()).then(resolve, reject); + }, time); + }); +} export async function test(t) { const shouldSkipTestsRequiringPermissions = @@ -32,9 +47,11 @@ export async function test(t) { } catch { wasRejected = true; } - const obtainedValue = await Brightness.getBrightnessAsync(); - t.expect(Math.abs(originalValue - obtainedValue)).toBeLessThan(EPSILON); - t.expect(wasRejected).toBe(false); + await timeoutWrapper(async () => { + const obtainedValue = await Brightness.getBrightnessAsync(); + t.expect(Math.abs(originalValue - obtainedValue)).toBeLessThan(EPSILON); + t.expect(wasRejected).toBe(false); + }, BRIGHTNESS_UPDATE_DELAY_MS); }); t.it( @@ -47,9 +64,11 @@ export async function test(t) { } catch { wasRejected = true; } - const obtainedValue = await Brightness.getBrightnessAsync(); - t.expect(Math.abs(0 - obtainedValue)).toBeLessThan(EPSILON); - t.expect(wasRejected).toBe(false); + await timeoutWrapper(async () => { + const obtainedValue = await Brightness.getBrightnessAsync(); + t.expect(Math.abs(0 - obtainedValue)).toBeLessThan(EPSILON); + t.expect(wasRejected).toBe(false); + }, BRIGHTNESS_UPDATE_DELAY_MS); } ); @@ -63,9 +82,11 @@ export async function test(t) { } catch { wasRejected = true; } - const obtainedValue = await Brightness.getBrightnessAsync(); - t.expect(Math.abs(1 - obtainedValue)).toBeLessThan(EPSILON); - t.expect(wasRejected).toBe(false); + await timeoutWrapper(async () => { + const obtainedValue = await Brightness.getBrightnessAsync(); + t.expect(Math.abs(1 - obtainedValue)).toBeLessThan(EPSILON); + t.expect(wasRejected).toBe(false); + }, BRIGHTNESS_UPDATE_DELAY_MS); } ); @@ -110,9 +131,11 @@ export async function test(t) { } catch { wasRejected = true; } - const obtainedValue = await Brightness.getSystemBrightnessAsync(); - t.expect(Math.abs(originalValue - obtainedValue)).toBeLessThan(EPSILON); - t.expect(wasRejected).toBe(false); + await timeoutWrapper(async () => { + const obtainedValue = await Brightness.getSystemBrightnessAsync(); + t.expect(Math.abs(originalValue - obtainedValue)).toBeLessThan(EPSILON); + t.expect(wasRejected).toBe(false); + }, BRIGHTNESS_UPDATE_DELAY_MS); }); t.it( @@ -125,9 +148,11 @@ export async function test(t) { } catch { wasRejected = true; } - const obtainedValue = await Brightness.getSystemBrightnessAsync(); - t.expect(Math.abs(0 - obtainedValue)).toBeLessThan(EPSILON); - t.expect(wasRejected).toBe(false); + await timeoutWrapper(async () => { + const obtainedValue = await Brightness.getSystemBrightnessAsync(); + t.expect(Math.abs(0 - obtainedValue)).toBeLessThan(EPSILON); + t.expect(wasRejected).toBe(false); + }, BRIGHTNESS_UPDATE_DELAY_MS); } ); @@ -141,9 +166,11 @@ export async function test(t) { } catch { wasRejected = true; } - const obtainedValue = await Brightness.getSystemBrightnessAsync(); - t.expect(Math.abs(1 - obtainedValue)).toBeLessThan(EPSILON); - t.expect(wasRejected).toBe(false); + await timeoutWrapper(async () => { + const obtainedValue = await Brightness.getSystemBrightnessAsync(); + t.expect(Math.abs(1 - obtainedValue)).toBeLessThan(EPSILON); + t.expect(wasRejected).toBe(false); + }, BRIGHTNESS_UPDATE_DELAY_MS); } ); @@ -183,9 +210,11 @@ export async function test(t) { } catch { wasRejected = true; } - const obtainedValue = await Brightness.getBrightnessAsync(); - t.expect(Math.abs(obtainedValue - systemValue)).toBeLessThan(EPSILON); - t.expect(wasRejected).toBe(false); + await timeoutWrapper(async () => { + const obtainedValue = await Brightness.getBrightnessAsync(); + t.expect(Math.abs(obtainedValue - systemValue)).toBeLessThan(EPSILON); + t.expect(wasRejected).toBe(false); + }, BRIGHTNESS_UPDATE_DELAY_MS); }); t.it(`is overridden by setting the app brightness`, async () => { @@ -199,9 +228,11 @@ export async function test(t) { } catch { wasRejected = true; } - const obtainedValue = await Brightness.getBrightnessAsync(); - t.expect(Math.abs(obtainedValue - appValue)).toBeLessThan(EPSILON); - t.expect(wasRejected).toBe(false); + await timeoutWrapper(async () => { + const obtainedValue = await Brightness.getBrightnessAsync(); + t.expect(Math.abs(obtainedValue - appValue)).toBeLessThan(EPSILON); + t.expect(wasRejected).toBe(false); + }, BRIGHTNESS_UPDATE_DELAY_MS); }); }); diff --git a/docs/.vale/writing-styles/expo-docs/HeadingCase.yml b/docs/.vale/writing-styles/expo-docs/HeadingCase.yml index 8020ecf0736f8e..434cc979b80887 100644 --- a/docs/.vale/writing-styles/expo-docs/HeadingCase.yml +++ b/docs/.vale/writing-styles/expo-docs/HeadingCase.yml @@ -83,6 +83,7 @@ exceptions: - '.*EAS Insights.*' - '.*Element Inspector.*' - '.*Environment Variables.*' + - '.*EXIF.*' - '.*ESLint.*' - '.*Expo.*' - '.*ExpoKit.*' diff --git a/docs/components/plugins/api/APIStaticData.ts b/docs/components/plugins/api/APIStaticData.ts index a6fe25b74f6b8c..3a742331af4385 100644 --- a/docs/components/plugins/api/APIStaticData.ts +++ b/docs/components/plugins/api/APIStaticData.ts @@ -52,9 +52,11 @@ export const nonLinkableTypes = [ 'ExpandedFullScreenSearchBarProps', 'FC', 'FileSystemDirectory', + 'FileSystemDownloadTask', 'FileSystemDownloadResult', 'FileSystemFile', 'FileSystemNetworkTaskProgressCallback', + 'FileSystemUploadTask', 'FileSystemUploadOptions', 'FileSystemUploadResult', 'FileWriteOptions', diff --git a/docs/constants/navigation.js b/docs/constants/navigation.js index 4759a5ee200be4..5622e84b78a439 100644 --- a/docs/constants/navigation.js +++ b/docs/constants/navigation.js @@ -380,6 +380,11 @@ export const general = [ 'More', [ makePage('workflow/upgrading-expo-sdk-walkthrough.mdx'), + makeSection('SDK libraries migration', [ + makePage('guides/sdk-libraries-migration/media-library.mdx'), + makePage('guides/sdk-libraries-migration/calendar.mdx'), + makePage('guides/sdk-libraries-migration/contacts.mdx'), + ]), makeSection('Assorted', [ makePage('guides/authentication.mdx'), makePage('guides/using-hermes.mdx'), diff --git a/docs/pages/guides/sdk-libraries-migration/calendar.mdx b/docs/pages/guides/sdk-libraries-migration/calendar.mdx new file mode 100644 index 00000000000000..93795b79543945 --- /dev/null +++ b/docs/pages/guides/sdk-libraries-migration/calendar.mdx @@ -0,0 +1,372 @@ +--- +title: Migrate to expo-calendar/next +sidebar_title: expo-calendar/next +description: Migrate from the legacy expo-calendar API to the new class-based expo-calendar/next API with ExpoCalendar, ExpoCalendarEvent, and hooks. +--- + +import { BookOpen02Icon } from '@expo/styleguide-icons/outline/BookOpen02Icon'; + +import { BoxLink } from '~/ui/components/BoxLink'; +import { Terminal } from '~/ui/components/Snippet'; + +The `expo-calendar/next` API is now stable. The legacy `expo-calendar` module is deprecated. Migrate to `expo-calendar/next` to benefit from the new API and future fixes. + +The new API replaces free functions that accepted IDs with methods on class instances. Calendars, events, reminders, and attendees are now represented as class instances with their own methods. Key changes: + +- Operations on calendars, events, reminders, and attendees are now methods on the corresponding instance instead of free functions that accept an ID. +- `createCalendar`, `createEvent`, and `createReminder` return class instances instead of string IDs. + +## Installation + +Install the SDK-compatible package that includes `expo-calendar/next`: + + + +## Importing the new API + +Import from `expo-calendar/next`: + +```ts +import { ExpoCalendar, ExpoCalendarEvent } from 'expo-calendar/next'; +``` + +## Calendars + +### Create a calendar + +```ts +// Before +const calendarId = await Calendar.createCalendarAsync({ title: 'My Calendar', color: '#ff0000' }); + +// After +const calendar = await createCalendar({ title: 'My Calendar', color: '#ff0000' }); +``` + +`createCalendar` returns an `ExpoCalendar` instance, not just an ID. + +### List calendars + +```ts +// Before +const calendars = await Calendar.getCalendarsAsync(Calendar.EntityTypes.EVENT); + +// After +const calendars = await getCalendars(EntityTypes.EVENT); +``` + +### Get a calendar by ID + +```ts +// Before +// No direct equivalent, had to filter from getCalendarsAsync + +// After +const calendar = await ExpoCalendar.get(calendarId); +``` + +### Update a calendar + +```ts +// Before +await Calendar.updateCalendarAsync(calendarId, { title: 'Renamed' }); + +// After +await calendar.update({ title: 'Renamed' }); +``` + +### Delete a calendar + +```ts +// Before +await Calendar.deleteCalendarAsync(calendarId); + +// After +await calendar.delete(); +``` + +### Get default calendar (iOS only) + +```ts +// Before +const calendar = await Calendar.getDefaultCalendarAsync(); + +// After +const calendar = getDefaultCalendarSync(); +``` + +### Show a calendar picker (iOS only) + +```ts +// Before +// No equivalent + +// After +const calendar = await presentPicker(); +if (calendar) { + // user selected a calendar +} +``` + +`presentPicker` returns `null` if the app user dismisses the picker without selecting a calendar. + +## Events + +### Create an event + +```ts +// Before +const eventId = await Calendar.createEventAsync(calendarId, { + title: 'Lunch', + startDate, + endDate, +}); + +// After +const event = await calendar.createEvent({ title: 'Lunch', startDate, endDate }); +``` + +`createEvent` returns an `ExpoCalendarEvent` instance, not just an ID. + +### List events in a calendar + +```ts +// Before +const events = await Calendar.getEventsAsync([calendarId], startDate, endDate); + +// After +const events = await calendar.listEvents(startDate, endDate); +``` + +### List events across multiple calendars + +```ts +// Before +const events = await Calendar.getEventsAsync([id1, id2], startDate, endDate); + +// After +const events = await listEvents([calendar1, calendar2], startDate, endDate); +``` + +### Get an event by ID + +```ts +// Before +const event = await Calendar.getEventAsync(eventId); + +// After +const event = await ExpoCalendarEvent.get(eventId); +``` + +### Update an event + +```ts +// Before +await Calendar.updateEventAsync(eventId, { title: 'Lunch with Alex' }); + +// After +await event.update({ title: 'Lunch with Alex' }); +``` + +The legacy `updateEventAsync` accepted `recurringEventOptions` (iOS only) to target a single occurrence or future occurrences of a recurring event. This is not supported in the new API — `update()` always modifies the entire recurring event series. + +### Delete an event + +```ts +// Before +await Calendar.deleteEventAsync(eventId); + +// After +await event.delete(); +``` + +The legacy `deleteEventAsync` accepted `recurringEventOptions` (iOS only) to target a single occurrence or future occurrences of a recurring event. This is not supported in the new API — `delete()` always deletes the entire recurring event series. + +### Open event in calendar + +```ts +// Before +await Calendar.openEventInCalendarAsync(params); + +// After +await event.openInCalendar(params); +``` + +The `id` field is no longer part of params — it comes from the event instance. Presentation options (`allowsEditing`, `allowsCalendarPreview`, `startNewActivityTask`) are now passed in the same params object instead of as a separate argument. + +### Edit event with native form + +```ts +// Before +await Calendar.editEventInCalendarAsync(params); +// or, to create a new event with form +await Calendar.createEventInCalendarAsync({ title, startDate, endDate }); + +// After +await event.editInCalendar(params); +// or, to create a new event with form +await calendar.addEventWithForm({ title, startDate, endDate }); +``` + +The `id` field is no longer part of params — it comes from the event instance. Presentation options (`startNewActivityTask`) are now passed in the same params object instead of as a separate argument. + +### Get recurring event occurrence + +```ts +// Before +const event = await Calendar.getEventAsync(eventId, { instanceStartDate }); + +// After +const event = await ExpoCalendarEvent.get(eventId); +const occurrence = event.getOccurrenceSync({ instanceStartDate }); +``` + +## Attendees + +### Get attendees of an event + +```ts +// Before +const attendees = await Calendar.getAttendeesForEventAsync(eventId); + +// After +const attendees = await event.getAttendees(); +``` + +### Add an attendee + +```ts +// Before +const attendeeId = await Calendar.createAttendeeAsync(eventId, { + email: 'alex@example.com', + name: 'Alex', + role: Calendar.AttendeeRole.ATTENDEE, + type: Calendar.AttendeeType.PERSON, + status: Calendar.AttendeeStatus.ACCEPTED, +}); + +// After +const attendee = await event.createAttendee({ email: 'alex@example.com', name: 'Alex' }); +``` + +### Update an attendee (Android only) + +```ts +// Before +await Calendar.updateAttendeeAsync(attendeeId, { name: 'Alexander' }); + +// After +await attendee.update({ name: 'Alexander' }); +``` + +### Delete an attendee (Android only) + +```ts +// Before +await Calendar.deleteAttendeeAsync(attendeeId); + +// After +await attendee.delete(); +``` + +## Reminders (iOS only) + +### Create a reminder + +```ts +// Before +const reminderId = await Calendar.createReminderAsync(calendarId, { title: 'Buy milk' }); + +// After +const reminder = await calendar.createReminder({ title: 'Buy milk' }); +``` + +`createReminder` returns an `ExpoCalendarReminder` instance, not just an ID. + +### List reminders + +```ts +// Before +const reminders = await Calendar.getRemindersAsync([calendarId], status, startDate, endDate); + +// After +const reminders = await calendar.listReminders(startDate, endDate, status); +``` + +### Get a reminder by ID + +```ts +// Before +const reminder = await Calendar.getReminderAsync(reminderId); + +// After +const reminder = await ExpoCalendarReminder.get(reminderId); +``` + +### Update a reminder + +```ts +// Before +await Calendar.updateReminderAsync(reminderId, { title: 'Buy oat milk' }); + +// After +await reminder.update({ title: 'Buy oat milk' }); +``` + +### Delete a reminder + +```ts +// Before +await Calendar.deleteReminderAsync(reminderId); + +// After +await reminder.delete(); +``` + +## Sources + +```ts +// Before +const sources = await Calendar.getSourcesAsync(); + +// After +const sources = getSourcesSync(); +``` + +`getSourcesAsync` is replaced by the synchronous `getSourcesSync`. Fetching a single source by ID has no direct equivalent in the new API. + +## Permissions + +```ts +// Before +await Calendar.requestCalendarPermissionsAsync(); +await Calendar.getCalendarPermissionsAsync(); +await Calendar.requestRemindersPermissionsAsync(); +await Calendar.getRemindersPermissionsAsync(); + +// After +await requestCalendarPermissions(); +await getCalendarPermissions(); +await requestRemindersPermissions(); +await getRemindersPermissions(); +``` + +`useCalendarPermissions` and `useRemindersPermissions` hooks are unchanged. + +## Breaking semantic changes + +- Calendars, events, reminders, and attendees are now class instances. Operations are methods on the instance instead of free functions that accept an ID. Use the corresponding `.get(id)` static method to obtain an instance if you only have an ID. +- `createCalendar`, `createEvent`, and `createReminder` return class instances instead of string IDs. +- The `Async` suffix is dropped. The majority of the library is asynchronous — only synchronous functions use a `Sync` suffix (for example, `getDefaultCalendarSync`, `getSourcesSync`, `getOccurrenceSync`). +- `getSourcesAsync` is replaced by the synchronous `getSourcesSync`. Fetching a single source by ID has no direct equivalent. +- `createEventInCalendarAsync` is renamed to `calendar.addEventWithForm`. +- `openEventInCalendar` (the fire-and-forget sync variant) is removed. Use `event.openInCalendar()` instead. +- Attendee operations are now instance methods: creating an attendee is done via `event.createAttendee()` on an `ExpoCalendarEvent` instance; updating and deleting are methods on the resulting `ExpoCalendarAttendee` instance. + +## Reference + + diff --git a/docs/pages/guides/sdk-libraries-migration/contacts.mdx b/docs/pages/guides/sdk-libraries-migration/contacts.mdx new file mode 100644 index 00000000000000..3b0027ab97d029 --- /dev/null +++ b/docs/pages/guides/sdk-libraries-migration/contacts.mdx @@ -0,0 +1,316 @@ +--- +title: Migrate to expo-contacts/next +sidebar_title: expo-contacts/next +description: Migrate from the legacy expo-contacts API to the new class-based expo-contacts/next API. +--- + +import { BookOpen02Icon } from '@expo/styleguide-icons/outline/BookOpen02Icon'; + +import { BoxLink } from '~/ui/components/BoxLink'; +import { Terminal } from '~/ui/components/Snippet'; + +The `expo-contacts/next` API is now stable. The legacy `expo-contacts` module is deprecated. Migrate to `expo-contacts/next` to benefit from the new API and future fixes. + +The new API replaces the function-based API with a `Contact` class. Contacts are represented as class instances that hold only the ID of the native contact. Key changes: + +- Contact properties (name, company, birthday, and more) are async getters and setters instead of plain object properties. +- Sub-records (phones, emails, addresses, ...) are managed via dedicated `add*`/`get*`/`update*`/`delete*` methods instead of re-writing the entire array. +- Two update methods are now available: `patch` for partial updates and `update` for full replacement. + +## Installation + +Install the SDK-compatible package that includes `expo-contacts/next`: + + + +## Importing the new API + +Import from `expo-contacts/next`: + +```ts +import { Contact } from 'expo-contacts/next'; +``` + +## Contacts + +### Create a contact + +```ts +// Before +const id = await Contacts.addContactAsync({ firstName: 'John', lastName: 'Doe' }); + +// After +const contact = await Contact.create({ givenName: 'John', familyName: 'Doe' }); +``` + +`Contact.create` returns a `Contact` instance, not just an ID. + +### Get all contacts + +```ts +// Before +const { data } = await Contacts.getContactsAsync({ + fields: [Contacts.Fields.Name, Contacts.Fields.PhoneNumbers], + pageSize: 20, + pageOffset: 10, + sort: Contacts.SortTypes.FirstName, +}); + +// After, instance objects +const contacts = await Contact.getAll({ + limit: 20, + offset: 10, + sortOrder: ContactsSortOrder.GivenName, +}); + +// After, typed field projection +const contacts = await Contact.getAllDetails([ContactField.FULL_NAME, ContactField.PHONES], { + limit: 20, + offset: 10, +}); +``` + +`getAllDetails` returns a strongly typed projection narrowed to the requested fields. + +### Get a contact by ID + +Results from `getAllDetails` include the contact ID. If you want to call methods on a contact returned from `getAllDetails`, wrap it in a `Contact` instance using the constructor: + +```ts +const results = await Contact.getAllDetails([ContactField.FULL_NAME, ContactField.PHONES]); +const contact = new Contact(results[0].id); +await contact.addPhone({ label: 'work', number: '+12345678912' }); +``` + +### Count contacts + +```ts +// Before +const hasAny = await Contacts.hasContactsAsync(); + +// After +const hasAny = await Contact.hasAny(); + +// After, no direct equivalent before +const count = await Contact.getCount(); +``` + +### Update a contact + +```ts +// Before, re-write the whole contact +await Contacts.updateContactAsync({ ...contact, firstName: 'Andrew' }); + +// After, partial update (only changes provided fields) +await contact.patch({ givenName: 'Andrew' }); + +// After, full replacement - all fields not provided will be cleared +await contact.update({ + givenName: 'John', + familyName: 'Doe', + phones: [{ label: 'mobile', number: '+12123456789' }], +}); +``` + +### Delete a contact + +```ts +// Before +await Contacts.removeContactAsync(id); + +// After +await contact.delete(); +``` + +## Scalar fields + +All scalar contact properties are now async getters and setters. Use `get*` to read and `set*` to write. You can also retrieve multiple fields at once using `contact.getDetails()`. + +| Field | Getter | Setter | +| ------------------------ | ----------------------- | ----------------------- | +| Given name | `getGivenName` | `setGivenName` | +| Family name | `getFamilyName` | `setFamilyName` | +| Middle name | `getMiddleName` | `setMiddleName` | +| Full name | `getFullName` | — | +| Nickname (iOS only) | `getNickname` | `setNickname` | +| Prefix | `getPrefix` | `setPrefix` | +| Suffix | `getSuffix` | `setSuffix` | +| Phonetic given name | `getPhoneticGivenName` | `setPhoneticGivenName` | +| Phonetic family name | `getPhoneticFamilyName` | `setPhoneticFamilyName` | +| Company | `getCompany` | `setCompany` | +| Job title | `getJobTitle` | `setJobTitle` | +| Department | `getDepartment` | `setDepartment` | +| Birthday (iOS only) | `getBirthday` | `setBirthday` | +| Note | `getNote` | `setNote` | +| Image | `getImage` | `setImage` | +| Thumbnail | `getThumbnail` | — | +| Favourite (Android only) | `getIsFavourite` | `setIsFavourite` | + +### Name + +```ts +// Before, contact fetched via getContactByIdAsync +const contact = await Contacts.getContactByIdAsync(id); +console.log(contact.firstName, contact.lastName); + +// After, individual async getters +const givenName = await contact.getGivenName(); +const familyName = await contact.getFamilyName(); + +// After, full name object via getDetails() +const details = await contact.getDetails([ContactField.FULL_NAME]); + +await contact.setGivenName('John'); +await contact.setFamilyName('Doe'); +await contact.setMiddleName('Michael'); +``` + +## Sub-records + +Sub-records are no longer managed by re-writing the entire array with `updateContactAsync`. Each type has dedicated `add*`, `get*`, `update*`, and `delete*` methods: + +| Sub-record | Methods | +| -------------------------- | ------------------------------------------------------------------------------------- | +| Phone numbers | `addPhone`, `getPhones`, `updatePhone`, `deletePhone` | +| Emails | `addEmail`, `getEmails`, `updateEmail`, `deleteEmail` | +| Addresses | `addAddress`, `getAddresses`, `updateAddress`, `deleteAddress` | +| URLs | `addUrlAddress`, `getUrlAddresses`, `updateUrlAddress`, `deleteUrlAddress` | +| Social profiles | `addSocialProfile`, `getSocialProfiles`, `updateSocialProfile`, `deleteSocialProfile` | +| IM addresses | `addImAddress`, `getImAddresses`, `updateImAddress`, `deleteImAddress` | +| Dates | `addDate`, `getDates`, `updateDate`, `deleteDate` | +| Extra names (Android only) | `addExtraName`, `getExtraNames`, `updateExtraName`, `deleteExtraName` | + +The following examples use phone numbers. + +```ts +// Before, re-write the whole array +await Contacts.updateContactAsync({ + ...contact, + phoneNumbers: [...existing, { label: 'work', number: '+12345678912' }], +}); + +// After, add +await contact.addPhone({ label: 'work', number: '+12345678912' }); + +// After, get +const phones = await contact.getPhones(); + +// After, update +await contact.updatePhone(existingPhone); + +// After, delete +await contact.deletePhone(existingPhone); +``` + +## Native UI + +```ts +// Before +const contact = await Contacts.presentContactPickerAsync(); +await Contacts.presentFormAsync(null, contactData, { isNew: true }); +await Contacts.presentFormAsync(contactId); + +// After +const contact = await Contact.presentPicker(); +if (contact) { + // user selected a contact +} +const created = await Contact.presentCreateForm(contactData); +await contact.editWithForm(); +``` + +### Access picker (iOS 18+ only) + +```ts +// Before +const contactIds = await Contacts.presentAccessPickerAsync(); + +// After +const selectedContacts = await Contact.presentAccessPicker(); +``` + +## Groups (iOS only) + +```ts +// Before +const groups = await Contacts.getGroupsAsync({}); +await Contacts.createGroupAsync('Family'); +await Contacts.addExistingContactToGroupAsync(contactId, groupId); +await Contacts.removeContactFromGroupAsync(contactId, groupId); + +// After +const groups = await Group.getAll(); +const group = await Group.create('Family'); +await group.addContact(contact); +await group.removeContact(contact); +const contacts = await group.getContacts(); +const name = await group.getName(); +await group.setName('Close Friends'); +await group.delete(); +``` + +## Containers (iOS only) + +```ts +// Before +const containers = await Contacts.getContainersAsync({}); +const defaultId = await Contacts.getDefaultContainerIdAsync(); + +// After +const containers = await Container.getAll(); +const defaultContainer = await Container.getDefault(); // may be null +const name = await container.getName(); +const type = await container.getType(); +const groups = await container.getGroups(); +const contacts = await container.getContacts(); +``` + +## Permissions + +```ts +// Before +const { status } = await Contacts.requestPermissionsAsync(); +const { status } = await Contacts.getPermissionsAsync(); + +// After +const { status } = await requestPermissionsAsync(); +const { status } = await getPermissionsAsync(); +``` + +## Listening for changes + +```ts +// Before +const subscription = Contacts.addContactsChangeListener(() => { + // contacts changed +}); +subscription.remove(); + +// After +const subscription = addContactsChangeListener(() => { + // contacts changed +}); +subscription.remove(); + +// Remove all listeners at once +removeAllContactsChangeListeners(); +``` + +## Breaking semantic changes + +- Field names follow the platform convention. For example, `firstName`/`lastName` become `givenName`/`familyName`. +- Field selection uses the typed `ContactField` enum. The result type of `getAllDetails` is narrowed to the requested fields. +- The `Async` suffix is dropped. The entire library is asynchronous. +- Contact properties are now async getters and setters instead of plain properties on the contact object. Use `contact.getDetails()` to retrieve multiple fields at once. +- Sub-records (phones, emails, addresses, ...) are managed via dedicated `add*`/`get*`/`update*`/`delete*` methods instead of re-writing the entire array with `updateContactAsync`. +- Two update methods replace `updateContactAsync`: `patch` applies partial changes, `update` replaces the entire contact. +- `shareContactAsync` and `writeContactToFileAsync` are removed with no replacement. You can safely delete any calls to these functions. + +## Reference + + diff --git a/docs/pages/guides/sdk-libraries-migration/media-library.mdx b/docs/pages/guides/sdk-libraries-migration/media-library.mdx new file mode 100644 index 00000000000000..76c4fe2b8f8f58 --- /dev/null +++ b/docs/pages/guides/sdk-libraries-migration/media-library.mdx @@ -0,0 +1,245 @@ +--- +title: Migrate to expo-media-library/next +sidebar_title: expo-media-library/next +description: Migrate from the legacy expo-media-library API to the new class-based expo-media-library/next API with Asset, Album, and Query. +--- + +import { BookOpen02Icon } from '@expo/styleguide-icons/outline/BookOpen02Icon'; + +import { BoxLink } from '~/ui/components/BoxLink'; +import { Terminal } from '~/ui/components/Snippet'; + +The `expo-media-library/next` API is now stable. The legacy `expo-media-library` module is deprecated. Migrate to `expo-media-library/next` to benefit from the new API and future fixes. + +The new API replaces the function-based `MediaLibrary.getAssetsAsync({ ... })` style with `Asset`, `Album`, and `Query` classes. Albums and assets are now represented as class instances that hold only the ID of the native asset. Asset properties are async getters instead of pre-fetched fields. `Query` replaces the `getAssetsAsync` function with a chainable builder pattern. + +## Installation + +Install the SDK-compatible package that includes `expo-media-library/next`: + + + +## Importing the new API + +Import from `expo-media-library/next`: + +```ts +import { Asset, Album, Query } from 'expo-media-library/next'; +``` + +## Assets + +### Create an asset from a file + +```ts +// Before +await MediaLibrary.saveToLibraryAsync(localUri); +// or, to get a reference back: +const asset = await MediaLibrary.createAssetAsync(localUri); + +// After +const asset = await Asset.create(localUri); +``` + +`saveToLibraryAsync` is not available in the new API. Use `Asset.create`, which saves the file to the library and returns an `Asset` instance. + +### Query assets + +```ts +// Before +const { assets } = await MediaLibrary.getAssetsAsync({ + mediaType: MediaLibrary.MediaType.photo, + first: 20, + sortBy: [['creationTime', false]], +}); + +// After +const assets = await new Query() + .eq(AssetField.MEDIA_TYPE, MediaType.IMAGE) + .limit(20) + .orderBy({ key: AssetField.CREATION_TIME, ascending: false }) + .exe(); +``` + +`Query` returns an array of `Asset` instances directly. There is no `assets` wrapper or `endCursor`. Pagination is handled by chaining `.limit()` and `.offset()`. + +### Read asset properties + +```ts +// Before +const info = await MediaLibrary.getAssetInfoAsync(asset); +console.log(info.filename, info.width, info.height); + +// After, individual getters +const filename = await asset.getFilename(); +const width = await asset.getWidth(); +const height = await asset.getHeight(); +const mediaType = await asset.getMediaType(); + +// After, all properties at once +const info = await asset.getInfo(); +``` + +Properties are accessed through async getters instead of pre-fetched fields. Use `getInfo()` to retrieve all properties at once as an `AssetInfo` object. + +### Read EXIF data + +```ts +// Before +const info = await MediaLibrary.getAssetInfoAsync(asset); +const exif = info.exif; + +// After +const exif = await asset.getExif(); +``` + +### Delete assets + +```ts +// Before +await MediaLibrary.deleteAssetsAsync([asset]); + +// After, single asset +await asset.delete(); + +// After, multiple assets +await Asset.delete([asset1, asset2]); +``` + +## Albums + +### Get an album by name + +```ts +// Before +const album = await MediaLibrary.getAlbumAsync('MyAlbum'); + +// After +const album = await Album.get('MyAlbum'); +if (album) { + // album found +} +``` + +### Get all albums + +```ts +// Before +const albums = await MediaLibrary.getAlbumsAsync(); + +// After +const albums = await Album.getAll(); +``` + +### Create an album + +```ts +// Before +const album = await MediaLibrary.createAlbumAsync('MyNewAlbum', asset, false); + +// After +const album = await Album.create('MyNewAlbum', [asset]); +``` + +### Get all assets in an album + +```ts +// Before +const { assets } = await MediaLibrary.getAssetsAsync({ album: album.id }); + +// After +const assets = await album.getAssets(); +``` + +### Get album title + +```ts +// Before, title was a synchronous property but required fetching the full album object first +const album = await MediaLibrary.getAlbumAsync('MyAlbum'); +console.log(album.title); + +// After +const title = await album.getTitle(); +``` + +### Add assets to an album + +```ts +// Before +await MediaLibrary.addAssetsToAlbumAsync([asset], album, false); + +// After +await album.add([asset]); +``` + +### Remove assets from an album (iOS only) + +```ts +// Before +await MediaLibrary.removeAssetsFromAlbumAsync(assets, album); + +// After +await album.removeAssets(assets); +``` + +### Delete an album + +```ts +// Before +await MediaLibrary.deleteAlbumsAsync([album], false); + +// After, single album +await album.delete(); + +// After, multiple albums +await Album.delete([album1, album2]); +``` + +## Permissions + +The permission hooks and functions are available under the same names. The only change is that `presentPermissionsPickerAsync` was renamed to `presentPermissionsPicker`. + +```ts +// Before +await MediaLibrary.presentPermissionsPickerAsync(mediaTypes); + +// After +await presentPermissionsPicker(mediaTypes); +``` + +`requestPermissionsAsync`, `getPermissionsAsync`, and `usePermissions` are unchanged. + +## Listening for changes + +```ts +// Before +const subscription = MediaLibrary.addListener(event => { ... }); +subscription.remove(); + +// After +const subscription = addListener(event => { ... }); +subscription.remove(); + +// Remove all listeners at once +removeAllListeners(); +``` + +The listener event shape is unchanged. + +## Breaking semantic changes + +- Asset properties are now async getters (`getFilename()`, `getWidth()`, ...) instead of synchronous fields on a result object. Use `asset.getInfo()` to retrieve all properties at once. +- The `Async` suffix is dropped. The entire library is asynchronous. +- `Query` replaces the `getAssetsAsync` options bag. There is no `endCursor`/`hasNextPage`. Use `.limit()` and `.offset()` for pagination. +- Operations on albums and assets are now methods on `Album` and `Asset` instances instead of free functions that accept an ID or reference. +- `saveToLibraryAsync` is replaced by `Asset.create`, which returns an `Asset` instance. +- `getMomentsAsync`, `albumNeedsMigrationAsync`, and `migrateAlbumIfNeededAsync` are removed with no replacement. You can safely delete any calls to these functions. + +## Reference + + diff --git a/docs/pages/guides/using-clerk.mdx b/docs/pages/guides/using-clerk.mdx index 0ac50a79222733..c6a2bd8f70692c 100644 --- a/docs/pages/guides/using-clerk.mdx +++ b/docs/pages/guides/using-clerk.mdx @@ -1,31 +1,450 @@ --- title: Using Clerk -description: Learn how to integrate Clerk authentication in your Expo and React Native projects. +description: Learn how to add Clerk authentication and user management in your Expo and React Native projects. +platforms: ['android', 'ios', 'web'] --- +import { BoxLink } from '~/ui/components/BoxLink'; +import { YesIcon, NoIcon } from '~/ui/components/DocIcons'; +import { Prerequisites, Requirement } from '~/ui/components/Prerequisites'; +import { Terminal } from '~/ui/components/Snippet'; +import { Step } from '~/ui/components/Step'; +import { Tabs, Tab } from '~/ui/components/Tabs'; import { BookOpen02Icon } from '@expo/styleguide-icons/outline/BookOpen02Icon'; -import { BoxLink } from '~/ui/components/BoxLink'; +[Clerk](https://clerk.com/expo-authentication) is an authentication and user management platform that provides sign-up, sign-in, multi-factor authentication, social sign-in, organizations, and a hosted user database. The [`@clerk/expo`](https://www.npmjs.com/package/@clerk/expo) SDK gives you React hooks, control components, and prebuilt native UI components that render with Jetpack Compose on Android and SwiftUI on iOS. + +This guide shows you how to install `@clerk/expo`, wrap your app in ``, and choose the integration approach that fits your project. It targets `@clerk/expo` Core 3 (the 3.x release line), which supports Expo SDK 53, 54, and 55. + +## Choose your integration approach + +`@clerk/expo` supports three approaches. Pick the one that matches your needs — you can change later without rewriting your app. + +| Approach | What you build | Runs in Expo Go | Best for | +| ------------------------------ | --------------------------------------------------------------------------------------------- | --------------- | ---------------------------------------------------------------- | +| JavaScript only | Your own React Native screens that call `useSignIn()` and `useSignUp()` | | Maximum UI control, prototyping in Expo Go | +| JavaScript with native sign-in | Your own screens plus native Sign in with Google and Sign in with Apple buttons | | Apps that want a custom look but native social sign-in | +| Native UI components | Drop in ``, ``, and `` from `@clerk/expo/native` | | The fastest path to a complete sign-in and account management UI | + +> **info** The native UI components in `@clerk/expo/native` are currently in beta. They render with Jetpack Compose on Android and SwiftUI on iOS and they synchronize the signed-in session back to the JavaScript SDK so all `@clerk/expo` hooks (such as `useAuth()` and `useUser()`) stay in sync. + +## Prerequisites + + + + Sign up at the [Clerk Dashboard](https://dashboard.clerk.com/) and create an application. + + + Open the [Native applications](https://dashboard.clerk.com/last-active?path=native-applications) page in the Clerk Dashboard and ensure **Native API** is on. This is required for any Expo integration that uses `@clerk/expo`. + + + `@clerk/expo` Core 3 has a peer dependency of `expo: >=53 <56`. + + + The native sign-in and native UI component approaches require a development build. The JavaScript-only approach also works in Expo Go. + + + +## Install and configure Clerk + + + +### Install `@clerk/expo` and `expo-secure-store` + +Use `npx expo install` so versions match your Expo SDK: + + + +`expo-secure-store` is a peer dependency. Clerk uses it through `@clerk/expo/token-cache` to encrypt session tokens with the iOS Keychain and the Android Keystore. + +If you plan to use native Sign in with Google, also install `expo-crypto`: + + + +For native Sign in with Apple, install both `expo-apple-authentication` and `expo-crypto`: + + + +You do not need any of these extra packages if you only use `` from `@clerk/expo/native`, since the component handles social sign-in flows internally. + + + + + +### Add the Clerk config plugin + +Add `@clerk/expo` to the `plugins` array in your [app config](/workflow/configuration/): + +```json app.json +{ + "expo": { + "plugins": ["@clerk/expo"] + } +} +``` + +The plugin configures the iOS URL scheme for native Sign in with Google (when `EXPO_PUBLIC_CLERK_GOOGLE_IOS_URL_SCHEME` is set) and applies the Android packaging fixes required by the underlying `clerk-android` SDK. The Apple Sign In entitlement is added by the plugin from `expo-apple-authentication` library, if you install it. + + + + + +{/* vale off */} + +### Add your Clerk Publishable Key + +{/* vale on */} -[Clerk](https://clerk.com/) is a full stack authentication and user management platform that helps you add sign-up, sign-in, and account management without building your own auth backend. It supports multiple authentication strategies, session management, and organizations for multi-tenant apps. +Copy your Publishable Key from the [API keys](https://dashboard.clerk.com/last-active?path=api-keys) page in the Clerk Dashboard, then add it to a **.env** file in the root of your project: -Clerk provides hooks, UI, and control components so you can build completely custom authentication screens. Pair it with `expo-secure-store` to keep session tokens encrypted on device, and configure your projects's providers and policies in the Clerk's dashboard. +```text .env +EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_your-key-here +``` -> **Note:** Clerk's [prebuilt UI components](https://clerk.com/docs/expo/reference/components/overview) are available for web only. For native platforms, Clerk recommends building custom flows. +The `EXPO_PUBLIC_` prefix is required because [Expo inlines these values at build time](/guides/environment-variables/#reading-environment-variables-from-env-files) so they are available in your JavaScript bundle. Clerk's Publishable Key is safe to expose. **Do not** put Secret Keys behind the `EXPO_PUBLIC_` prefix. + + + + + +### Wrap your app in `` + +In your root layout file (**src/app/\_layout.tsx** with Expo Router), wrap your app in `` and pass the Publishable Key. Passing `tokenCache` explicitly is recommended: + +```tsx src/app/_layout.tsx +import { ClerkProvider } from '@clerk/expo'; +import { tokenCache } from '@clerk/expo/token-cache'; +import { Slot } from 'expo-router'; + +const publishableKey = process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY!; + +if (!publishableKey) { + throw new Error('Add your Clerk Publishable Key to the .env file'); +} + +export default function RootLayout() { + return ( + + + + ); +} +``` + +In Core 3, `publishableKey` is required on `` for Expo apps. Environment variables inside **node_modules** are not inlined during production React Native builds, so the prop must be passed explicitly. + +`tokenCache` from `@clerk/expo/token-cache` persists the user's session across app restarts using `expo-secure-store`. Passing it explicitly makes the dependency clear and lets you swap in a custom cache implementation later. + + + +## Build your sign-in screen + +The next step depends on which approach you chose. The tabs below show the minimum code for each. + + + + + +Drop `` into a screen. It renders a complete native sign-in and sign-up interface that handles email, phone, passkeys, multi-factor authentication, and any social connection enabled in the Clerk Dashboard: + +```tsx +import { AuthView } from '@clerk/expo/native'; +import { useAuth } from '@clerk/expo'; +import { useRouter } from 'expo-router'; +import { useEffect } from 'react'; + +export default function SignInScreen() { + const { isSignedIn } = useAuth({ treatPendingAsSignedOut: false }); + const router = useRouter(); + + useEffect(() => { + if (isSignedIn) { + router.replace('/(home)'); + } + }, [isSignedIn]); + + return ; +} +``` + +After the user signs in, the native session is synchronized back to the JavaScript SDK, so `useAuth()` and `useUser()` reflect the signed-in state. Pass `treatPendingAsSignedOut: false` to `useAuth()` so the brief native-to-JS session sync isn't reported as a signed-out state, which can otherwise cause redirect loops on screens that key navigation off `isSignedIn`. + +`` accepts `mode="signIn" | "signUp" | "signInOrUp"` and an optional `isDismissable` boolean. + +To show the user's avatar and a profile modal elsewhere in your app, use ``: + +```tsx +import { UserButton } from '@clerk/expo/native'; +import { Show } from '@clerk/expo'; +import { View } from 'react-native'; + +export function Header() { + return ( + + + + + + ); +} +``` + +`` fills its parent, so the parent controls size and shape. To open the native profile modal from any other UI, use the `useUserProfileModal()` hook: + +```tsx +import { useUserProfileModal } from '@clerk/expo'; +import { Pressable, Text } from 'react-native'; + +export function ProfileLink() { + const { presentUserProfile, isAvailable } = useUserProfileModal(); + return ( + + Manage profile + + ); +} +``` + +This approach requires a development build because the components are backed by native modules: + + -## Features + -- **Authentication flows:** Sign-up and sign-in with email verification code, magic links, passwords, social providers (20+), passkeys, phone number verification, SAML, OpenID Connect, Web3 (MetaMask), and authenticator apps for multi-factor authentication. -- **Session management:** Secure token handling with [`expo-secure-store`](/versions/latest/sdk/securestore/). -- **User management:** Profile data, account settings, and organization membership for multi-tenant apps. + -## Get started +Use the `useSignInWithGoogle()` and `useSignInWithApple()` hooks alongside your own React Native UI: -To get started, follow the instructions in the Clerk's documentation: +```tsx +import { useSignInWithGoogle } from '@clerk/expo/google'; +import { useRouter } from 'expo-router'; +import { Platform, Text, TouchableOpacity } from 'react-native'; + +export function GoogleSignInButton() { + const { startGoogleAuthenticationFlow } = useSignInWithGoogle(); + const router = useRouter(); + + if (Platform.OS !== 'ios' && Platform.OS !== 'android') return null; + + const onPress = async () => { + try { + const { createdSessionId, setActive } = await startGoogleAuthenticationFlow(); + if (createdSessionId && setActive) { + await setActive({ session: createdSessionId }); + router.replace('/'); + } + } catch (err) { + console.error('Google sign-in error', err); + } + }; + + return ( + + Continue with Google + + ); +} +``` + +On Android, this uses Credential Manager and never opens a browser. On iOS, the flow uses `ASAuthorization` (the system credential picker) when `EXPO_PUBLIC_CLERK_GOOGLE_IOS_URL_SCHEME` is configured — without it, iOS falls back to a system browser sheet. Follow the Clerk guides linked at the bottom of this page to register your Android package name, iOS bundle ID, and SHA-256 fingerprints in the Clerk Dashboard and the Google Cloud Console. + +`useSignInWithApple()` from `@clerk/expo/apple` follows the same pattern (`startAppleAuthenticationFlow()` returning `{ createdSessionId, setActive }`) and is iOS only. App Store Guideline 4.8 requires that any app offering third-party social sign-in must also offer Sign in with Apple on iOS. + +This approach requires a development build because it uses native modules. `useSignInWithGoogle()` requires `expo-crypto`. The `useSignInWithApple()` requires both `expo-apple-authentication` and `expo-crypto`. + + + + + +Build a custom sign-in form using the Core 3 hooks. This works in Expo Go. + +```tsx +import { useSignIn } from '@clerk/expo'; +import { useRouter, type Href } from 'expo-router'; +import { useState } from 'react'; +import { Text, TextInput, TouchableOpacity, View } from 'react-native'; + +export default function SignInScreen() { + const { signIn, fetchStatus, errors } = useSignIn(); + const router = useRouter(); + const [emailAddress, setEmailAddress] = useState(''); + const [password, setPassword] = useState(''); + + const onSignInPress = async () => { + const { error } = await signIn.password({ emailAddress, password }); + if (error) { + console.error(JSON.stringify(error, null, 2)); + return; + } + + if (signIn.status === 'complete') { + await signIn.finalize({ + navigate: ({ session, decorateUrl }) => { + if (session?.currentTask) return; // let the session task layer handle it + router.replace(decorateUrl('/') as Href); + }, + }); + } + }; + + return ( + + + + + Sign in + + {errors?.fields?.identifier ? {errors.fields.identifier.message} : null} + {errors?.fields?.password ? {errors.fields.password.message} : null} + + ); +} +``` + +In Core 3, `signIn.password()` returns `{ error }` instead of throwing for validation errors, and `signIn.finalize()` replaces the legacy `setActive()` call for sign-in flows built with `useSignIn()`. + +The corresponding sign-up flow with email verification looks like: + +```tsx +await signUp.password({ emailAddress, password }); +await signUp.verifications.sendEmailCode(); +// ... collect the code from the user, then: +await signUp.verifications.verifyEmailCode({ code }); +if (signUp.status === 'complete') { + await signUp.finalize({ + navigate: ({ session, decorateUrl }) => { + if (session?.currentTask) return; + router.replace(decorateUrl('/') as Href); + }, + }); +} +``` + +Clerk's bot sign-up protection is enabled by default, so include `` somewhere in your sign-up screen so the invisible CAPTCHA can mount. + + + + + +## Read the signed-in user + +Anywhere in your app, use `useUser()` and `useAuth()` to read user data, plus `` and `useClerk()` to protect content and sign out: + +```tsx +import { Show, useClerk, useUser } from '@clerk/expo'; +import { Link } from 'expo-router'; +import { Pressable, Text, View } from 'react-native'; + +export default function HomeScreen() { + const { user } = useUser(); + const { signOut } = useClerk(); + + return ( + + + Hello, {user?.firstName ?? 'friend'} + signOut()}> + Sign out + + + + + Sign in + + + + ); +} +``` + +`` replaces the legacy ``, ``, and `` components from earlier versions of the SDK. It also accepts `when={{ role: '...' }}`, `when={{ permission: '...' }}`, and other authorization predicates. + +## Run the app + + + + + + + + + + + + + + + + + +For the JavaScript-only approach, run the following command and open the project in Expo Go: + + + + + + + +## Next steps + + + + + + + + + + diff --git a/docs/pages/router/installation.mdx b/docs/pages/router/installation.mdx index cf6fbe7189b867..de8b53e9be5f33 100644 --- a/docs/pages/router/installation.mdx +++ b/docs/pages/router/installation.mdx @@ -90,9 +90,11 @@ Add a deep linking `scheme` and enable [typed routes](/router/reference/typed-ro ```json app.json { - "scheme": "your-app-scheme", - "experiments": { - "typedRoutes": true + "expo": { + "scheme": "your-app-scheme", + "experiments": { + "typedRoutes": true + } } } ``` @@ -105,8 +107,10 @@ Then, enable [Metro web](/guides/customizing-metro/#adding-web-support-to-metro) ```json app.json { - "web": { - "bundler": "metro" + "expo": { + "web": { + "bundler": "metro" + } } } ``` diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/alertdialog.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/alertdialog.mdx index 7f40dae14339de..d776210e1c6503 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/alertdialog.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/alertdialog.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI AlertDialog matches the official Jetpack Compose [AlertDialog](https://developer.android.com/develop/ui/compose/components/dialog) API. Content is provided via slot sub-components (`AlertDialog.Title`, `AlertDialog.Text`, `AlertDialog.ConfirmButton`, `AlertDialog.DismissButton`, `AlertDialog.Icon`) that map directly to Compose's slot parameters. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/badge.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/badge.mdx index 7d3fb872d9e5f6..fd79469a0ac5f7 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/badge.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/badge.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Badge matches the official Jetpack Compose [`Badge`](https://developer.android.com/develop/ui/compose/components/badges) API. It renders as a small colored indicator dot, or with content such as a count number. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/badgedbox.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/badgedbox.mdx index f5a03a65166312..f622bfb12e226e 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/badgedbox.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/badgedbox.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI BadgedBox matches the official Jetpack Compose [`BadgedBox`](https://developer.android.com/develop/ui/compose/components/badges) API. It overlays a badge on top of content such as an icon. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/basicalertdialog.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/basicalertdialog.mdx index c73dfd60c614e5..ff1d46da381ed6 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/basicalertdialog.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/basicalertdialog.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI BasicAlertDialog matches the official Jetpack Compose [BasicAlertDialog](https://developer.android.com/develop/ui/compose/components/dialog) API and displays a minimal dialog that accepts custom children as its content, giving you full control over the dialog layout. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/bottomsheet.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/bottomsheet.mdx index 1edee8b19d1ced..d7c99f641a83c8 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/bottomsheet.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/bottomsheet.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI ModalBottomSheet matches the official Jetpack Compose [Bottom Sheet API](https://developer.android.com/develop/ui/compose/components/bottom-sheets) and displays content in a modal sheet that slides up from the bottom. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/box.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/box.mdx index 7ec12a192901b8..162b01c842c860 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/box.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/box.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Box matches the official Jetpack Compose [Box](https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#Box) API and stacks children on top of each other with configurable content alignment. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/button.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/button.mdx index 86c87ee06faddb..012076a5fc9919 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/button.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/button.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI provides five button components that match the official Jetpack Compose [Button API](https://developer.android.com/develop/ui/compose/components/button): `Button` (filled), `FilledTonalButton`, `OutlinedButton`, `ElevatedButton`, and `TextButton`. All variants share the same props and accept composable children for content. + + | Type | Appearance | Purpose | | ------------ | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Filled | Solid background with contrasting text. | High-emphasis buttons for primary actions such as "submit" and "save." | diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/card.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/card.mdx index c1012ad05dfd7e..a61a0ca18d1714 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/card.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/card.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Card matches the official Jetpack Compose [Card API](https://developer.android.com/develop/ui/compose/components/card) and displays content inside a styled surface container with optional elevation and outline. The `Card` component renders a [filled card](https://developer.android.com/develop/ui/compose/components/card#filled), while `ElevatedCard` and `OutlinedCard` provide raised and bordered variants respectively. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/carousel.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/carousel.mdx index 381323d35a98c4..aaea4ce1246aef 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/carousel.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/carousel.mdx @@ -8,11 +8,19 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI provides three carousel components matching the official Jetpack Compose [Carousel](https://developer.android.com/develop/ui/compose/components/carousel) API: `HorizontalCenteredHeroCarousel`, `HorizontalMultiBrowseCarousel`, and `HorizontalUncontainedCarousel`. > **Note:** Carousel is a horizontally scrollable component, so the parent `Host` must provide a finite width on the scroll axis. Use `matchContents={{ vertical: true }}` together with `style={{ width: '100%' }}` (or any finite width). See [Match contents in Host reference](host/#match-contents) for details. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/checkbox.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/checkbox.mdx index 9bdc112288e02d..3efd4ea599c7ec 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/checkbox.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/checkbox.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Checkbox matches the official Jetpack Compose [Checkbox](https://developer.android.com/develop/ui/compose/components/checkbox) API. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/chip.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/chip.mdx index c0673b801cb624..3c15f1b9fd53cd 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/chip.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/chip.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Chips match the official Jetpack Compose [Chip API](https://developer.android.com/develop/ui/compose/components/chip). Each chip type is a separate component: `AssistChip`, `FilterChip`, `InputChip`, and `SuggestionChip`. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/column.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/column.mdx index 6a66988a52b741..b310169fd02b96 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/column.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/column.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Column matches the official Jetpack Compose [Column](https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#Column) API and places children vertically with configurable arrangement and alignment. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/datetimepicker.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/datetimepicker.mdx index a9a7c406f90428..c308980ccc3725 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/datetimepicker.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/datetimepicker.mdx @@ -8,11 +8,19 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI DateTimePicker matches the official Jetpack Compose [Date Picker](https://developer.android.com/develop/ui/compose/components/datepickers) and [Time Picker](https://developer.android.com/develop/ui/compose/components/time-pickers) APIs and supports date, time, and combined selection. > **Note:** The date variants render Material's calendar grid and input field, both of which scroll horizontally internally. The parent `Host` must provide a finite width on the horizontal axis, use `matchContents={{ vertical: true }}` together with `style={{ width: '100%' }}` (or any finite width). See [Match contents in Host reference](host/#match-contents) for details. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/divider.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/divider.mdx index d9de29ceda5a3e..05c3c711091ab0 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/divider.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/divider.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI provides [`HorizontalDivider`]() and [`VerticalDivider`]() matching the official Jetpack Compose Divider API. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/dockedsearchbar.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/dockedsearchbar.mdx index a6a97030892e21..2518ed97226d0d 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/dockedsearchbar.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/dockedsearchbar.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI DockedSearchBar matches the official Jetpack Compose [SearchBar API](https://developer.android.com/develop/ui/compose/components/search-bar) and displays a search input that remains anchored in its parent layout rather than expanding to full screen. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/dropdownmenu.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/dropdownmenu.mdx index 78b2fe246699bc..2080ab8693a075 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/dropdownmenu.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/dropdownmenu.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI DropdownMenu matches the official Jetpack Compose [Menu API](https://developer.android.com/develop/ui/compose/components/menu) and displays a dropdown menu when a trigger element is pressed. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/exposeddropdownmenubox.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/exposeddropdownmenubox.mdx index 1a5522c2ba8fb7..296ab47974745f 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/exposeddropdownmenubox.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/exposeddropdownmenubox.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI `ExposedDropdownMenuBox` matches the official Jetpack Compose [`ExposedDropdownMenuBox`](https://kotlinlang.org/api/compose-multiplatform/material3/androidx.compose.material3/-exposed-dropdown-menu-box.html). Use the `menuAnchor()` modifier on the anchor content (typically a read-only `TextField`) and `ExposedDropdownMenu` to wrap `DropdownMenuItem` children. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/floatingactionbutton.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/floatingactionbutton.mdx index a7b61b53555233..1d01b50a435759 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/floatingactionbutton.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/floatingactionbutton.mdx @@ -8,6 +8,7 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI provides four FloatingActionButton variants matching the Material Design 3 [`FloatingActionButton`](https://developer.android.com/develop/ui/compose/components/fab) API: @@ -20,6 +21,13 @@ Each component uses slot-based children (`.Icon` and, for `ExtendedFloatingActio > **Note:** If you need multiple action buttons in a floating toolbar, use [`HorizontalFloatingToolbar`](/versions/latest/sdk/ui/jetpack-compose/horizontalfloatingtoolbar/) instead. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/flowrow.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/flowrow.mdx index d2e42006696e87..aef1df427321be 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/flowrow.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/flowrow.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI FlowRow matches the official Jetpack Compose [FlowRow](https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#FlowRow) API and arranges children in a horizontal flow that wraps to the next line when it runs out of space. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/horizontalfloatingtoolbar.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/horizontalfloatingtoolbar.mdx index 115dc26c6d5def..12e68922da19ba 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/horizontalfloatingtoolbar.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/horizontalfloatingtoolbar.mdx @@ -8,11 +8,19 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI HorizontalFloatingToolbar wraps the official Jetpack Compose [`HorizontalFloatingToolbar`](https://kotlinlang.org/api/compose-multiplatform/material3/androidx.compose.material3/-horizontal-floating-toolbar.html) and displays a horizontal toolbar that floats above content, containing action buttons. > **Note:** If you only need a single floating button, use [`FloatingActionButton`](/versions/unversioned/sdk/ui/jetpack-compose/floatingactionbutton/) instead. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/horizontalpager.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/horizontalpager.mdx index 16ec206e298548..d7582c0b6ad229 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/horizontalpager.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/horizontalpager.mdx @@ -8,11 +8,19 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI HorizontalPager matches Jetpack Compose's [HorizontalPager]() — a horizontally scrolling pager that snaps to individual pages. `HorizontalPager` does not impose its own height — give it one with the [`height`](modifiers/#heightheight) modifier or place it inside a parent with a finite height. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/icon.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/icon.mdx index 7276933e25f097..0d5c896d60cdcc 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/icon.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/icon.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; An icon component for rendering icons in Jetpack Compose. We recommend downloading icons as XML vector drawables from [Material Symbols](https://fonts.google.com/icons), which is the standard approach for Android development. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/iconbutton.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/iconbutton.mdx index 38c17a9ce69b85..95c2fa6765005e 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/iconbutton.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/iconbutton.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI provides four icon button components that match the official Jetpack Compose [IconButton API](https://developer.android.com/develop/ui/compose/components/icon-button): `IconButton`, `FilledIconButton`, `FilledTonalIconButton`, and `OutlinedIconButton`. All variants share the same props and accept composable children for content. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/lazycolumn.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/lazycolumn.mdx index 0fe8b56d87601a..ea5b1ddc24996f 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/lazycolumn.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/lazycolumn.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; A lazily-loaded vertical list component that only renders visible items for efficient scrolling. See the [official Jetpack Compose documentation](https://developer.android.com/develop/ui/compose/lists) for more information. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/lazyrow.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/lazyrow.mdx index 9375399c4635be..5bcd0de822c140 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/lazyrow.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/lazyrow.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; A lazily-loaded horizontal list component that only renders visible items for efficient scrolling. See the [official Jetpack Compose documentation](https://developer.android.com/develop/ui/compose/lists) for more information. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/listitem.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/listitem.mdx index 1957f6a63ea1c6..b8f3bff8439dd2 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/listitem.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/listitem.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI ListItem matches the official Jetpack Compose [`ListItem`]() API for structured list entries with headline, supporting, overline, leading, and trailing content slots. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/progress.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/progress.mdx index 38630c9027d9ad..439f8cd469fb3d 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/progress.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/progress.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Progress Indicators match the official Jetpack Compose [Progress Indicator API](https://developer.android.com/develop/ui/compose/components/progress). + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/pulltorefreshbox.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/pulltorefreshbox.mdx index 40be6221779b72..86df774d12ab83 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/pulltorefreshbox.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/pulltorefreshbox.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI PullToRefreshBox matches the official Jetpack Compose [PullToRefreshBox]() API. It wraps scrollable content and shows a refresh indicator when pulled. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/radiobutton.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/radiobutton.mdx index daa353a0864a18..974ec123738a0a 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/radiobutton.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/radiobutton.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; A radio button component for selecting a single option from a set. Maps to the official Jetpack Compose [RadioButton](https://developer.android.com/develop/ui/compose/components/radio-button) API. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/row.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/row.mdx index 848bd649479299..f346e86e6e3e2b 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/row.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/row.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Row matches the official Jetpack Compose [Row](https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#Row) API and places children horizontally with configurable arrangement and alignment. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/searchbar.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/searchbar.mdx index a8d84dc9597379..8d87a30b4765df 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/searchbar.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/searchbar.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI SearchBar matches the official Jetpack Compose [Search](https://developer.android.com/develop/ui/compose/components/search-bar) API and provides a search input with support for placeholder text and expanded full-screen search. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/segmentedbutton.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/segmentedbutton.mdx index f2e7e559d6c68b..9a78c717135cd6 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/segmentedbutton.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/segmentedbutton.mdx @@ -8,6 +8,7 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Segmented buttons let app users choose from a small set of options displayed side by side in a row. They map to the official Jetpack Compose [Segmented Button](https://developer.android.com/develop/ui/compose/components/segmented-button) API. @@ -16,6 +17,13 @@ There are two container types: - **`SingleChoiceSegmentedButtonRow`**: only one button can be selected at a time (like radio buttons). - **`MultiChoiceSegmentedButtonRow`**: multiple buttons can be toggled independently (like checkboxes). + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/shape.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/shape.mdx index 291c14613cd358..bc21976cd62eb1 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/shape.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/shape.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Shape matches the official Jetpack Compose [Shapes](https://developer.android.com/develop/ui/compose/graphics/draw/shapes) API and provides a set of sub-components for drawing geometric shapes such as stars, circles, rectangles, pills, and polygons. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/slider.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/slider.mdx index c83063a3c87198..dce2a7cb22b84a 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/slider.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/slider.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Slider matches the official Jetpack Compose [Slider API](https://developer.android.com/develop/ui/compose/components/slider) and allows selecting values from a bounded range. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/spacer.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/spacer.mdx index 61bd8ca98c4c51..cc410da547e826 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/spacer.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/spacer.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Spacer matches the official Jetpack Compose [Spacer](https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#Spacer) API and is used to add flexible or fixed-size space between elements in a layout. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/surface.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/surface.mdx index 7fe0c8e3ea8c9a..f5cdd3548fc5c6 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/surface.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/surface.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Surface matches the official Jetpack Compose [Surface](https://developer.android.com/develop/ui/compose/designsystems/material3) API and provides a container that applies Material Design surface styling including color, elevation, and content color. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/switch.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/switch.mdx index e2c13605ae6426..96685114141285 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/switch.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/switch.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Switch matches the official Jetpack Compose [Switch](https://developer.android.com/develop/ui/compose/components/switch) API. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/text.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/text.mdx index ab16c3d57fc59a..853edd6f070241 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/text.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/text.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Text matches the official Jetpack Compose [Text styling](https://developer.android.com/develop/ui/compose/text/style-text) API and displays text with Material 3 typography styles, custom fonts, and text formatting options. + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/textfield.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/textfield.mdx index 18b7026de506a6..42e834179ea073 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/textfield.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/textfield.mdx @@ -8,6 +8,7 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI provides two text field components that match the official Jetpack Compose [TextField API](https://developer.android.com/develop/ui/compose/text/user-input): `TextField` (filled) and `OutlinedTextField` (outlined border). Both variants share the same props and support composable slot children for label, placeholder, icons, prefix, suffix, and supporting text. @@ -16,6 +17,13 @@ Expo UI provides two text field components that match the official Jetpack Compo | Filled | Solid background with a bottom indicator line. | Default text input style following Material3 design. Use for most forms and input fields. | | Outlined | Transparent background with a border outline. | Alternative style that provides a distinct visual boundary. Use when filled fields blend into the background. | + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/togglebutton.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/togglebutton.mdx index 0fb81d0cf92639..a570507814397c 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/togglebutton.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/togglebutton.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI provides four toggle button components that match the official Jetpack Compose Toggle Button API: [`ToggleButton`](https://kotlinlang.org/api/compose-multiplatform/material3/androidx.compose.material3/-toggle-button.html), [`IconToggleButton`](https://kotlinlang.org/api/compose-multiplatform/material3/androidx.compose.material3/-icon-toggle-button.html), [`FilledIconToggleButton`](https://kotlinlang.org/api/compose-multiplatform/material3/androidx.compose.material3/-filled-icon-toggle-button.html), and [`OutlinedIconToggleButton`](https://kotlinlang.org/api/compose-multiplatform/material3/androidx.compose.material3/-outlined-icon-toggle-button.html). + + ## Installation diff --git a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/tooltip.mdx b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/tooltip.mdx index 7777728f7c2b27..f85ffb5c8a8a3e 100644 --- a/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/tooltip.mdx +++ b/docs/pages/versions/unversioned/sdk/ui/jetpack-compose/tooltip.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Tooltip matches the official Jetpack Compose [Tooltip](https://developer.android.com/develop/ui/compose/components/tooltip) API. `TooltipBox` wraps anchor content and displays a tooltip. The tooltip content is provided via the `TooltipBox.PlainTooltip` or `TooltipBox.RichTooltip` compound components, which match [`PlainTooltip`](https://developer.android.com/develop/ui/compose/components/tooltip#display-plain) and [`RichTooltip`](https://developer.android.com/develop/ui/compose/components/tooltip#display-rich) respectively. Tooltips can be triggered by long-press or shown programmatically via `ref`. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/alertdialog.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/alertdialog.mdx index 13de32a4baa718..9a84494523994f 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/alertdialog.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/alertdialog.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI AlertDialog matches the official Jetpack Compose [AlertDialog](https://developer.android.com/develop/ui/compose/components/dialog) API. Content is provided via slot sub-components (`AlertDialog.Title`, `AlertDialog.Text`, `AlertDialog.ConfirmButton`, `AlertDialog.DismissButton`, `AlertDialog.Icon`) that map directly to Compose's slot parameters. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/badge.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/badge.mdx index 3724bb9352e8ed..db52127314724d 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/badge.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/badge.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Badge matches the official Jetpack Compose [`Badge`](https://developer.android.com/develop/ui/compose/components/badges) API. It renders as a small colored indicator dot, or with content such as a count number. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/badgedbox.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/badgedbox.mdx index ec92bdcea8de1c..46d08208cf867f 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/badgedbox.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/badgedbox.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI BadgedBox matches the official Jetpack Compose [`BadgedBox`](https://developer.android.com/develop/ui/compose/components/badges) API. It overlays a badge on top of content such as an icon. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/basicalertdialog.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/basicalertdialog.mdx index 55c8a24721deec..12c683abdf3cea 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/basicalertdialog.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/basicalertdialog.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI BasicAlertDialog matches the official Jetpack Compose [BasicAlertDialog](https://developer.android.com/develop/ui/compose/components/dialog) API and displays a minimal dialog that accepts custom children as its content, giving you full control over the dialog layout. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/bottomsheet.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/bottomsheet.mdx index 367780c38ceaab..9f14293df34c55 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/bottomsheet.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/bottomsheet.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI ModalBottomSheet matches the official Jetpack Compose [Bottom Sheet API](https://developer.android.com/develop/ui/compose/components/bottom-sheets) and displays content in a modal sheet that slides up from the bottom. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/box.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/box.mdx index 23275bc5599c6a..f44241ac9cf4de 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/box.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/box.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Box matches the official Jetpack Compose [Box](https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#Box) API and stacks children on top of each other with configurable content alignment. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/button.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/button.mdx index fa9117a41aaddc..4c70d358dd127d 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/button.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/button.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI provides five button components that match the official Jetpack Compose [Button API](https://developer.android.com/develop/ui/compose/components/button): `Button` (filled), `FilledTonalButton`, `OutlinedButton`, `ElevatedButton`, and `TextButton`. All variants share the same props and accept composable children for content. + + | Type | Appearance | Purpose | | ------------ | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Filled | Solid background with contrasting text. | High-emphasis buttons for primary actions such as "submit" and "save." | diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/card.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/card.mdx index 3459f9ed0d400c..9ceba5d3ff90b9 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/card.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/card.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Card matches the official Jetpack Compose [Card API](https://developer.android.com/develop/ui/compose/components/card) and displays content inside a styled surface container with optional elevation and outline. The `Card` component renders a [filled card](https://developer.android.com/develop/ui/compose/components/card#filled), while `ElevatedCard` and `OutlinedCard` provide raised and bordered variants respectively. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/carousel.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/carousel.mdx index a65ff37e71b875..c05c28f5598f61 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/carousel.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/carousel.mdx @@ -8,11 +8,19 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI provides three carousel components matching the official Jetpack Compose [Carousel](https://developer.android.com/develop/ui/compose/components/carousel) API: `HorizontalCenteredHeroCarousel`, `HorizontalMultiBrowseCarousel`, and `HorizontalUncontainedCarousel`. > **Note:** Carousel is a horizontally scrollable component, so the parent `Host` must provide a finite width on the scroll axis. Use `matchContents={{ vertical: true }}` together with `style={{ width: '100%' }}` (or any finite width). See [Match contents in Host reference](host/#match-contents) for details. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/checkbox.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/checkbox.mdx index 34588d32bd5cdc..04b70297dc5bb1 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/checkbox.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/checkbox.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Checkbox matches the official Jetpack Compose [Checkbox](https://developer.android.com/develop/ui/compose/components/checkbox) API. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/chip.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/chip.mdx index 9116f19afbce72..c1a4e09f490caa 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/chip.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/chip.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Chips match the official Jetpack Compose [Chip API](https://developer.android.com/develop/ui/compose/components/chip). Each chip type is a separate component: `AssistChip`, `FilterChip`, `InputChip`, and `SuggestionChip`. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/column.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/column.mdx index 5dda7df9769d3c..ed6a879a977264 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/column.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/column.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Column matches the official Jetpack Compose [Column](https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#Column) API and places children vertically with configurable arrangement and alignment. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/datetimepicker.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/datetimepicker.mdx index 4443129e9792d7..a4603726b9a0f6 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/datetimepicker.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/datetimepicker.mdx @@ -8,11 +8,19 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI DateTimePicker matches the official Jetpack Compose [Date Picker](https://developer.android.com/develop/ui/compose/components/datepickers) and [Time Picker](https://developer.android.com/develop/ui/compose/components/time-pickers) APIs and supports date, time, and combined selection. > **Note:** The date variants render Material's calendar grid and input field, both of which scroll horizontally internally. The parent `Host` must provide a finite width on the horizontal axis, use `matchContents={{ vertical: true }}` together with `style={{ width: '100%' }}` (or any finite width). See [Match contents in Host reference](host/#match-contents) for details. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/divider.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/divider.mdx index 5d8b0fe4eaa7f2..fac4b1a94cbff0 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/divider.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/divider.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI provides [`HorizontalDivider`]() and [`VerticalDivider`]() matching the official Jetpack Compose Divider API. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/dockedsearchbar.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/dockedsearchbar.mdx index 5661f24d03c126..41a336d866d0ed 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/dockedsearchbar.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/dockedsearchbar.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI DockedSearchBar matches the official Jetpack Compose [SearchBar API](https://developer.android.com/develop/ui/compose/components/search-bar) and displays a search input that remains anchored in its parent layout rather than expanding to full screen. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/dropdownmenu.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/dropdownmenu.mdx index 6acbe8b9506892..41be945ee93d1e 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/dropdownmenu.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/dropdownmenu.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI DropdownMenu matches the official Jetpack Compose [Menu API](https://developer.android.com/develop/ui/compose/components/menu) and displays a dropdown menu when a trigger element is pressed. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/exposeddropdownmenubox.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/exposeddropdownmenubox.mdx index 895c0fb19e3313..71f032296d98f0 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/exposeddropdownmenubox.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/exposeddropdownmenubox.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI `ExposedDropdownMenuBox` matches the official Jetpack Compose [`ExposedDropdownMenuBox`](https://kotlinlang.org/api/compose-multiplatform/material3/androidx.compose.material3/-exposed-dropdown-menu-box.html). Use the `menuAnchor()` modifier on the anchor content (typically a read-only `TextField`) and `ExposedDropdownMenu` to wrap `DropdownMenuItem` children. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/floatingactionbutton.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/floatingactionbutton.mdx index a27f36f6621ed5..78154413e14495 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/floatingactionbutton.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/floatingactionbutton.mdx @@ -8,6 +8,7 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI provides four FloatingActionButton variants matching the Material Design 3 [`FloatingActionButton`](https://developer.android.com/develop/ui/compose/components/fab) API: @@ -20,6 +21,13 @@ Each component uses slot-based children (`.Icon` and, for `ExtendedFloatingActio > **Note:** If you need multiple action buttons in a floating toolbar, use [`HorizontalFloatingToolbar`](/versions/latest/sdk/ui/jetpack-compose/horizontalfloatingtoolbar/) instead. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/flowrow.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/flowrow.mdx index d8779497a60594..ce7e818923e2ae 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/flowrow.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/flowrow.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI FlowRow matches the official Jetpack Compose [FlowRow](https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#FlowRow) API and arranges children in a horizontal flow that wraps to the next line when it runs out of space. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/horizontalfloatingtoolbar.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/horizontalfloatingtoolbar.mdx index 299db573916b7e..04ea867d32df2f 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/horizontalfloatingtoolbar.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/horizontalfloatingtoolbar.mdx @@ -8,11 +8,19 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI HorizontalFloatingToolbar wraps the official Jetpack Compose [`HorizontalFloatingToolbar`](https://kotlinlang.org/api/compose-multiplatform/material3/androidx.compose.material3/-horizontal-floating-toolbar.html) and displays a horizontal toolbar that floats above content, containing action buttons. > **Note:** If you only need a single floating button, use [`FloatingActionButton`](/versions/unversioned/sdk/ui/jetpack-compose/floatingactionbutton/) instead. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/horizontalpager.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/horizontalpager.mdx index 5b4cda97641002..6a15084ea4e05d 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/horizontalpager.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/horizontalpager.mdx @@ -8,11 +8,19 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI HorizontalPager matches Jetpack Compose's [HorizontalPager]() — a horizontally scrolling pager that snaps to individual pages. `HorizontalPager` does not impose its own height — give it one with the [`height`](modifiers/#heightheight) modifier or place it inside a parent with a finite height. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/icon.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/icon.mdx index 5fb67861d6e962..60363e6d6139b9 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/icon.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/icon.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; An icon component for rendering icons in Jetpack Compose. We recommend downloading icons as XML vector drawables from [Material Symbols](https://fonts.google.com/icons), which is the standard approach for Android development. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/iconbutton.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/iconbutton.mdx index 0d4ed5e4476d86..284567d08cffa9 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/iconbutton.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/iconbutton.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI provides four icon button components that match the official Jetpack Compose [IconButton API](https://developer.android.com/develop/ui/compose/components/icon-button): `IconButton`, `FilledIconButton`, `FilledTonalIconButton`, and `OutlinedIconButton`. All variants share the same props and accept composable children for content. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/lazycolumn.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/lazycolumn.mdx index 056d21158eaf79..7d2a14fe6fbe24 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/lazycolumn.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/lazycolumn.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; A lazily-loaded vertical list component that only renders visible items for efficient scrolling. See the [official Jetpack Compose documentation](https://developer.android.com/develop/ui/compose/lists) for more information. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/lazyrow.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/lazyrow.mdx index 5479d897ad505c..052ba8a71b95ed 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/lazyrow.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/lazyrow.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; A lazily-loaded horizontal list component that only renders visible items for efficient scrolling. See the [official Jetpack Compose documentation](https://developer.android.com/develop/ui/compose/lists) for more information. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/listitem.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/listitem.mdx index d552eb8dbe1ad7..f4ebbf87734cb9 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/listitem.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/listitem.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI ListItem matches the official Jetpack Compose [`ListItem`]() API for structured list entries with headline, supporting, overline, leading, and trailing content slots. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/progress.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/progress.mdx index 081819ac6dbb2c..79d7551171c1b7 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/progress.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/progress.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Progress Indicators match the official Jetpack Compose [Progress Indicator API](https://developer.android.com/develop/ui/compose/components/progress). + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/pulltorefreshbox.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/pulltorefreshbox.mdx index 8dedb7d674b6fc..007e8d897958f6 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/pulltorefreshbox.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/pulltorefreshbox.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI PullToRefreshBox matches the official Jetpack Compose [PullToRefreshBox]() API. It wraps scrollable content and shows a refresh indicator when pulled. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/radiobutton.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/radiobutton.mdx index 12aa34cbfcd634..74aaabef7782a4 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/radiobutton.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/radiobutton.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; A radio button component for selecting a single option from a set. Maps to the official Jetpack Compose [RadioButton](https://developer.android.com/develop/ui/compose/components/radio-button) API. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/row.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/row.mdx index 686ebe189af079..e7b83dc3ba32aa 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/row.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/row.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Row matches the official Jetpack Compose [Row](https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#Row) API and places children horizontally with configurable arrangement and alignment. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/searchbar.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/searchbar.mdx index 30154db493e0c0..539ecc94516b89 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/searchbar.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/searchbar.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI SearchBar matches the official Jetpack Compose [Search](https://developer.android.com/develop/ui/compose/components/search-bar) API and provides a search input with support for placeholder text and expanded full-screen search. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/segmentedbutton.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/segmentedbutton.mdx index 7f96abc3a015e1..cccfbab82d07b0 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/segmentedbutton.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/segmentedbutton.mdx @@ -8,6 +8,7 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Segmented buttons let app users choose from a small set of options displayed side by side in a row. They map to the official Jetpack Compose [Segmented Button](https://developer.android.com/develop/ui/compose/components/segmented-button) API. @@ -16,6 +17,13 @@ There are two container types: - **`SingleChoiceSegmentedButtonRow`**: only one button can be selected at a time (like radio buttons). - **`MultiChoiceSegmentedButtonRow`**: multiple buttons can be toggled independently (like checkboxes). + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/shape.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/shape.mdx index b029ee32a7e56e..e60079ddaec901 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/shape.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/shape.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Shape matches the official Jetpack Compose [Shapes](https://developer.android.com/develop/ui/compose/graphics/draw/shapes) API and provides a set of sub-components for drawing geometric shapes such as stars, circles, rectangles, pills, and polygons. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/slider.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/slider.mdx index ea87c3449218a2..2fb83d6093f781 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/slider.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/slider.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Slider matches the official Jetpack Compose [Slider API](https://developer.android.com/develop/ui/compose/components/slider) and allows selecting values from a bounded range. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/spacer.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/spacer.mdx index 204685f4ed92e2..a3c1abe0935c23 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/spacer.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/spacer.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Spacer matches the official Jetpack Compose [Spacer](https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#Spacer) API and is used to add flexible or fixed-size space between elements in a layout. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/surface.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/surface.mdx index 3662e0a4eb5b7c..013d957e3e70e8 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/surface.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/surface.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Surface matches the official Jetpack Compose [Surface](https://developer.android.com/develop/ui/compose/designsystems/material3) API and provides a container that applies Material Design surface styling including color, elevation, and content color. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/switch.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/switch.mdx index e266297d748c54..bf6f8a6552eb09 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/switch.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/switch.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Switch matches the official Jetpack Compose [Switch](https://developer.android.com/develop/ui/compose/components/switch) API. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/text.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/text.mdx index c5452697c0542c..0b0f4c37611d7b 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/text.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/text.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Text matches the official Jetpack Compose [Text styling](https://developer.android.com/develop/ui/compose/text/style-text) API and displays text with Material 3 typography styles, custom fonts, and text formatting options. + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/textfield.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/textfield.mdx index d6f322eb9ca396..f28fcc5baec6bf 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/textfield.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/textfield.mdx @@ -8,6 +8,7 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI provides two text field components that match the official Jetpack Compose [TextField API](https://developer.android.com/develop/ui/compose/text/user-input): `TextField` (filled) and `OutlinedTextField` (outlined border). Both variants share the same props and support composable slot children for label, placeholder, icons, prefix, suffix, and supporting text. @@ -16,6 +17,13 @@ Expo UI provides two text field components that match the official Jetpack Compo | Filled | Solid background with a bottom indicator line. | Default text input style following Material3 design. Use for most forms and input fields. | | Outlined | Transparent background with a border outline. | Alternative style that provides a distinct visual boundary. Use when filled fields blend into the background. | + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/togglebutton.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/togglebutton.mdx index 80c3858db08407..0b9765e6cf77ff 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/togglebutton.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/togglebutton.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI provides four toggle button components that match the official Jetpack Compose Toggle Button API: [`ToggleButton`](https://kotlinlang.org/api/compose-multiplatform/material3/androidx.compose.material3/-toggle-button.html), [`IconToggleButton`](https://kotlinlang.org/api/compose-multiplatform/material3/androidx.compose.material3/-icon-toggle-button.html), [`FilledIconToggleButton`](https://kotlinlang.org/api/compose-multiplatform/material3/androidx.compose.material3/-filled-icon-toggle-button.html), and [`OutlinedIconToggleButton`](https://kotlinlang.org/api/compose-multiplatform/material3/androidx.compose.material3/-outlined-icon-toggle-button.html). + + ## Installation diff --git a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/tooltip.mdx b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/tooltip.mdx index ec97f661981311..9f83351bc231b0 100644 --- a/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/tooltip.mdx +++ b/docs/pages/versions/v56.0.0/sdk/ui/jetpack-compose/tooltip.mdx @@ -8,9 +8,17 @@ platforms: ['android', 'expo-go'] import APISection from '~/components/plugins/APISection'; import { APIInstallSection } from '~/components/plugins/InstallSection'; +import { ComponentDiagram } from '~/ui/components/Diagram'; Expo UI Tooltip matches the official Jetpack Compose [Tooltip](https://developer.android.com/develop/ui/compose/components/tooltip) API. `TooltipBox` wraps anchor content and displays a tooltip. The tooltip content is provided via the `TooltipBox.PlainTooltip` or `TooltipBox.RichTooltip` compound components, which match [`PlainTooltip`](https://developer.android.com/develop/ui/compose/components/tooltip#display-plain) and [`RichTooltip`](https://developer.android.com/develop/ui/compose/components/tooltip#display-rich) respectively. Tooltips can be triggered by long-press or shown programmatically via `ref`. + + ## Installation diff --git a/docs/public/static/data/unversioned/expo-file-system.json b/docs/public/static/data/unversioned/expo-file-system.json index 1bf0feaf642e34..0d3d419971f099 100644 --- a/docs/public/static/data/unversioned/expo-file-system.json +++ b/docs/public/static/data/unversioned/expo-file-system.json @@ -1 +1 @@ -{"schemaVersion":"2.0","name":"expo-file-system","variant":"project","kind":1,"children":[{"name":"EncodingType","variant":"declaration","kind":8,"children":[{"name":"Base64","variant":"declaration","kind":16,"comment":{"summary":[{"kind":"text","text":"Binary, radix-64 representation."}]},"type":{"type":"literal","value":"base64"}},{"name":"UTF8","variant":"declaration","kind":16,"comment":{"summary":[{"kind":"text","text":"Standard encoding format."}]},"type":{"type":"literal","value":"utf8"}}]},{"name":"FileMode","variant":"declaration","kind":8,"comment":{"summary":[{"kind":"text","text":"Specifies the access mode when opening a file handle."}]},"children":[{"name":"Append","variant":"declaration","kind":16,"comment":{"summary":[{"kind":"text","text":"Opens the file for writing only.\nThe cursor is positioned at the end of the file.\n\n> **Note**: For SAF files, this is a strict append-only mode.\nThe cursor cannot be moved; calling "},{"kind":"code","text":"`seek()`"},{"kind":"text","text":" will have no effect."}]},"type":{"type":"literal","value":"wa"}},{"name":"ReadOnly","variant":"declaration","kind":16,"comment":{"summary":[{"kind":"text","text":"Opens the file for reading only.\nThe cursor is positioned at the beginning of the file."}]},"type":{"type":"literal","value":"r"}},{"name":"ReadWrite","variant":"declaration","kind":16,"comment":{"summary":[{"kind":"text","text":"Opens the file for both reading and writing.\nThe cursor is positioned at the beginning of the file.\n\n> **Note**: This mode cannot be used with SAF (Storage Access Framework) "},{"kind":"code","text":"`content://`"},{"kind":"text","text":" URIs."}]},"type":{"type":"literal","value":"rw"}},{"name":"Truncate","variant":"declaration","kind":16,"comment":{"summary":[{"kind":"text","text":"Opens the file for writing only and truncates the file to zero length (wipes content)."}]},"type":{"type":"literal","value":"wt"}},{"name":"WriteOnly","variant":"declaration","kind":16,"comment":{"summary":[{"kind":"text","text":"Opens the file for writing only.\nThe cursor is positioned at the beginning of the file."}]},"type":{"type":"literal","value":"w"}}]},{"name":"UploadType","variant":"declaration","kind":8,"comment":{"summary":[{"kind":"text","text":"Represents the type of upload operation."}]},"children":[{"name":"BINARY_CONTENT","variant":"declaration","kind":16,"comment":{"summary":[{"kind":"text","text":"Binary content upload - the file is uploaded as-is in the request body."}]},"type":{"type":"literal","value":0}},{"name":"MULTIPART","variant":"declaration","kind":16,"comment":{"summary":[{"kind":"text","text":"Multipart form upload - the file is uploaded as part of a multipart/form-data request."}]},"type":{"type":"literal","value":1}}]},{"name":"Directory","variant":"declaration","kind":128,"comment":{"summary":[{"kind":"text","text":"Represents a directory on the filesystem.\n\nA "},{"kind":"code","text":"`Directory`"},{"kind":"text","text":" instance can be created for any path, and does not need to exist on the filesystem during creation.\n\nThe constructor accepts an array of strings that are joined to create the directory URI. The first argument can also be a "},{"kind":"code","text":"`Directory`"},{"kind":"text","text":" instance (like "},{"kind":"code","text":"`Paths.cache`"},{"kind":"text","text":")."}],"blockTags":[{"tag":"@example","content":[{"kind":"code","text":"```ts\nconst directory = new Directory(Paths.cache, \"subdirName\");\n```"}]}]},"children":[{"name":"constructor","variant":"declaration","kind":512,"signatures":[{"name":"Directory","variant":"signature","kind":16384,"comment":{"summary":[{"kind":"text","text":"Creates an instance of a directory. It can be created for any path, and does not need to exist on the filesystem during creation.\n\nThe constructor accepts an array of strings that are joined to create the directory URI. The first argument can also be a "},{"kind":"code","text":"`Directory`"},{"kind":"text","text":" instance (like "},{"kind":"code","text":"`Paths.cache`"},{"kind":"text","text":")."}],"blockTags":[{"tag":"@example","content":[{"kind":"code","text":"```ts\nconst directory = new Directory(Paths.cache, \"subdirName\");\n```"}]}]},"parameters":[{"name":"uris","variant":"param","kind":32768,"flags":{"isRest":true},"comment":{"summary":[{"kind":"text","text":"An array of: "},{"kind":"code","text":"`file:///`"},{"kind":"text","text":" string URIs, "},{"kind":"code","text":"`File`"},{"kind":"text","text":" instances, and "},{"kind":"code","text":"`Directory`"},{"kind":"text","text":" instances representing an arbitrary location on the file system."}]},"type":{"type":"array","elementType":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}}}],"type":{"type":"reference","name":"Directory","package":"expo-file-system"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.constructor","package":"expo-file-system"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.constructor","package":"expo-file-system"}},{"name":"exists","variant":"declaration","kind":1024,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A boolean representing if a directory exists and can be accessed."}]},"type":{"type":"intrinsic","name":"boolean"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.exists"}},{"name":"size","variant":"declaration","kind":1024,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A size of the directory in bytes. Null if the directory does not exist, or it cannot be read."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"number"},{"type":"literal","value":null}]},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.size"}},{"name":"uri","variant":"declaration","kind":1024,"flags":{"isReadonly":true,"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Represents the directory URI. The field is read-only, but it may change as a result of calling some methods such as "},{"kind":"code","text":"`move`"},{"kind":"text","text":"."}]},"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.uri"}},{"name":"pickDirectoryAsync","variant":"declaration","kind":1024,"flags":{"isStatic":true},"comment":{"summary":[{"kind":"text","text":"A static method that opens a file picker to select a directory.\n\nOn iOS, the selected directory grants temporary read and write access for the current app session only. After the app restarts, you must prompt the user again to regain access."}]},"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"signatures":[{"name":"__type","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"a "},{"kind":"code","text":"`Directory`"},{"kind":"text","text":" instance. On Android, the underlying uri will be a content URI."}]}]},"parameters":[{"name":"initialUri","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"An optional uri pointing to an initial folder on which the directory picker is opened."}]},"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","name":"Directory","package":"expo-file-system"}],"name":"Promise","package":"typescript"}}]}},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.pickDirectoryAsync"}},{"name":"name","variant":"declaration","kind":262144,"getSignature":{"name":"name","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"Directory name."}]},"type":{"type":"intrinsic","name":"string"}}},{"name":"parentDirectory","variant":"declaration","kind":262144,"getSignature":{"name":"parentDirectory","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"Directory containing the file."}]},"type":{"type":"reference","name":"Directory","package":"expo-file-system"}}},{"name":"copy","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"copy","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Copies a directory."}]},"parameters":[{"name":"destination","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"Directory"},"name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"RelocationOptions"},"name":"RelocationOptions","package":"expo-file-system"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.copy","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.copy","package":"expo-file-system"}},{"name":"copySync","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"copySync","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Copies a directory synchronously."}]},"parameters":[{"name":"destination","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"Directory"},"name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"RelocationOptions"},"name":"RelocationOptions","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.copySync","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.copySync","package":"expo-file-system"}},{"name":"create","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"create","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Creates a directory that the current uri points to."}],"blockTags":[{"tag":"@throws","content":[{"kind":"text","text":"Error if the containing folder doesn't exist, the application has no read access to it or the directory (or a file with the same path) already exists (unless "},{"kind":"code","text":"`idempotent`"},{"kind":"text","text":" is "},{"kind":"code","text":"`true`"},{"kind":"text","text":")."}]}]},"parameters":[{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","name":"DirectoryCreateOptions","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.create"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.create"}},{"name":"createDirectory","variant":"declaration","kind":2048,"signatures":[{"name":"createDirectory","variant":"signature","kind":4096,"parameters":[{"name":"name","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"reference","name":"Directory","package":"expo-file-system"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.createDirectory"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.createDirectory"}},{"name":"createFile","variant":"declaration","kind":2048,"signatures":[{"name":"createFile","variant":"signature","kind":4096,"parameters":[{"name":"name","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"mimeType","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"literal","value":null}]}}],"type":{"type":"reference","name":"File","package":"expo-file-system"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.createFile","package":"expo-file-system"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.createFile","package":"expo-file-system"}},{"name":"delete","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"delete","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Deletes a directory. Also deletes all files and directories inside the directory."}],"blockTags":[{"tag":"@throws","content":[{"kind":"text","text":"Error if the directory does not exist or cannot be deleted."}]}]},"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.delete"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.delete"}},{"name":"info","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"info","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Retrieves an object containing properties of a directory."}],"blockTags":[{"tag":"@throws","content":[{"kind":"text","text":"Error If the application does not have read access to the directory, or if the path does not point to a directory (e.g., it points to a file)."}]},{"tag":"@returns","content":[{"kind":"text","text":"An object with directory metadata (for example, size, creation date, and so on)."}]}]},"type":{"type":"reference","name":"DirectoryInfo","package":"expo-file-system"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.info"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.info"}},{"name":"list","variant":"declaration","kind":2048,"signatures":[{"name":"list","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Lists the contents of a directory.\nCalling this method if the parent directory does not exist will throw an error."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"An array of "},{"kind":"code","text":"`Directory`"},{"kind":"text","text":" and "},{"kind":"code","text":"`File`"},{"kind":"text","text":" instances."}]}]},"type":{"type":"array","elementType":{"type":"union","types":[{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.list","package":"expo-file-system"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.list","package":"expo-file-system"}},{"name":"move","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"move","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Moves a directory. Updates the "},{"kind":"code","text":"`uri`"},{"kind":"text","text":" property that now points to the new location."}]},"parameters":[{"name":"destination","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"Directory"},"name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"RelocationOptions"},"name":"RelocationOptions","package":"expo-file-system"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.move","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.move","package":"expo-file-system"}},{"name":"moveSync","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"moveSync","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Moves a directory synchronously. Updates the "},{"kind":"code","text":"`uri`"},{"kind":"text","text":" property that now points to the new location."}]},"parameters":[{"name":"destination","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"Directory"},"name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"RelocationOptions"},"name":"RelocationOptions","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.moveSync","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.moveSync","package":"expo-file-system"}},{"name":"rename","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"rename","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Renames a directory."}]},"parameters":[{"name":"newName","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.rename"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.rename"}},{"name":"watch","variant":"declaration","kind":2048,"signatures":[{"name":"watch","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Watches this directory for changes to its contents or the directory itself.\n\nEvents are emitted when files or subdirectories are created, modified, deleted, or renamed\nwithin this directory. On iOS, child changes are surfaced as a coarse-grained "},{"kind":"code","text":"`modified`"},{"kind":"text","text":" event\non the directory itself, so filtering for child-level "},{"kind":"code","text":"`created`"},{"kind":"text","text":", "},{"kind":"code","text":"`deleted`"},{"kind":"text","text":", or "},{"kind":"code","text":"`renamed`"},{"kind":"text","text":" events\nis not reliable. The watcher automatically stops when the directory is deleted or renamed.\nTo stop watching manually, call "},{"kind":"code","text":"`remove()`"},{"kind":"text","text":" on the returned subscription."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A subscription handle. Call "},{"kind":"code","text":"`remove()`"},{"kind":"text","text":" to stop watching."}]},{"tag":"@example","content":[{"kind":"code","text":"```ts\nconst cacheDir = new Directory(Paths.cache);\nconst subscription = cacheDir.watch((event) => {\n console.log(`${event.type}: ${event.target.uri}`);\n});\n\n// Later, stop watching:\nsubscription.remove();\n```"}]}]},"parameters":[{"name":"callback","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"Invoked when a change is detected. Receives a "},{"kind":"code","text":"`WatchEvent`"},{"kind":"text","text":" describing what changed."}]},"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"signatures":[{"name":"__type","variant":"signature","kind":4096,"parameters":[{"name":"event","variant":"param","kind":32768,"type":{"type":"reference","typeArguments":[{"type":"union","types":[{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}],"name":"WatchEvent","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"}}]}}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Configuration for debouncing and filtering events."}]},"type":{"type":"reference","name":"WatchOptions","package":"expo-file-system"}}],"type":{"type":"reference","name":"WatchSubscription","package":"expo-file-system"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.watch","package":"expo-file-system"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.watch","package":"expo-file-system"}}],"extendedTypes":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.ts","qualifiedName":"ExpoFileSystemModule.FileSystemDirectory"},"name":"FileSystemDirectory","package":"expo-file-system","qualifiedName":"ExpoFileSystemModule.FileSystemDirectory"}]},{"name":"DownloadTask","variant":"declaration","kind":128,"comment":{"summary":[{"kind":"text","text":"Represents a download task with pause/resume support and progress tracking."}]},"children":[{"name":"constructor","variant":"declaration","kind":512,"signatures":[{"name":"DownloadTask","variant":"signature","kind":16384,"parameters":[{"name":"url","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"destination","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","name":"DownloadTaskOptions","package":"expo-file-system"}}],"type":{"type":"reference","name":"DownloadTask","package":"expo-file-system"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.constructor","package":"expo-file-system"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.constructor","package":"expo-file-system"}},{"name":"state","variant":"declaration","kind":262144,"getSignature":{"name":"state","variant":"signature","kind":524288,"type":{"type":"union","types":[{"type":"literal","value":"idle"},{"type":"literal","value":"active"},{"type":"literal","value":"paused"},{"type":"literal","value":"completed"},{"type":"literal","value":"cancelled"},{"type":"literal","value":"error"}]}}},{"name":"addListener","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"addListener","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Adds a listener for the given event name."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}},{"name":"listener","variant":"param","kind":32768,"type":{"type":"indexedAccess","indexType":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true},"objectType":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.ts","qualifiedName":"DownloadTaskEvents"},"name":"DownloadTaskEvents","package":"expo-file-system"}}}],"type":{"type":"reference","target":{"packageName":"expo-modules-core","packagePath":"src/ts-declarations/EventEmitter.ts","qualifiedName":"EventSubscription"},"name":"EventSubscription","package":"expo-modules-core"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.addListener","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.addListener","package":"expo-modules-core"}},{"name":"cancel","variant":"declaration","kind":2048,"signatures":[{"name":"cancel","variant":"signature","kind":4096,"type":{"type":"intrinsic","name":"void"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.cancel"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.cancel"}},{"name":"downloadAsync","variant":"declaration","kind":2048,"signatures":[{"name":"downloadAsync","variant":"signature","kind":4096,"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"union","types":[{"type":"reference","name":"File","package":"expo-file-system"},{"type":"literal","value":null}]}],"name":"Promise","package":"typescript"}}]},{"name":"emit","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"emit","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Synchronously calls all the listeners attached to that specific event.\nThe event can include any number of arguments that will be passed to the listeners."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}},{"name":"args","variant":"param","kind":32768,"flags":{"isRest":true},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Parameters"},"typeArguments":[{"type":"indexedAccess","indexType":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true},"objectType":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.ts","qualifiedName":"DownloadTaskEvents"},"name":"DownloadTaskEvents","package":"expo-file-system"}}],"name":"Parameters","package":"typescript"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.emit","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.emit","package":"expo-modules-core"}},{"name":"listenerCount","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"listenerCount","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Returns a number of listeners added to the given event."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}}],"type":{"type":"intrinsic","name":"number"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.listenerCount","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.listenerCount","package":"expo-modules-core"}},{"name":"pause","variant":"declaration","kind":2048,"signatures":[{"name":"pause","variant":"signature","kind":4096,"type":{"type":"intrinsic","name":"void"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.pause"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.pause"}},{"name":"pauseAsync","variant":"declaration","kind":2048,"signatures":[{"name":"pauseAsync","variant":"signature","kind":4096,"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"}}]},{"name":"release","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"release","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A function that detaches the JS and native objects to let the native object deallocate\nbefore the JS object gets deallocated by the JS garbage collector. Any subsequent calls to native\nfunctions of the object will throw an error as it is no longer associated with its native counterpart.\n\nIn most cases, you should never need to use this function, except some specific performance-critical cases when\nmanual memory management makes sense and the native object is known to exclusively retain some native memory\n(such as binary data or image bitmap). Before calling this function, you should ensure that nothing else will use\nthis object later on. Shared objects created by React hooks are usually automatically released in the effect's cleanup phase,\nfor example: "},{"kind":"code","text":"`useVideoPlayer()`"},{"kind":"text","text":" from "},{"kind":"code","text":"`expo-video`"},{"kind":"text","text":" and "},{"kind":"code","text":"`useImage()`"},{"kind":"text","text":" from "},{"kind":"code","text":"`expo-image`"},{"kind":"text","text":"."}]},"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.release","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.release","package":"expo-modules-core"}},{"name":"removeAllListeners","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"removeAllListeners","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Removes all listeners for the given event name."}]},"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"literal","value":"progress"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.removeAllListeners","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.removeAllListeners","package":"expo-modules-core"}},{"name":"removeListener","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"removeListener","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Removes a listener for the given event name."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}},{"name":"listener","variant":"param","kind":32768,"type":{"type":"indexedAccess","indexType":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true},"objectType":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.ts","qualifiedName":"DownloadTaskEvents"},"name":"DownloadTaskEvents","package":"expo-file-system"}}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.removeListener","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.removeListener","package":"expo-modules-core"}},{"name":"resume","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"resume","variant":"signature","kind":4096,"flags":{"isInherited":true},"parameters":[{"name":"url","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"to","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"Directory"},"name":"Directory","package":"expo-file-system"}]}},{"name":"resumeData","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Record"},"typeArguments":[{"type":"intrinsic","name":"string"},{"type":"intrinsic","name":"any"}],"name":"Record","package":"typescript"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"literal","value":null}]}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.resume","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.resume","package":"expo-file-system"}},{"name":"resumeAsync","variant":"declaration","kind":2048,"signatures":[{"name":"resumeAsync","variant":"signature","kind":4096,"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"union","types":[{"type":"reference","name":"File","package":"expo-file-system"},{"type":"literal","value":null}]}],"name":"Promise","package":"typescript"}}]},{"name":"savable","variant":"declaration","kind":2048,"signatures":[{"name":"savable","variant":"signature","kind":4096,"type":{"type":"reference","name":"DownloadPauseState","package":"expo-file-system"}}]},{"name":"start","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"start","variant":"signature","kind":4096,"flags":{"isInherited":true},"parameters":[{"name":"url","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"to","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"Directory"},"name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Record"},"typeArguments":[{"type":"intrinsic","name":"string"},{"type":"intrinsic","name":"any"}],"name":"Record","package":"typescript"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"literal","value":null}]}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.start","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.start","package":"expo-file-system"}},{"name":"startObserving","variant":"declaration","kind":2048,"flags":{"isOptional":true,"isInherited":true},"signatures":[{"name":"startObserving","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Function that is automatically invoked when the first listener for an event with the given name is added.\nOverride it in a subclass to perform some additional setup once the event started being observed."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.startObserving","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.startObserving","package":"expo-modules-core"}},{"name":"stopObserving","variant":"declaration","kind":2048,"flags":{"isOptional":true,"isInherited":true},"signatures":[{"name":"stopObserving","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Function that is automatically invoked when the last listener for an event with the given name is removed.\nOverride it in a subclass to perform some additional cleanup once the event is no longer observed."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.stopObserving","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.stopObserving","package":"expo-modules-core"}},{"name":"fromSavable","variant":"declaration","kind":2048,"flags":{"isStatic":true},"signatures":[{"name":"fromSavable","variant":"signature","kind":4096,"parameters":[{"name":"state","variant":"param","kind":32768,"type":{"type":"reference","name":"DownloadPauseState","package":"expo-file-system"}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","name":"DownloadTaskOptions","package":"expo-file-system"}}],"type":{"type":"reference","name":"DownloadTask","package":"expo-file-system"}}]}],"extendedTypes":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.ts","qualifiedName":"ExpoFileSystemModule.FileSystemDownloadTask"},"name":"FileSystemDownloadTask","package":"expo-file-system","qualifiedName":"ExpoFileSystemModule.FileSystemDownloadTask"}]},{"name":"File","variant":"declaration","kind":128,"comment":{"summary":[{"kind":"text","text":"Represents a file on the filesystem.\n\nA "},{"kind":"code","text":"`File`"},{"kind":"text","text":" instance can be created for any path, and does not need to exist on the filesystem during creation.\n\nThe constructor accepts an array of strings that are joined to create the file URI. The first argument can also be a "},{"kind":"code","text":"`Directory`"},{"kind":"text","text":" instance (like "},{"kind":"code","text":"`Paths.cache`"},{"kind":"text","text":") or a "},{"kind":"code","text":"`File`"},{"kind":"text","text":" instance (which creates a new reference to the same file)."}],"blockTags":[{"tag":"@example","content":[{"kind":"code","text":"```ts\nconst file = new File(Paths.cache, \"subdirName\", \"file.txt\");\n```"}]}]},"children":[{"name":"constructor","variant":"declaration","kind":512,"signatures":[{"name":"File","variant":"signature","kind":16384,"comment":{"summary":[{"kind":"text","text":"Creates an instance of a file. It can be created for any path, and does not need to exist on the filesystem during creation.\n\nThe constructor accepts an array of strings that are joined to create the file URI. The first argument can also be a "},{"kind":"code","text":"`Directory`"},{"kind":"text","text":" instance (like "},{"kind":"code","text":"`Paths.cache`"},{"kind":"text","text":") or a "},{"kind":"code","text":"`File`"},{"kind":"text","text":" instance (which creates a new reference to the same file)."}],"blockTags":[{"tag":"@example","content":[{"kind":"code","text":"```ts\nconst file = new File(Paths.cache, \"subdirName\", \"file.txt\");\n```"}]}]},"parameters":[{"name":"uris","variant":"param","kind":32768,"flags":{"isRest":true},"comment":{"summary":[{"kind":"text","text":"An array of: "},{"kind":"code","text":"`file:///`"},{"kind":"text","text":" string URIs, "},{"kind":"code","text":"`File`"},{"kind":"text","text":" instances, and "},{"kind":"code","text":"`Directory`"},{"kind":"text","text":" instances representing an arbitrary location on the file system."}]},"type":{"type":"array","elementType":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}}}],"type":{"type":"reference","name":"File","package":"expo-file-system"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.constructor","package":"expo-file-system"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.constructor","package":"expo-file-system"}},{"name":"contentUri","variant":"declaration","kind":1024,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A content URI to the file that can be shared to external applications."}],"blockTags":[{"tag":"@platform","content":[{"kind":"text","text":"android"}]}]},"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.contentUri"}},{"name":"creationTime","variant":"declaration","kind":1024,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A creation time of the file expressed in milliseconds since the epoch. Returns a "},{"kind":"code","text":"`null`"},{"kind":"text","text":" if the file does not exist, cannot be read or the Android version is earlier than API 26."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"number"},{"type":"literal","value":null}]},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.creationTime"}},{"name":"exists","variant":"declaration","kind":1024,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A boolean representing if a file exists. "},{"kind":"code","text":"`true`"},{"kind":"text","text":" if the file exists, "},{"kind":"code","text":"`false`"},{"kind":"text","text":" otherwise.\nAlso, "},{"kind":"code","text":"`false`"},{"kind":"text","text":" if the application does not have read access to the file."}]},"type":{"type":"intrinsic","name":"boolean"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.exists"}},{"name":"lastModified","variant":"declaration","kind":1024,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A last modification time of the file expressed in milliseconds since the epoch. Returns a "},{"kind":"code","text":"`null`"},{"kind":"text","text":" if the file does not exist, or if it cannot be read."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"number"},{"type":"literal","value":null}]},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.lastModified"}},{"name":"md5","variant":"declaration","kind":1024,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A md5 hash of the file. Null if the file does not exist, or it cannot be read."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"literal","value":null}]},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.md5"}},{"name":"modificationTime","variant":"declaration","kind":1024,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A last modification time of the file expressed in milliseconds since the epoch. Returns a "},{"kind":"code","text":"`null`"},{"kind":"text","text":" if the file does not exist, or if it cannot be read."}],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"In favor of "},{"kind":"code","text":"`lastModified`"},{"kind":"text","text":" to be more in line with web ["},{"kind":"code","text":"`File`"},{"kind":"text","text":"](https://developer.mozilla.org/en-US/docs/Web/API/File)"}]}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"number"},{"type":"literal","value":null}]},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.modificationTime"}},{"name":"size","variant":"declaration","kind":1024,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A size of the file in bytes. 0 if the file does not exist, or it cannot be read."}]},"type":{"type":"intrinsic","name":"number"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.size"},"implementationOf":{"type":"reference","name":"Blob.size"}},{"name":"type","variant":"declaration","kind":1024,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A mime type of the file. An empty string if the file does not exist, or it cannot be read."}]},"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.type"},"implementationOf":{"type":"reference","name":"Blob.type"}},{"name":"downloadFileAsync","variant":"declaration","kind":1024,"flags":{"isStatic":true},"comment":{"summary":[{"kind":"text","text":"A static method that downloads a file from the network.\n\nOn Android, the response body streams directly into the target file. If the download fails after\nit starts, a partially written file may remain at the destination. On iOS, the download first\ncompletes in a temporary location and the file is moved into place only after success, so no\nfile is left behind when the request fails."}],"blockTags":[{"tag":"@example","content":[{"kind":"code","text":"```ts\nconst file = await File.downloadFileAsync(\"https://example.com/image.png\", new Directory(Paths.document));\n```"}]}]},"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"signatures":[{"name":"__type","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A promise that resolves to the downloaded file. When the server responds with\na non-2xx HTTP status, the promise rejects with an "},{"kind":"code","text":"`UnableToDownload`"},{"kind":"text","text":" error whose\nmessage includes the status code. No file is created in that scenario."}]}]},"parameters":[{"name":"url","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The URL of the file to download."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"destination","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The destination directory or file. If a directory is provided, the resulting filename will be determined based on the response headers."}]},"type":{"type":"union","types":[{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Download options. When the destination already contains a file, the promise rejects with a "},{"kind":"code","text":"`DestinationAlreadyExists`"},{"kind":"text","text":" error unless "},{"kind":"code","text":"`options.idempotent`"},{"kind":"text","text":" is set to "},{"kind":"code","text":"`true`"},{"kind":"text","text":". With "},{"kind":"code","text":"`idempotent: true`"},{"kind":"text","text":", the download overwrites the existing file instead of failing."}]},"type":{"type":"reference","name":"DownloadOptions","package":"expo-file-system"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","name":"File","package":"expo-file-system"}],"name":"Promise","package":"typescript"}}]}},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.downloadFileAsync"}},{"name":"extension","variant":"declaration","kind":262144,"getSignature":{"name":"extension","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"File extension."}],"blockTags":[{"tag":"@example","name":"'.png'","content":[]}]},"type":{"type":"intrinsic","name":"string"}}},{"name":"name","variant":"declaration","kind":262144,"getSignature":{"name":"name","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"File name. Includes the extension."}]},"type":{"type":"intrinsic","name":"string"}}},{"name":"parentDirectory","variant":"declaration","kind":262144,"getSignature":{"name":"parentDirectory","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"Directory containing the file."}]},"type":{"type":"reference","name":"Directory","package":"expo-file-system"}}},{"name":"uri","variant":"declaration","kind":262144,"flags":{"isInherited":true},"getSignature":{"name":"uri","variant":"signature","kind":524288,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Represents the file URI. The field is read-only, but it may change as a result of calling some methods such as "},{"kind":"code","text":"`move`"},{"kind":"text","text":"."}]},"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.uri"}},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.uri"}},{"name":"arrayBuffer","variant":"declaration","kind":2048,"signatures":[{"name":"arrayBuffer","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"The **"},{"kind":"code","text":"`arrayBuffer()`"},{"kind":"text","text":"** method of the Blob interface returns a Promise that resolves with the contents of the blob as binary data contained in an ArrayBuffer.\n\n[MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/arrayBuffer)"}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"ArrayBuffer"},"name":"ArrayBuffer","package":"typescript"}],"name":"Promise","package":"typescript"},"implementationOf":{"type":"reference","name":"Blob.arrayBuffer"}}],"implementationOf":{"type":"reference","name":"Blob.arrayBuffer"}},{"name":"base64","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"base64","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Retrieves content of the file as base64."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A promise that resolves with the contents of the file as a base64 string."}]}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"string"}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.base64"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.base64"}},{"name":"base64Sync","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"base64Sync","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Retrieves content of the file as base64."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"The contents of the file as a base64 string."}]}]},"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.base64Sync"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.base64Sync"}},{"name":"bytes","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"bytes","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Retrieves byte content of the entire file."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A promise that resolves with the contents of the file as a "},{"kind":"code","text":"`Uint8Array`"},{"kind":"text","text":"."}]}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Uint8Array"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"ArrayBuffer"},"name":"ArrayBuffer","package":"typescript"}],"name":"Uint8Array","package":"typescript"}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.bytes"},"implementationOf":{"type":"reference","name":"Blob.bytes"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.bytes"},"implementationOf":{"type":"reference","name":"Blob.bytes"}},{"name":"bytesSync","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"bytesSync","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Retrieves byte content of the entire file."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"The contents of the file as a "},{"kind":"code","text":"`Uint8Array`"},{"kind":"text","text":"."}]}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Uint8Array"},"name":"Uint8Array","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.bytesSync"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.bytesSync"}},{"name":"copy","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"copy","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Copies a file."}]},"parameters":[{"name":"destination","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"Directory"},"name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"RelocationOptions"},"name":"RelocationOptions","package":"expo-file-system"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.copy","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.copy","package":"expo-file-system"}},{"name":"copySync","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"copySync","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Copies a file synchronously."}]},"parameters":[{"name":"destination","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"Directory"},"name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"RelocationOptions"},"name":"RelocationOptions","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.copySync","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.copySync","package":"expo-file-system"}},{"name":"create","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"create","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Creates a file."}],"blockTags":[{"tag":"@throws","content":[{"kind":"text","text":"Error if the containing folder doesn't exist, the application has no read access to it or the file (or directory with the same path) already exists."}]}]},"parameters":[{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","name":"FileCreateOptions","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.create"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.create"}},{"name":"createUploadTask","variant":"declaration","kind":2048,"signatures":[{"name":"createUploadTask","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Creates an upload task for uploading this file with progress tracking."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"An "},{"kind":"code","text":"`UploadTask`"},{"kind":"text","text":" instance that can be used to control the upload."}]},{"tag":"@example","content":[{"kind":"code","text":"```ts\nconst file = new File(Paths.document, 'photo.jpg');\nconst uploadTask = file.createUploadTask(url, {\n uploadType: UploadType.MULTIPART,\n headers: { Authorization: 'Bearer token' },\n onProgress: ({ bytesSent, totalBytes }) => {\n console.log(`Uploaded ${bytesSent} of ${totalBytes} bytes`);\n }\n});\nconst result = await uploadTask.uploadAsync();\nconsole.log('Upload status:', result.status);\n```"}]}]},"parameters":[{"name":"url","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The URL to upload the file to."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Upload options including upload type, headers, progress callback, and abort signal."}]},"type":{"type":"reference","name":"UploadOptions","package":"expo-file-system"}}],"type":{"type":"reference","name":"UploadTask","package":"expo-file-system"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.createUploadTask"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.createUploadTask"}},{"name":"delete","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"delete","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Deletes a file."}],"blockTags":[{"tag":"@throws","content":[{"kind":"text","text":"Error if the directory does not exist or cannot be deleted."}]}]},"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.delete"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.delete"}},{"name":"info","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"info","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Retrieves an object containing properties of a file"}],"blockTags":[{"tag":"@throws","content":[{"kind":"text","text":"Error If the application does not have read access to the file, or if the path does not point to a file (for example, it points to a directory)."}]},{"tag":"@returns","content":[{"kind":"text","text":"An object with file metadata (for example, size, creation date, and so on)."}]}]},"parameters":[{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","name":"InfoOptions","package":"expo-file-system"}}],"type":{"type":"reference","name":"FileInfo","package":"expo-file-system"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.info"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.info"}},{"name":"move","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"move","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Moves a directory. Updates the "},{"kind":"code","text":"`uri`"},{"kind":"text","text":" property that now points to the new location."}]},"parameters":[{"name":"destination","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"Directory"},"name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"RelocationOptions"},"name":"RelocationOptions","package":"expo-file-system"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.move","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.move","package":"expo-file-system"}},{"name":"moveSync","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"moveSync","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Moves a file synchronously. Updates the "},{"kind":"code","text":"`uri`"},{"kind":"text","text":" property that now points to the new location."}]},"parameters":[{"name":"destination","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"Directory"},"name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"RelocationOptions"},"name":"RelocationOptions","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.moveSync","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.moveSync","package":"expo-file-system"}},{"name":"open","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"open","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Returns A "},{"kind":"code","text":"`FileHandle`"},{"kind":"text","text":" object that can be used to read and write data to the file."}],"blockTags":[{"tag":"@throws","content":[{"kind":"text","text":"Error if the file does not exist or cannot be opened."}]}]},"parameters":[{"name":"mode","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The "},{"kind":"inline-tag","tag":"@link","text":"FileMode"},{"kind":"text","text":" to use.\n- On **Android**, SAF "},{"kind":"code","text":"`content://`"},{"kind":"text","text":" URIs do not support "},{"kind":"code","text":"`ReadWrite`"},{"kind":"text","text":" mode.\n- **Defaults**:\n - For SAF "},{"kind":"code","text":"`content://`"},{"kind":"text","text":" URIs, the default is "},{"kind":"code","text":"`FileMode.ReadOnly`"},{"kind":"text","text":".\n - For standard "},{"kind":"code","text":"`file://`"},{"kind":"text","text":" URIs, the default is "},{"kind":"code","text":"`FileMode.ReadWrite`"},{"kind":"text","text":"."}]},"type":{"type":"reference","name":"FileMode","package":"expo-file-system"}}],"type":{"type":"reference","name":"FileHandle","package":"expo-file-system"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.open"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.open"}},{"name":"readableStream","variant":"declaration","kind":2048,"signatures":[{"name":"readableStream","variant":"signature","kind":4096,"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.dom.d.ts","qualifiedName":"ReadableStream"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Uint8Array"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"ArrayBuffer"},"name":"ArrayBuffer","package":"typescript"}],"name":"Uint8Array","package":"typescript"}],"name":"ReadableStream","package":"typescript"}}]},{"name":"rename","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"rename","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Renames a file."}]},"parameters":[{"name":"newName","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.rename"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.rename"}},{"name":"slice","variant":"declaration","kind":2048,"signatures":[{"name":"slice","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"The **"},{"kind":"code","text":"`slice()`"},{"kind":"text","text":"** method of the Blob interface creates and returns a new "},{"kind":"code","text":"`Blob`"},{"kind":"text","text":" object which contains data from a subset of the blob on which it's called.\n\n[MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/slice)"}]},"parameters":[{"name":"start","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"intrinsic","name":"number"}},{"name":"end","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"intrinsic","name":"number"}},{"name":"contentType","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.dom.d.ts","qualifiedName":"Blob"},"name":"Blob","package":"typescript"},"implementationOf":{"type":"reference","name":"Blob.slice"}}],"implementationOf":{"type":"reference","name":"Blob.slice"}},{"name":"stream","variant":"declaration","kind":2048,"signatures":[{"name":"stream","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"The **"},{"kind":"code","text":"`stream()`"},{"kind":"text","text":"** method of the Blob interface returns a ReadableStream which upon reading returns the data contained within the "},{"kind":"code","text":"`Blob`"},{"kind":"text","text":".\n\n[MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/stream)"}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.dom.d.ts","qualifiedName":"ReadableStream"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Uint8Array"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"ArrayBuffer"},"name":"ArrayBuffer","package":"typescript"}],"name":"Uint8Array","package":"typescript"}],"name":"ReadableStream","package":"typescript"},"implementationOf":{"type":"reference","name":"Blob.stream"}}],"implementationOf":{"type":"reference","name":"Blob.stream"}},{"name":"text","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"text","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Retrieves text from the file."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A promise that resolves with the contents of the file as string."}]}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"string"}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.text"},"implementationOf":{"type":"reference","name":"Blob.text"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.text"},"implementationOf":{"type":"reference","name":"Blob.text"}},{"name":"textSync","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"textSync","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Retrieves text from the file."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"The contents of the file as string."}]}]},"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.textSync"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.textSync"}},{"name":"upload","variant":"declaration","kind":2048,"signatures":[{"name":"upload","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Uploads this file to the network.\n\nThe promise resolves with the HTTP response metadata and body for any completed response,\nincluding non-2xx status codes. It rejects only for local file errors, transport failures,\nor cancellation."}]},"parameters":[{"name":"url","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The URL to upload the file to."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Upload options."}]},"type":{"type":"reference","name":"UploadOptions","package":"expo-file-system"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","name":"UploadResult","package":"expo-file-system"}],"name":"Promise","package":"typescript"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.upload"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.upload"}},{"name":"watch","variant":"declaration","kind":2048,"signatures":[{"name":"watch","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Watches this file for changes on the filesystem.\n\nThe watcher automatically stops when the file is deleted or renamed. To stop watching manually,\ncall "},{"kind":"code","text":"`remove()`"},{"kind":"text","text":" on the returned subscription."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A subscription handle. Call "},{"kind":"code","text":"`remove()`"},{"kind":"text","text":" to stop watching."}]},{"tag":"@example","content":[{"kind":"code","text":"```ts\nconst file = new File(Paths.cache, 'data.json');\nconst subscription = file.watch((event) => {\n console.log(`File ${event.type}`);\n});\n\n// Later, stop watching:\nsubscription.remove();\n```"}]}]},"parameters":[{"name":"callback","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"Invoked when a change is detected. Receives a "},{"kind":"code","text":"`WatchEvent`"},{"kind":"text","text":" describing what changed."}]},"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"signatures":[{"name":"__type","variant":"signature","kind":4096,"parameters":[{"name":"event","variant":"param","kind":32768,"type":{"type":"reference","typeArguments":[{"type":"reference","name":"File","package":"expo-file-system"}],"name":"WatchEvent","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"}}]}}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Configuration for debouncing and filtering events."}]},"type":{"type":"reference","name":"WatchOptions","package":"expo-file-system"}}],"type":{"type":"reference","name":"WatchSubscription","package":"expo-file-system"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.watch","package":"expo-file-system"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.watch","package":"expo-file-system"}},{"name":"writableStream","variant":"declaration","kind":2048,"signatures":[{"name":"writableStream","variant":"signature","kind":4096,"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.dom.d.ts","qualifiedName":"WritableStream"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Uint8Array"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"ArrayBufferLike"},"name":"ArrayBufferLike","package":"typescript"}],"name":"Uint8Array","package":"typescript"}],"name":"WritableStream","package":"typescript"}}]},{"name":"write","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"write","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Writes content to the file."}]},"parameters":[{"name":"content","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The content to write into the file."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Uint8Array"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"ArrayBufferLike"},"name":"ArrayBufferLike","package":"typescript"}],"name":"Uint8Array","package":"typescript"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","name":"FileWriteOptions","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.write","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.write","package":"expo-file-system"}},{"name":"createDownloadTask","variant":"declaration","kind":2048,"flags":{"isStatic":true},"signatures":[{"name":"createDownloadTask","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Creates a download task for downloading a file with pause/resume support."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A "},{"kind":"code","text":"`DownloadTask`"},{"kind":"text","text":" instance that can be used to control the download."}]},{"tag":"@example","content":[{"kind":"code","text":"```ts\nconst dest = new File(Paths.document, 'video.mp4');\nconst downloadTask = File.createDownloadTask(url, dest, {\n onProgress: ({ bytesWritten, totalBytes }) => {\n console.log(`Downloaded ${bytesWritten} of ${totalBytes} bytes`);\n }\n});\nconst file = await downloadTask.downloadAsync();\n```"}]}]},"parameters":[{"name":"url","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The URL of the file to download."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"destination","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The destination directory or file."}]},"type":{"type":"union","types":[{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Download options including headers, progress callback, and abort signal."}]},"type":{"type":"reference","name":"DownloadTaskOptions","package":"expo-file-system"}}],"type":{"type":"reference","name":"DownloadTask","package":"expo-file-system"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.createDownloadTask"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.createDownloadTask"}},{"name":"pickFileAsync","variant":"declaration","kind":2048,"flags":{"isStatic":true,"isInherited":true},"signatures":[{"name":"pickFileAsync","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"An overload of the "},{"kind":"code","text":"`pickFileAsync`"},{"kind":"text","text":" method, which picks and returns a single "},{"kind":"code","text":"`File`"},{"kind":"text","text":".\nThis overload requires options to have "},{"kind":"code","text":"`multipleFiles`"},{"kind":"text","text":" flag be "},{"kind":"code","text":"`undefined`"},{"kind":"text","text":" or "},{"kind":"code","text":"`false`"},{"kind":"text","text":"."}]},"parameters":[{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"options"}]},"type":{"type":"reference","name":"PickSingleFileOptions","package":"expo-file-system"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","name":"PickSingleFileResult","package":"expo-file-system"}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.pickFileAsync"}},{"name":"pickFileAsync","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"An overload of the "},{"kind":"code","text":"`pickFileAsync`"},{"kind":"text","text":" method, which picks and returns a list of "},{"kind":"code","text":"`File`"},{"kind":"text","text":"'s.\nThis overload requires options to have "},{"kind":"code","text":"`multipleFiles`"},{"kind":"text","text":" flag be "},{"kind":"code","text":"`true`"},{"kind":"text","text":"."}]},"parameters":[{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"options"}]},"type":{"type":"reference","name":"PickMultipleFilesOptions","package":"expo-file-system"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","name":"PickMultipleFilesResult","package":"expo-file-system"}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.pickFileAsync"}},{"name":"pickFileAsync","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A static method that opens a file picker to select a single file of specified type. On iOS, it returns a temporary copy of the file leaving the original file untouched.\n\nSelecting multiple files is not supported yet."}],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`pickFileAsync({initialUri, mimeTypes: mimeType})`"},{"kind":"text","text":" instead."}]},{"tag":"@returns","content":[{"kind":"text","text":"A "},{"kind":"code","text":"`File`"},{"kind":"text","text":" instance or an array of "},{"kind":"code","text":"`File`"},{"kind":"text","text":" instances."}]}]},"parameters":[{"name":"initialUri","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"An optional URI pointing to an initial folder on which the file picker is opened."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"mimeType","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"A mime type that is used to filter out files that can be picked out."}]},"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"array","elementType":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"}}]}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.pickFileAsync"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.pickFileAsync"}}],"extendedTypes":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.ts","qualifiedName":"ExpoFileSystemModule.FileSystemFile"},"name":"FileSystemFile","package":"expo-file-system","qualifiedName":"ExpoFileSystemModule.FileSystemFile"}],"implementedTypes":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.dom.d.ts","qualifiedName":"Blob"},"name":"Blob","package":"typescript"}]},{"name":"Paths","variant":"declaration","kind":128,"children":[{"name":"constructor","variant":"declaration","kind":512,"signatures":[{"name":"Paths","variant":"signature","kind":16384,"type":{"type":"reference","name":"Paths","package":"expo-file-system"},"inheritedFrom":{"type":"reference","name":"PathUtilities.constructor","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"PathUtilities.constructor","package":"expo-file-system"}},{"name":"appleSharedContainers","variant":"declaration","kind":262144,"flags":{"isStatic":true},"getSignature":{"name":"appleSharedContainers","variant":"signature","kind":524288,"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Record"},"typeArguments":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"Directory","package":"expo-file-system"}],"name":"Record","package":"typescript"}}},{"name":"availableDiskSpace","variant":"declaration","kind":262144,"flags":{"isStatic":true},"getSignature":{"name":"availableDiskSpace","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"A property that represents the available space on device's internal storage, represented in bytes."}]},"type":{"type":"intrinsic","name":"number"}}},{"name":"bundle","variant":"declaration","kind":262144,"flags":{"isStatic":true},"getSignature":{"name":"bundle","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"A property containing the bundle directory – the directory where assets bundled with the application are stored."}]},"type":{"type":"reference","name":"Directory","package":"expo-file-system"}}},{"name":"cache","variant":"declaration","kind":262144,"flags":{"isStatic":true},"getSignature":{"name":"cache","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"A property containing the cache directory – a place to store files that can be deleted by the system when the device runs low on storage."}]},"type":{"type":"reference","name":"Directory","package":"expo-file-system"}}},{"name":"document","variant":"declaration","kind":262144,"flags":{"isStatic":true},"getSignature":{"name":"document","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"A property containing the document directory – a place to store files that are safe from being deleted by the system."}]},"type":{"type":"reference","name":"Directory","package":"expo-file-system"}}},{"name":"totalDiskSpace","variant":"declaration","kind":262144,"flags":{"isStatic":true},"getSignature":{"name":"totalDiskSpace","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"A property that represents the total space on device's internal storage, represented in bytes."}]},"type":{"type":"intrinsic","name":"number"}}},{"name":"basename","variant":"declaration","kind":2048,"flags":{"isStatic":true,"isInherited":true},"signatures":[{"name":"basename","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Returns the base name of a path."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A string representing the base name."}]}]},"parameters":[{"name":"path","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The path to get the base name from."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}},{"name":"ext","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"An optional file extension."}]},"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"PathUtilities.basename"}}],"inheritedFrom":{"type":"reference","name":"PathUtilities.basename"}},{"name":"dirname","variant":"declaration","kind":2048,"flags":{"isStatic":true,"isInherited":true},"signatures":[{"name":"dirname","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Returns the directory name of a path."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A string representing the directory name."}]}]},"parameters":[{"name":"path","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The path to get the directory name from."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}}],"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"PathUtilities.dirname"}}],"inheritedFrom":{"type":"reference","name":"PathUtilities.dirname"}},{"name":"extname","variant":"declaration","kind":2048,"flags":{"isStatic":true,"isInherited":true},"signatures":[{"name":"extname","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Returns the extension of a path."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A string representing the extension."}]}]},"parameters":[{"name":"path","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The path to get the extension from."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}}],"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"PathUtilities.extname"}}],"inheritedFrom":{"type":"reference","name":"PathUtilities.extname"}},{"name":"info","variant":"declaration","kind":2048,"flags":{"isStatic":true},"signatures":[{"name":"info","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Returns an object that indicates if the specified path represents a directory."}]},"parameters":[{"name":"uris","variant":"param","kind":32768,"flags":{"isRest":true},"type":{"type":"array","elementType":{"type":"intrinsic","name":"string"}}}],"type":{"type":"reference","name":"PathInfo","package":"expo-file-system"}}]},{"name":"isAbsolute","variant":"declaration","kind":2048,"flags":{"isStatic":true,"isInherited":true},"signatures":[{"name":"isAbsolute","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Checks if a path is absolute."}],"blockTags":[{"tag":"@returns","content":[{"kind":"code","text":"`true`"},{"kind":"text","text":" if the path is absolute, "},{"kind":"code","text":"`false`"},{"kind":"text","text":" otherwise."}]}]},"parameters":[{"name":"path","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The path to check."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}}],"type":{"type":"intrinsic","name":"boolean"},"inheritedFrom":{"type":"reference","name":"PathUtilities.isAbsolute"}}],"inheritedFrom":{"type":"reference","name":"PathUtilities.isAbsolute"}},{"name":"join","variant":"declaration","kind":2048,"flags":{"isStatic":true,"isInherited":true},"signatures":[{"name":"join","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Joins path segments into a single path."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A string representing the joined path."}]}]},"parameters":[{"name":"paths","variant":"param","kind":32768,"flags":{"isRest":true},"comment":{"summary":[{"kind":"text","text":"An array of path segments."}]},"type":{"type":"array","elementType":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}}}],"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"PathUtilities.join"}}],"inheritedFrom":{"type":"reference","name":"PathUtilities.join"}},{"name":"normalize","variant":"declaration","kind":2048,"flags":{"isStatic":true,"isInherited":true},"signatures":[{"name":"normalize","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Normalizes a path."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A string representing the normalized path."}]}]},"parameters":[{"name":"path","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The path to normalize."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}}],"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"PathUtilities.normalize"}}],"inheritedFrom":{"type":"reference","name":"PathUtilities.normalize"}},{"name":"parse","variant":"declaration","kind":2048,"flags":{"isStatic":true,"isInherited":true},"signatures":[{"name":"parse","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Parses a path into its components."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"An object containing the parsed path components."}]}]},"parameters":[{"name":"path","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The path to parse."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}}],"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"children":[{"name":"base","variant":"declaration","kind":1024,"type":{"type":"intrinsic","name":"string"}},{"name":"dir","variant":"declaration","kind":1024,"type":{"type":"intrinsic","name":"string"}},{"name":"ext","variant":"declaration","kind":1024,"type":{"type":"intrinsic","name":"string"}},{"name":"name","variant":"declaration","kind":1024,"type":{"type":"intrinsic","name":"string"}},{"name":"root","variant":"declaration","kind":1024,"type":{"type":"intrinsic","name":"string"}}]}},"inheritedFrom":{"type":"reference","name":"PathUtilities.parse"}}],"inheritedFrom":{"type":"reference","name":"PathUtilities.parse"}},{"name":"relative","variant":"declaration","kind":2048,"flags":{"isStatic":true,"isInherited":true},"signatures":[{"name":"relative","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Resolves a relative path to an absolute path."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A string representing the resolved path."}]}]},"parameters":[{"name":"from","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The base path."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}},{"name":"to","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The relative path."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}}],"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"PathUtilities.relative"}}],"inheritedFrom":{"type":"reference","name":"PathUtilities.relative"}}],"extendedTypes":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/pathUtilities/index.ts","qualifiedName":"PathUtilities"},"name":"PathUtilities","package":"expo-file-system"}]},{"name":"UploadTask","variant":"declaration","kind":128,"comment":{"summary":[{"kind":"text","text":"Represents an upload task with progress tracking and cancellation support."}]},"children":[{"name":"constructor","variant":"declaration","kind":512,"signatures":[{"name":"UploadTask","variant":"signature","kind":16384,"parameters":[{"name":"file","variant":"param","kind":32768,"type":{"type":"reference","name":"File","package":"expo-file-system"}},{"name":"url","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","name":"UploadOptions","package":"expo-file-system"}}],"type":{"type":"reference","name":"UploadTask","package":"expo-file-system"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.constructor","package":"expo-file-system"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.constructor","package":"expo-file-system"}},{"name":"state","variant":"declaration","kind":262144,"getSignature":{"name":"state","variant":"signature","kind":524288,"type":{"type":"reference","name":"UploadTaskState","package":"expo-file-system"}}},{"name":"addListener","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"addListener","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Adds a listener for the given event name."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}},{"name":"listener","variant":"param","kind":32768,"type":{"type":"indexedAccess","indexType":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true},"objectType":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.ts","qualifiedName":"UploadTaskEvents"},"name":"UploadTaskEvents","package":"expo-file-system"}}}],"type":{"type":"reference","target":{"packageName":"expo-modules-core","packagePath":"src/ts-declarations/EventEmitter.ts","qualifiedName":"EventSubscription"},"name":"EventSubscription","package":"expo-modules-core"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.addListener","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.addListener","package":"expo-modules-core"}},{"name":"cancel","variant":"declaration","kind":2048,"signatures":[{"name":"cancel","variant":"signature","kind":4096,"type":{"type":"intrinsic","name":"void"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.cancel"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.cancel"}},{"name":"emit","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"emit","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Synchronously calls all the listeners attached to that specific event.\nThe event can include any number of arguments that will be passed to the listeners."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}},{"name":"args","variant":"param","kind":32768,"flags":{"isRest":true},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Parameters"},"typeArguments":[{"type":"indexedAccess","indexType":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true},"objectType":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.ts","qualifiedName":"UploadTaskEvents"},"name":"UploadTaskEvents","package":"expo-file-system"}}],"name":"Parameters","package":"typescript"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.emit","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.emit","package":"expo-modules-core"}},{"name":"listenerCount","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"listenerCount","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Returns a number of listeners added to the given event."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}}],"type":{"type":"intrinsic","name":"number"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.listenerCount","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.listenerCount","package":"expo-modules-core"}},{"name":"release","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"release","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A function that detaches the JS and native objects to let the native object deallocate\nbefore the JS object gets deallocated by the JS garbage collector. Any subsequent calls to native\nfunctions of the object will throw an error as it is no longer associated with its native counterpart.\n\nIn most cases, you should never need to use this function, except some specific performance-critical cases when\nmanual memory management makes sense and the native object is known to exclusively retain some native memory\n(such as binary data or image bitmap). Before calling this function, you should ensure that nothing else will use\nthis object later on. Shared objects created by React hooks are usually automatically released in the effect's cleanup phase,\nfor example: "},{"kind":"code","text":"`useVideoPlayer()`"},{"kind":"text","text":" from "},{"kind":"code","text":"`expo-video`"},{"kind":"text","text":" and "},{"kind":"code","text":"`useImage()`"},{"kind":"text","text":" from "},{"kind":"code","text":"`expo-image`"},{"kind":"text","text":"."}]},"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.release","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.release","package":"expo-modules-core"}},{"name":"removeAllListeners","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"removeAllListeners","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Removes all listeners for the given event name."}]},"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"literal","value":"progress"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.removeAllListeners","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.removeAllListeners","package":"expo-modules-core"}},{"name":"removeListener","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"removeListener","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Removes a listener for the given event name."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}},{"name":"listener","variant":"param","kind":32768,"type":{"type":"indexedAccess","indexType":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true},"objectType":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.ts","qualifiedName":"UploadTaskEvents"},"name":"UploadTaskEvents","package":"expo-file-system"}}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.removeListener","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.removeListener","package":"expo-modules-core"}},{"name":"start","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"start","variant":"signature","kind":4096,"flags":{"isInherited":true},"parameters":[{"name":"url","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"file","variant":"param","kind":32768,"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"}},{"name":"options","variant":"param","kind":32768,"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Record"},"typeArguments":[{"type":"intrinsic","name":"string"},{"type":"intrinsic","name":"any"}],"name":"Record","package":"typescript"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","name":"UploadResult","package":"expo-file-system"}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.start"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.start"}},{"name":"startObserving","variant":"declaration","kind":2048,"flags":{"isOptional":true,"isInherited":true},"signatures":[{"name":"startObserving","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Function that is automatically invoked when the first listener for an event with the given name is added.\nOverride it in a subclass to perform some additional setup once the event started being observed."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.startObserving","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.startObserving","package":"expo-modules-core"}},{"name":"stopObserving","variant":"declaration","kind":2048,"flags":{"isOptional":true,"isInherited":true},"signatures":[{"name":"stopObserving","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Function that is automatically invoked when the last listener for an event with the given name is removed.\nOverride it in a subclass to perform some additional cleanup once the event is no longer observed."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.stopObserving","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.stopObserving","package":"expo-modules-core"}},{"name":"uploadAsync","variant":"declaration","kind":2048,"signatures":[{"name":"uploadAsync","variant":"signature","kind":4096,"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","name":"UploadResult","package":"expo-file-system"}],"name":"Promise","package":"typescript"}}]}],"extendedTypes":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.ts","qualifiedName":"ExpoFileSystemModule.FileSystemUploadTask"},"name":"FileSystemUploadTask","package":"expo-file-system","qualifiedName":"ExpoFileSystemModule.FileSystemUploadTask"}]},{"name":"FileHandle","variant":"declaration","kind":256,"children":[{"name":"offset","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"A property that indicates the current byte offset in the file. Calling "},{"kind":"code","text":"`readBytes`"},{"kind":"text","text":" or "},{"kind":"code","text":"`writeBytes`"},{"kind":"text","text":" will read or write a specified amount of bytes starting from this offset. The offset is incremented by the number of bytes read or written.\nThe offset can be set to any value within the file size. If the offset is set to a value greater than the file size, the next write operation will append data to the end of the file.\nNull if the file handle is closed."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"number"},{"type":"literal","value":null}]}},{"name":"size","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"A size of the file in bytes or "},{"kind":"code","text":"`null`"},{"kind":"text","text":" if the file handle is closed."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"number"},{"type":"literal","value":null}]}},{"name":"close","variant":"declaration","kind":2048,"signatures":[{"name":"close","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Closes the file handle. This allows the file to be deleted, moved or read by a different process. Subsequent calls to "},{"kind":"code","text":"`readBytes`"},{"kind":"text","text":" or "},{"kind":"code","text":"`writeBytes`"},{"kind":"text","text":" will throw an error."}]},"type":{"type":"intrinsic","name":"void"}}]},{"name":"readBytes","variant":"declaration","kind":2048,"signatures":[{"name":"readBytes","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Reads the specified amount of bytes from the file at the current offset. Max amount of bytes read at once is capped by ArrayBuffer max size (32 bit signed MAX_INT on Android and 64 bit on iOS), but you can read from a FileHandle multiple times."}]},"parameters":[{"name":"length","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The number of bytes to read."}]},"type":{"type":"intrinsic","name":"number"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Uint8Array"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"ArrayBuffer"},"name":"ArrayBuffer","package":"typescript"}],"name":"Uint8Array","package":"typescript"}}]},{"name":"writeBytes","variant":"declaration","kind":2048,"signatures":[{"name":"writeBytes","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Writes the specified bytes to the file at the current offset."}]},"parameters":[{"name":"bytes","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"A "},{"kind":"code","text":"`Uint8Array`"},{"kind":"text","text":" array containing bytes to write."}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Uint8Array"},"name":"Uint8Array","package":"typescript"}}],"type":{"type":"intrinsic","name":"void"}}]}]},{"name":"DirectoryCreateOptions","variant":"declaration","kind":2097152,"children":[{"name":"idempotent","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"This flag controls whether the "},{"kind":"code","text":"`create`"},{"kind":"text","text":" operation is idempotent\n(safe to call multiple times without error).\n\nIf "},{"kind":"code","text":"`true`"},{"kind":"text","text":", creating a file or directory that already exists will succeed silently.\nIf "},{"kind":"code","text":"`false`"},{"kind":"text","text":", an error will be thrown when the target already exists."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"false"}]}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"intermediates","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Whether to create intermediate directories if they do not exist."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"false"}]}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"overwrite","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Whether to overwrite the directory if it exists."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"false"}]}]},"type":{"type":"intrinsic","name":"boolean"}}]},{"name":"DirectoryInfo","variant":"declaration","kind":2097152,"children":[{"name":"creationTime","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"A creation time of the directory expressed in milliseconds since epoch. Returns null if the Android version is earlier than API 26."}]},"type":{"type":"intrinsic","name":"number"}},{"name":"exists","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Indicates whether the directory exists."}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"files","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"A list of file names contained within a directory."}]},"type":{"type":"array","elementType":{"type":"intrinsic","name":"string"}}},{"name":"modificationTime","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The last modification time of the directory expressed in milliseconds since epoch."}]},"type":{"type":"intrinsic","name":"number"}},{"name":"size","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The size of the file in bytes."}]},"type":{"type":"intrinsic","name":"number"}},{"name":"uri","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"A "},{"kind":"code","text":"`file://`"},{"kind":"text","text":" URI pointing to the directory."}]},"type":{"type":"intrinsic","name":"string"}}]},{"name":"DownloadOptions","variant":"declaration","kind":2097152,"children":[{"name":"headers","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The headers to send with the request."}]},"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"indexSignatures":[{"name":"__index","variant":"signature","kind":8192,"parameters":[{"name":"key","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"intrinsic","name":"string"}}]}}},{"name":"idempotent","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"This flag controls whether the "},{"kind":"code","text":"`download`"},{"kind":"text","text":" operation is idempotent\n(safe to call multiple times without error).\n\nIf "},{"kind":"code","text":"`true`"},{"kind":"text","text":", downloading a file that already exists overwrites the previous one.\nIf "},{"kind":"code","text":"`false`"},{"kind":"text","text":", an error is thrown when the target file already exists."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"false"}]}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"onProgress","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"A callback that is invoked with progress updates during the download."}]},"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"signatures":[{"name":"__type","variant":"signature","kind":4096,"parameters":[{"name":"data","variant":"param","kind":32768,"type":{"type":"reference","name":"DownloadProgress","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"}}]}}},{"name":"signal","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"An "},{"kind":"code","text":"`AbortSignal`"},{"kind":"text","text":" that can be used to cancel the download.\nWhen the signal is aborted, the download is cancelled and the promise rejects with an "},{"kind":"code","text":"`AbortError`"},{"kind":"text","text":"."}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.dom.d.ts","qualifiedName":"AbortSignal"},"name":"AbortSignal","package":"typescript"}}]},{"name":"DownloadPauseState","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Represents the state of a paused download that can be persisted and resumed later."}]},"children":[{"name":"fileUri","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The destination file or directory URI."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"headers","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Custom headers that were used for the download request."}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Record"},"typeArguments":[{"type":"intrinsic","name":"string"},{"type":"intrinsic","name":"string"}],"name":"Record","package":"typescript"}},{"name":"isDirectory","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Whether the destination is a directory. When "},{"kind":"code","text":"`true`"},{"kind":"text","text":", the filename is derived from the URL."}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"resumeData","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Platform-specific opaque resume data."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"url","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The URL of the download."}]},"type":{"type":"intrinsic","name":"string"}}]},{"name":"DownloadProgress","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Data provided to the "},{"kind":"code","text":"`onProgress`"},{"kind":"text","text":" callback during a file download."}]},"children":[{"name":"bytesWritten","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The number of bytes written so far."}]},"type":{"type":"intrinsic","name":"number"}},{"name":"totalBytes","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The total number of bytes expected to be downloaded. "},{"kind":"code","text":"`-1`"},{"kind":"text","text":" if the server did not provide a "},{"kind":"code","text":"`Content-Length`"},{"kind":"text","text":" header."}]},"type":{"type":"intrinsic","name":"number"}}]},{"name":"DownloadTaskOptions","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Options for download task operations."}]},"children":[{"name":"headers","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Custom headers to include in the request."}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Record"},"typeArguments":[{"type":"intrinsic","name":"string"},{"type":"intrinsic","name":"string"}],"name":"Record","package":"typescript"}},{"name":"onProgress","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Callback for download progress updates."}]},"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"signatures":[{"name":"__type","variant":"signature","kind":4096,"parameters":[{"name":"data","variant":"param","kind":32768,"type":{"type":"reference","name":"DownloadProgress","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"}}]}}},{"name":"sessionType","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Determines whether the iOS native session should continue in the background.\nAndroid accepts this option for API consistency and ignores it.\n\nWhen set to "},{"kind":"code","text":"`'background'`"},{"kind":"text","text":", the native transfer may continue after the app is\nsuspended. However, the JavaScript "},{"kind":"code","text":"`DownloadTask`"},{"kind":"text","text":" instance is not\nrestored if the app is terminated or relaunched, so its promise, progress\ncallbacks, and cancellation state are only available while the original JS\nruntime is still alive."}],"blockTags":[{"tag":"@platform","content":[{"kind":"text","text":"ios"}]},{"tag":"@default","content":[{"kind":"text","text":"'background'"}]}]},"type":{"type":"reference","name":"NetworkTaskSessionType","package":"expo-file-system"}},{"name":"signal","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"AbortSignal to cancel the download."}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.dom.d.ts","qualifiedName":"AbortSignal"},"name":"AbortSignal","package":"typescript"}}]},{"name":"DownloadTaskState","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Represents the current state of a download task."}]},"type":{"type":"union","types":[{"type":"literal","value":"idle"},{"type":"literal","value":"active"},{"type":"literal","value":"paused"},{"type":"literal","value":"completed"},{"type":"literal","value":"cancelled"},{"type":"literal","value":"error"}]}},{"name":"FileCreateOptions","variant":"declaration","kind":2097152,"children":[{"name":"intermediates","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Whether to create intermediate directories if they do not exist."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"false"}]}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"overwrite","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Whether to overwrite the file if it exists."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"false"}]}]},"type":{"type":"intrinsic","name":"boolean"}}]},{"name":"FileInfo","variant":"declaration","kind":2097152,"children":[{"name":"creationTime","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"A creation time of the file expressed in milliseconds since epoch. Returns null if the Android version is earlier than API 26."}]},"type":{"type":"intrinsic","name":"number"}},{"name":"exists","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Indicates whether the file exists."}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"md5","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Present if the "},{"kind":"code","text":"`md5`"},{"kind":"text","text":" option was truthy. Contains the MD5 hash of the file."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"modificationTime","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The last modification time of the file expressed in milliseconds since epoch."}]},"type":{"type":"intrinsic","name":"number"}},{"name":"size","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The size of the file in bytes."}]},"type":{"type":"intrinsic","name":"number"}},{"name":"uri","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"A URI pointing to the file. This is the same as the "},{"kind":"code","text":"`fileUri`"},{"kind":"text","text":" input parameter\nand preserves its scheme (for example, "},{"kind":"code","text":"`file://`"},{"kind":"text","text":" or "},{"kind":"code","text":"`content://`"},{"kind":"text","text":")."}]},"type":{"type":"intrinsic","name":"string"}}]},{"name":"FileWriteOptions","variant":"declaration","kind":2097152,"children":[{"name":"append","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Whether to append the contents to the end of the file or overwrite the existing file."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"false"}]}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"encoding","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The encoding format to use when writing the file."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"FileSystem.EncodingType.UTF8"}]}]},"type":{"type":"union","types":[{"type":"reference","name":"EncodingType","package":"expo-file-system"},{"type":"literal","value":"utf8"},{"type":"literal","value":"base64"}]}}]},{"name":"InfoOptions","variant":"declaration","kind":2097152,"children":[{"name":"md5","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Whether to return the MD5 hash of the file."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"false"}]}]},"type":{"type":"intrinsic","name":"boolean"}}]},{"name":"NetworkTaskSessionType","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"The native URL session mode used by iOS upload and download tasks."}]},"type":{"type":"union","types":[{"type":"literal","value":"background"},{"type":"literal","value":"foreground"}]}},{"name":"PathInfo","variant":"declaration","kind":2097152,"children":[{"name":"exists","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Indicates whether the path exists. Returns true if it exists; false if the path does not exist or if there is no read permission."}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"isDirectory","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Indicates whether the path is a directory. Returns true or false if the path exists; otherwise, returns null."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"boolean"},{"type":"literal","value":null}]}}]},{"name":"PickFileCanceledResult","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Result type for a canceled file pick."}]},"children":[{"name":"canceled","variant":"declaration","kind":1024,"type":{"type":"literal","value":true}},{"name":"result","variant":"declaration","kind":1024,"type":{"type":"literal","value":null}}]},{"name":"PickFileGeneralOptions","variant":"declaration","kind":2097152,"children":[{"name":"initialUri","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"A URI pointing to an initial folder in which the file picker is opened."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"mimeTypes","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The [MIME type(s)](https://en.wikipedia.org/wiki/Media_type) of the documents that are available\nto be picked. It also supports wildcards like "},{"kind":"code","text":"`'image/*'`"},{"kind":"text","text":" to choose any image. To allow any type\nof document you can use "},{"kind":"code","text":"`'*/*'`"},{"kind":"text","text":"."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"'*/*'"}]}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"array","elementType":{"type":"intrinsic","name":"string"}}]}},{"name":"multipleFiles","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Allows multiple files to be selected from the system UI."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"false"}]}]},"type":{"type":"intrinsic","name":"boolean"}}]},{"name":"PickMultipleFilesOptions","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Options for picking multiple files."}]},"type":{"type":"intersection","types":[{"type":"reference","name":"PickFileGeneralOptions","package":"expo-file-system"},{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"children":[{"name":"multipleFiles","variant":"declaration","kind":1024,"type":{"type":"literal","value":true}}]}}]}},{"name":"PickMultipleFilesResult","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Result type for picking multiple files."}]},"type":{"type":"union","types":[{"type":"reference","name":"PickMultipleFilesSuccessResult","package":"expo-file-system"},{"type":"reference","name":"PickFileCanceledResult","package":"expo-file-system"}]}},{"name":"PickMultipleFilesSuccessResult","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Result type for a successful picking multiple files."}]},"children":[{"name":"canceled","variant":"declaration","kind":1024,"type":{"type":"literal","value":false}},{"name":"result","variant":"declaration","kind":1024,"type":{"type":"array","elementType":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"}}}]},{"name":"PickSingleFileOptions","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Options for picking a single file."}]},"type":{"type":"intersection","types":[{"type":"reference","name":"PickFileGeneralOptions","package":"expo-file-system"},{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"children":[{"name":"multipleFiles","variant":"declaration","kind":1024,"flags":{"isOptional":true},"type":{"type":"literal","value":false}}]}}]}},{"name":"PickSingleFileResult","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Result type for picking a single file."}]},"type":{"type":"union","types":[{"type":"reference","name":"PickSingleFileSuccessResult","package":"expo-file-system"},{"type":"reference","name":"PickFileCanceledResult","package":"expo-file-system"}]}},{"name":"PickSingleFileSuccessResult","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Result type for successfully picking a single file."}]},"children":[{"name":"canceled","variant":"declaration","kind":1024,"type":{"type":"literal","value":false}},{"name":"result","variant":"declaration","kind":1024,"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"}}]},{"name":"UploadOptions","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Options for upload operations."}]},"children":[{"name":"fieldName","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The field name for the file in multipart uploads."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"'file'"}]}]},"type":{"type":"intrinsic","name":"string"}},{"name":"headers","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Custom headers to include in the request."}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Record"},"typeArguments":[{"type":"intrinsic","name":"string"},{"type":"intrinsic","name":"string"}],"name":"Record","package":"typescript"}},{"name":"httpMethod","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The HTTP method to use."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"'POST'"}]}]},"type":{"type":"union","types":[{"type":"literal","value":"POST"},{"type":"literal","value":"PUT"},{"type":"literal","value":"PATCH"}]}},{"name":"mimeType","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The MIME type of the file."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"onProgress","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Callback for upload progress updates.\n\n> **Note:** For multipart uploads, the reported bytes may include multipart framing overhead\n> (boundary strings, headers, form parameters) in addition to the file content."}]},"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"signatures":[{"name":"__type","variant":"signature","kind":4096,"parameters":[{"name":"data","variant":"param","kind":32768,"type":{"type":"reference","name":"UploadProgress","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"}}]}}},{"name":"parameters","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Additional form parameters to include in multipart uploads."}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Record"},"typeArguments":[{"type":"intrinsic","name":"string"},{"type":"intrinsic","name":"string"}],"name":"Record","package":"typescript"}},{"name":"sessionType","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Determines whether the iOS native session should continue in the background.\n\nWhen set to "},{"kind":"code","text":"`'background'`"},{"kind":"text","text":", the native transfer may continue after the app is\nsuspended. However, the JavaScript "},{"kind":"code","text":"`UploadTask`"},{"kind":"text","text":" instance is not\nrestored if the app is terminated or relaunched, so its promise, progress\ncallbacks, and cancellation state are only available while the original JS\nruntime is still alive."}],"blockTags":[{"tag":"@platform","content":[{"kind":"text","text":"ios"}]},{"tag":"@default","content":[{"kind":"text","text":"'background'"}]}]},"type":{"type":"reference","name":"NetworkTaskSessionType","package":"expo-file-system"}},{"name":"signal","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"An "},{"kind":"code","text":"`AbortSignal`"},{"kind":"text","text":" that can be used to cancel the upload.\nWhen the signal is aborted, the upload is cancelled and the promise rejects with an "},{"kind":"code","text":"`AbortError`"},{"kind":"text","text":"."}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.dom.d.ts","qualifiedName":"AbortSignal"},"name":"AbortSignal","package":"typescript"}},{"name":"uploadType","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The type of upload operation."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"UploadType.BINARY_CONTENT"}]}]},"type":{"type":"reference","name":"UploadType","package":"expo-file-system"}}]},{"name":"UploadProgress","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Represents upload progress data."}]},"children":[{"name":"bytesSent","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The number of bytes sent so far."}]},"type":{"type":"intrinsic","name":"number"}},{"name":"totalBytes","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The total number of bytes to send."}]},"type":{"type":"intrinsic","name":"number"}}]},{"name":"UploadResult","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Represents the result of an upload operation."}]},"children":[{"name":"body","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The response body as a string."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"headers","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The response headers."}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Record"},"typeArguments":[{"type":"intrinsic","name":"string"},{"type":"intrinsic","name":"string"}],"name":"Record","package":"typescript"}},{"name":"status","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The HTTP status code."}]},"type":{"type":"intrinsic","name":"number"}}]},{"name":"UploadTaskState","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Represents the current state of an upload task."}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Exclude"},"typeArguments":[{"type":"union","types":[{"type":"literal","value":"idle"},{"type":"literal","value":"active"},{"type":"literal","value":"paused"},{"type":"literal","value":"completed"},{"type":"literal","value":"cancelled"},{"type":"literal","value":"error"}]},{"type":"literal","value":"paused"}],"name":"Exclude","package":"typescript"}},{"name":"WatchEvent","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Describes a change detected by a file system watcher."}]},"children":[{"name":"nativeEventFlags","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Raw platform-specific event flags for advanced use cases.\nOn Android: FileObserver event flags.\nOn iOS: DispatchSource.FileSystemEvent flags."}]},"type":{"type":"intrinsic","name":"number"}},{"name":"newTarget","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"For rename events, the new path after rename.\nPopulated when MOVED_FROM and MOVED_TO events are correlated within the debounce window."}],"blockTags":[{"tag":"@platform","content":[{"kind":"text","text":"android"}]}]},"type":{"type":"reference","name":"T","package":"expo-file-system","refersToTypeParameter":true}},{"name":"target","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The file or directory that changed. For "},{"kind":"code","text":"`renamed`"},{"kind":"text","text":" events, this is the original path before the rename."}]},"type":{"type":"reference","name":"T","package":"expo-file-system","refersToTypeParameter":true}},{"name":"type","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The kind of change that occurred."}]},"type":{"type":"reference","name":"WatchEventType","package":"expo-file-system"}}],"typeParameters":[{"name":"T","variant":"typeParam","kind":131072,"type":{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"Directory"},"name":"Directory","package":"expo-file-system"}]}}]},{"name":"WatchEventType","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"The type of change that triggered a watcher event.\n- "},{"kind":"code","text":"`created`"},{"kind":"text","text":" — a new file or directory was created\n- "},{"kind":"code","text":"`modified`"},{"kind":"text","text":" — the file contents or metadata changed\n- "},{"kind":"code","text":"`deleted`"},{"kind":"text","text":" — the file or directory was removed\n- "},{"kind":"code","text":"`renamed`"},{"kind":"text","text":" — the file or directory was renamed or moved"}]},"type":{"type":"union","types":[{"type":"literal","value":"created"},{"type":"literal","value":"modified"},{"type":"literal","value":"deleted"},{"type":"literal","value":"renamed"}]}},{"name":"WatchOptions","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Options for configuring a file system watcher."}]},"children":[{"name":"debounce","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The debounce interval in milliseconds for coalescing rapid successive events into a single callback."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"DEFAULT_DEBOUNCE_MS"}]}]},"type":{"type":"intrinsic","name":"number"}},{"name":"events","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Limits which event types trigger the callback. If omitted, all event types are observed.\n\nOn iOS, directory watchers only provide coarse-grained notifications that the directory itself\nchanged, so filtering for child-level "},{"kind":"code","text":"`created`"},{"kind":"text","text":", "},{"kind":"code","text":"`deleted`"},{"kind":"text","text":", or "},{"kind":"code","text":"`renamed`"},{"kind":"text","text":" events is not reliable."}]},"type":{"type":"array","elementType":{"type":"reference","name":"WatchEventType","package":"expo-file-system"}}}]},{"name":"WatchSubscription","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"A handle to an active file system watcher. Call "},{"kind":"code","text":"`remove()`"},{"kind":"text","text":" to stop watching and release resources."}]},"children":[{"name":"remove","variant":"declaration","kind":2048,"signatures":[{"name":"remove","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Stops watching for changes and releases native resources.\nAfter calling this method, the callback will no longer be invoked."}]},"type":{"type":"intrinsic","name":"void"}}]}]},{"name":"DEFAULT_DEBOUNCE_MS","variant":"declaration","kind":32,"flags":{"isConst":true},"comment":{"summary":[{"kind":"text","text":"The default debounce time for file system watcher events in milliseconds."}]},"type":{"type":"literal","value":100},"defaultValue":"100"},{"name":"copyAsync","variant":"declaration","kind":64,"signatures":[{"name":"copyAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`new File().copy()`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"options","variant":"param","kind":32768,"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"RelocatingOptions"},"name":"RelocatingOptions","package":"expo-file-system"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"}}]},{"name":"createDownloadResumable","variant":"declaration","kind":64,"signatures":[{"name":"createDownloadResumable","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"uri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"DownloadOptions"},"name":"DownloadOptions","package":"expo-file-system"}},{"name":"callback","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"FileSystemNetworkTaskProgressCallback"},"typeArguments":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"DownloadProgressData"},"name":"DownloadProgressData","package":"expo-file-system"}],"name":"FileSystemNetworkTaskProgressCallback","package":"expo-file-system"}},{"name":"resumeData","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"intrinsic","name":"any"}}]},{"name":"createUploadTask","variant":"declaration","kind":64,"signatures":[{"name":"createUploadTask","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"url","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"FileSystemUploadOptions"},"name":"FileSystemUploadOptions","package":"expo-file-system"}},{"name":"callback","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"FileSystemNetworkTaskProgressCallback"},"typeArguments":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"UploadProgressData"},"name":"UploadProgressData","package":"expo-file-system"}],"name":"FileSystemNetworkTaskProgressCallback","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"any"}}]},{"name":"deleteAsync","variant":"declaration","kind":64,"signatures":[{"name":"deleteAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`new File().delete()`"},{"kind":"text","text":" or "},{"kind":"code","text":"`new Directory().delete()`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"DeletingOptions"},"name":"DeletingOptions","package":"expo-file-system"},"defaultValue":"{}"}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"}}]},{"name":"deleteLegacyDocumentDirectoryAndroid","variant":"declaration","kind":64,"signatures":[{"name":"deleteLegacyDocumentDirectoryAndroid","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[]}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"}}]},{"name":"downloadAsync","variant":"declaration","kind":64,"signatures":[{"name":"downloadAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`File.downloadFileAsync`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"uri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"DownloadOptions"},"name":"DownloadOptions","package":"expo-file-system"},"defaultValue":"{}"}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"FileSystemDownloadResult"},"name":"FileSystemDownloadResult","package":"expo-file-system"}],"name":"Promise","package":"typescript"}}]},{"name":"getContentUriAsync","variant":"declaration","kind":64,"signatures":[{"name":"getContentUriAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"string"}],"name":"Promise","package":"typescript"}}]},{"name":"getFreeDiskStorageAsync","variant":"declaration","kind":64,"signatures":[{"name":"getFreeDiskStorageAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`Paths.availableDiskSpace`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"number"}],"name":"Promise","package":"typescript"}}]},{"name":"getInfoAsync","variant":"declaration","kind":64,"signatures":[{"name":"getInfoAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`new File().info`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"InfoOptions"},"name":"InfoOptions","package":"expo-file-system"},"defaultValue":"{}"}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"FileInfo"},"name":"FileInfo","package":"expo-file-system"}],"name":"Promise","package":"typescript"}}]},{"name":"getTotalDiskCapacityAsync","variant":"declaration","kind":64,"signatures":[{"name":"getTotalDiskCapacityAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`Paths.totalDiskSpace`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"number"}],"name":"Promise","package":"typescript"}}]},{"name":"makeDirectoryAsync","variant":"declaration","kind":64,"signatures":[{"name":"makeDirectoryAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`new Directory().create()`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"MakeDirectoryOptions"},"name":"MakeDirectoryOptions","package":"expo-file-system"},"defaultValue":"{}"}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"}}]},{"name":"moveAsync","variant":"declaration","kind":64,"signatures":[{"name":"moveAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`new File().move()`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"options","variant":"param","kind":32768,"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"RelocatingOptions"},"name":"RelocatingOptions","package":"expo-file-system"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"}}]},{"name":"readAsStringAsync","variant":"declaration","kind":64,"signatures":[{"name":"readAsStringAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`new File().text()`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"ReadingOptions"},"name":"ReadingOptions","package":"expo-file-system"},"defaultValue":"{}"}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"string"}],"name":"Promise","package":"typescript"}}]},{"name":"readDirectoryAsync","variant":"declaration","kind":64,"signatures":[{"name":"readDirectoryAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`new Directory().list()`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"array","elementType":{"type":"intrinsic","name":"string"}}],"name":"Promise","package":"typescript"}}]},{"name":"uploadAsync","variant":"declaration","kind":64,"signatures":[{"name":"uploadAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`@expo/fetch`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"url","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"FileSystemUploadOptions"},"name":"FileSystemUploadOptions","package":"expo-file-system"},"defaultValue":"{}"}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"FileSystemUploadResult"},"name":"FileSystemUploadResult","package":"expo-file-system"}],"name":"Promise","package":"typescript"}}]},{"name":"writeAsStringAsync","variant":"declaration","kind":64,"signatures":[{"name":"writeAsStringAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`new File().write()`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"contents","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"WritingOptions"},"name":"WritingOptions","package":"expo-file-system"},"defaultValue":"{}"}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"}}]}],"packageName":"expo-file-system"} \ No newline at end of file +{"schemaVersion":"2.0","name":"expo-file-system","variant":"project","kind":1,"children":[{"name":"EncodingType","variant":"declaration","kind":8,"children":[{"name":"Base64","variant":"declaration","kind":16,"comment":{"summary":[{"kind":"text","text":"Binary, radix-64 representation."}]},"type":{"type":"literal","value":"base64"}},{"name":"UTF8","variant":"declaration","kind":16,"comment":{"summary":[{"kind":"text","text":"Standard encoding format."}]},"type":{"type":"literal","value":"utf8"}}]},{"name":"FileMode","variant":"declaration","kind":8,"comment":{"summary":[{"kind":"text","text":"Specifies the access mode when opening a file handle."}]},"children":[{"name":"Append","variant":"declaration","kind":16,"comment":{"summary":[{"kind":"text","text":"Opens the file for writing only.\nThe cursor is positioned at the end of the file.\n\n> **Note**: For SAF files, this is a strict append-only mode.\nThe cursor cannot be moved; calling "},{"kind":"code","text":"`seek()`"},{"kind":"text","text":" will have no effect."}]},"type":{"type":"literal","value":"wa"}},{"name":"ReadOnly","variant":"declaration","kind":16,"comment":{"summary":[{"kind":"text","text":"Opens the file for reading only.\nThe cursor is positioned at the beginning of the file."}]},"type":{"type":"literal","value":"r"}},{"name":"ReadWrite","variant":"declaration","kind":16,"comment":{"summary":[{"kind":"text","text":"Opens the file for both reading and writing.\nThe cursor is positioned at the beginning of the file.\n\n> **Note**: This mode cannot be used with SAF (Storage Access Framework) "},{"kind":"code","text":"`content://`"},{"kind":"text","text":" URIs."}]},"type":{"type":"literal","value":"rw"}},{"name":"Truncate","variant":"declaration","kind":16,"comment":{"summary":[{"kind":"text","text":"Opens the file for writing only and truncates the file to zero length (wipes content)."}]},"type":{"type":"literal","value":"wt"}},{"name":"WriteOnly","variant":"declaration","kind":16,"comment":{"summary":[{"kind":"text","text":"Opens the file for writing only.\nThe cursor is positioned at the beginning of the file."}]},"type":{"type":"literal","value":"w"}}]},{"name":"UploadType","variant":"declaration","kind":8,"comment":{"summary":[{"kind":"text","text":"Represents the type of upload operation."}]},"children":[{"name":"BINARY_CONTENT","variant":"declaration","kind":16,"comment":{"summary":[{"kind":"text","text":"Binary content upload - the file is uploaded as-is in the request body."}]},"type":{"type":"literal","value":0}},{"name":"MULTIPART","variant":"declaration","kind":16,"comment":{"summary":[{"kind":"text","text":"Multipart form upload - the file is uploaded as part of a multipart/form-data request."}]},"type":{"type":"literal","value":1}}]},{"name":"Directory","variant":"declaration","kind":128,"comment":{"summary":[{"kind":"text","text":"Represents a directory on the filesystem.\n\nA "},{"kind":"code","text":"`Directory`"},{"kind":"text","text":" instance can be created for any path, and does not need to exist on the filesystem during creation.\n\nThe constructor accepts an array of strings that are joined to create the directory URI. The first argument can also be a "},{"kind":"code","text":"`Directory`"},{"kind":"text","text":" instance (like "},{"kind":"code","text":"`Paths.cache`"},{"kind":"text","text":")."}],"blockTags":[{"tag":"@example","content":[{"kind":"code","text":"```ts\nconst directory = new Directory(Paths.cache, \"subdirName\");\n```"}]}]},"children":[{"name":"constructor","variant":"declaration","kind":512,"signatures":[{"name":"Directory","variant":"signature","kind":16384,"comment":{"summary":[{"kind":"text","text":"Creates an instance of a directory. It can be created for any path, and does not need to exist on the filesystem during creation.\n\nThe constructor accepts an array of strings that are joined to create the directory URI. The first argument can also be a "},{"kind":"code","text":"`Directory`"},{"kind":"text","text":" instance (like "},{"kind":"code","text":"`Paths.cache`"},{"kind":"text","text":")."}],"blockTags":[{"tag":"@example","content":[{"kind":"code","text":"```ts\nconst directory = new Directory(Paths.cache, \"subdirName\");\n```"}]}]},"parameters":[{"name":"uris","variant":"param","kind":32768,"flags":{"isRest":true},"comment":{"summary":[{"kind":"text","text":"An array of: "},{"kind":"code","text":"`file:///`"},{"kind":"text","text":" string URIs, "},{"kind":"code","text":"`File`"},{"kind":"text","text":" instances, and "},{"kind":"code","text":"`Directory`"},{"kind":"text","text":" instances representing an arbitrary location on the file system."}]},"type":{"type":"array","elementType":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}}}],"type":{"type":"reference","name":"Directory","package":"expo-file-system"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.constructor","package":"expo-file-system"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.constructor","package":"expo-file-system"}},{"name":"exists","variant":"declaration","kind":1024,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A boolean representing if a directory exists and can be accessed."}]},"type":{"type":"intrinsic","name":"boolean"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.exists"}},{"name":"size","variant":"declaration","kind":1024,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A size of the directory in bytes. Null if the directory does not exist, or it cannot be read."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"number"},{"type":"literal","value":null}]},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.size"}},{"name":"uri","variant":"declaration","kind":1024,"flags":{"isReadonly":true,"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Represents the directory URI. The field is read-only, but it may change as a result of calling some methods such as "},{"kind":"code","text":"`move`"},{"kind":"text","text":"."}]},"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.uri"}},{"name":"pickDirectoryAsync","variant":"declaration","kind":1024,"flags":{"isStatic":true},"comment":{"summary":[{"kind":"text","text":"A static method that opens a file picker to select a directory.\n\nOn iOS, the selected directory grants temporary read and write access for the current app session only. After the app restarts, you must prompt the user again to regain access."}]},"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"signatures":[{"name":"__type","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"a "},{"kind":"code","text":"`Directory`"},{"kind":"text","text":" instance. On Android, the underlying uri will be a content URI."}]}]},"parameters":[{"name":"initialUri","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"An optional uri pointing to an initial folder on which the directory picker is opened."}]},"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","name":"Directory","package":"expo-file-system"}],"name":"Promise","package":"typescript"}}]}},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.pickDirectoryAsync"}},{"name":"name","variant":"declaration","kind":262144,"getSignature":{"name":"name","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"Directory name."}]},"type":{"type":"intrinsic","name":"string"}}},{"name":"parentDirectory","variant":"declaration","kind":262144,"getSignature":{"name":"parentDirectory","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"Directory containing the file."}]},"type":{"type":"reference","name":"Directory","package":"expo-file-system"}}},{"name":"copy","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"copy","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Copies a directory."}]},"parameters":[{"name":"destination","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"Directory"},"name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","name":"RelocationOptions","package":"expo-file-system"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.copy","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.copy","package":"expo-file-system"}},{"name":"copySync","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"copySync","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Copies a directory synchronously."}]},"parameters":[{"name":"destination","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"Directory"},"name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","name":"RelocationOptions","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.copySync","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.copySync","package":"expo-file-system"}},{"name":"create","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"create","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Creates a directory that the current uri points to."}],"blockTags":[{"tag":"@throws","content":[{"kind":"text","text":"Error if the containing folder doesn't exist, the application has no read access to it or the directory (or a file with the same path) already exists (unless "},{"kind":"code","text":"`idempotent`"},{"kind":"text","text":" is "},{"kind":"code","text":"`true`"},{"kind":"text","text":")."}]}]},"parameters":[{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","name":"DirectoryCreateOptions","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.create"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.create"}},{"name":"createDirectory","variant":"declaration","kind":2048,"signatures":[{"name":"createDirectory","variant":"signature","kind":4096,"parameters":[{"name":"name","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"reference","name":"Directory","package":"expo-file-system"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.createDirectory"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.createDirectory"}},{"name":"createFile","variant":"declaration","kind":2048,"signatures":[{"name":"createFile","variant":"signature","kind":4096,"parameters":[{"name":"name","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"mimeType","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"literal","value":null}]}}],"type":{"type":"reference","name":"File","package":"expo-file-system"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.createFile","package":"expo-file-system"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.createFile","package":"expo-file-system"}},{"name":"delete","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"delete","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Deletes a directory. Also deletes all files and directories inside the directory."}],"blockTags":[{"tag":"@throws","content":[{"kind":"text","text":"Error if the directory does not exist or cannot be deleted."}]}]},"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.delete"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.delete"}},{"name":"info","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"info","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Retrieves an object containing properties of a directory."}],"blockTags":[{"tag":"@throws","content":[{"kind":"text","text":"Error If the application does not have read access to the directory, or if the path does not point to a directory (e.g., it points to a file)."}]},{"tag":"@returns","content":[{"kind":"text","text":"An object with directory metadata (for example, size, creation date, and so on)."}]}]},"type":{"type":"reference","name":"DirectoryInfo","package":"expo-file-system"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.info"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.info"}},{"name":"list","variant":"declaration","kind":2048,"signatures":[{"name":"list","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Lists the contents of a directory.\nCalling this method if the parent directory does not exist will throw an error."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"An array of "},{"kind":"code","text":"`Directory`"},{"kind":"text","text":" and "},{"kind":"code","text":"`File`"},{"kind":"text","text":" instances."}]}]},"type":{"type":"array","elementType":{"type":"union","types":[{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.list","package":"expo-file-system"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.list","package":"expo-file-system"}},{"name":"move","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"move","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Moves a directory. Updates the "},{"kind":"code","text":"`uri`"},{"kind":"text","text":" property that now points to the new location."}]},"parameters":[{"name":"destination","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"Directory"},"name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","name":"RelocationOptions","package":"expo-file-system"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.move","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.move","package":"expo-file-system"}},{"name":"moveSync","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"moveSync","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Moves a directory synchronously. Updates the "},{"kind":"code","text":"`uri`"},{"kind":"text","text":" property that now points to the new location."}]},"parameters":[{"name":"destination","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"Directory"},"name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","name":"RelocationOptions","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.moveSync","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.moveSync","package":"expo-file-system"}},{"name":"rename","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"rename","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Renames a directory."}]},"parameters":[{"name":"newName","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.rename"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.rename"}},{"name":"watch","variant":"declaration","kind":2048,"signatures":[{"name":"watch","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Watches this directory for changes to its contents or the directory itself.\n\nEvents are emitted when files or subdirectories are created, modified, deleted, or renamed\nwithin this directory. On iOS, child changes are surfaced as a coarse-grained "},{"kind":"code","text":"`modified`"},{"kind":"text","text":" event\non the directory itself, so filtering for child-level "},{"kind":"code","text":"`created`"},{"kind":"text","text":", "},{"kind":"code","text":"`deleted`"},{"kind":"text","text":", or "},{"kind":"code","text":"`renamed`"},{"kind":"text","text":" events\nis not reliable. The watcher automatically stops when the directory is deleted or renamed.\nTo stop watching manually, call "},{"kind":"code","text":"`remove()`"},{"kind":"text","text":" on the returned subscription."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A subscription handle. Call "},{"kind":"code","text":"`remove()`"},{"kind":"text","text":" to stop watching."}]},{"tag":"@example","content":[{"kind":"code","text":"```ts\nconst cacheDir = new Directory(Paths.cache);\nconst subscription = cacheDir.watch((event) => {\n console.log(`${event.type}: ${event.target.uri}`);\n});\n\n// Later, stop watching:\nsubscription.remove();\n```"}]}]},"parameters":[{"name":"callback","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"Invoked when a change is detected. Receives a "},{"kind":"code","text":"`WatchEvent`"},{"kind":"text","text":" describing what changed."}]},"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"signatures":[{"name":"__type","variant":"signature","kind":4096,"parameters":[{"name":"event","variant":"param","kind":32768,"type":{"type":"reference","typeArguments":[{"type":"union","types":[{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}],"name":"WatchEvent","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"}}]}}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Configuration for debouncing and filtering events."}]},"type":{"type":"reference","name":"WatchOptions","package":"expo-file-system"}}],"type":{"type":"reference","name":"WatchSubscription","package":"expo-file-system"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.watch","package":"expo-file-system"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDirectory.watch","package":"expo-file-system"}}],"extendedTypes":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.ts","qualifiedName":"ExpoFileSystemModule.FileSystemDirectory"},"name":"FileSystemDirectory","package":"expo-file-system","qualifiedName":"ExpoFileSystemModule.FileSystemDirectory"}]},{"name":"DownloadTask","variant":"declaration","kind":128,"comment":{"summary":[{"kind":"text","text":"Represents a download task with pause/resume support and progress tracking.\n\nDownload tasks start in the "},{"kind":"code","text":"`idle`"},{"kind":"text","text":" state. Calling "},{"kind":"code","text":"`downloadAsync()`"},{"kind":"text","text":" moves the task to "},{"kind":"code","text":"`active`"},{"kind":"text","text":";\npausing moves it to "},{"kind":"code","text":"`paused`"},{"kind":"text","text":", and a completed, cancelled, or failed transfer moves it to the\ncorresponding terminal state."}]},"children":[{"name":"constructor","variant":"declaration","kind":512,"signatures":[{"name":"DownloadTask","variant":"signature","kind":16384,"comment":{"summary":[{"kind":"text","text":"Creates a download task.\n\nThe task does not start automatically. Call "},{"kind":"code","text":"`downloadAsync()`"},{"kind":"text","text":" to begin downloading."}]},"parameters":[{"name":"url","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The URL of the file to download."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"destination","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The destination file or directory. If a directory is provided, the resulting\nfilename is determined from the response headers or URL."}]},"type":{"type":"union","types":[{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Download task options."}]},"type":{"type":"reference","name":"DownloadTaskOptions","package":"expo-file-system"}}],"type":{"type":"reference","name":"DownloadTask","package":"expo-file-system"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.constructor","package":"expo-file-system"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.constructor","package":"expo-file-system"}},{"name":"state","variant":"declaration","kind":262144,"getSignature":{"name":"state","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"The current state of the download task."}]},"type":{"type":"union","types":[{"type":"literal","value":"idle"},{"type":"literal","value":"active"},{"type":"literal","value":"paused"},{"type":"literal","value":"completed"},{"type":"literal","value":"cancelled"},{"type":"literal","value":"error"}]}}},{"name":"addListener","variant":"declaration","kind":2048,"signatures":[{"name":"addListener","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Adds a listener for download progress events.\n\n> **Note:** Prefer the "},{"kind":"code","text":"`onProgress`"},{"kind":"text","text":" option unless you need manual subscription control."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A subscription handle. Call "},{"kind":"code","text":"`remove()`"},{"kind":"text","text":" to stop listening."}]}]},"parameters":[{"name":"eventName","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The event to listen to. Only "},{"kind":"code","text":"`'progress'`"},{"kind":"text","text":" is supported."}]},"type":{"type":"literal","value":"progress"}},{"name":"listener","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"Invoked with download progress updates."}]},"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"signatures":[{"name":"__type","variant":"signature","kind":4096,"parameters":[{"name":"data","variant":"param","kind":32768,"type":{"type":"reference","name":"DownloadProgress","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"}}]}}}],"type":{"type":"reference","target":{"packageName":"expo-modules-core","packagePath":"src/EventEmitter.ts","qualifiedName":"EventSubscription"},"name":"EventSubscription","package":"expo-modules-core"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.addListener","package":"expo-modules-core"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.addListener","package":"expo-modules-core"}},{"name":"cancel","variant":"declaration","kind":2048,"signatures":[{"name":"cancel","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Cancels the download operation.\n\nIf "},{"kind":"code","text":"`downloadAsync()`"},{"kind":"text","text":" or "},{"kind":"code","text":"`resumeAsync()`"},{"kind":"text","text":" is pending, its promise is rejected after the native\nrequest is cancelled. Calling this method after the task reaches "},{"kind":"code","text":"`completed`"},{"kind":"text","text":", "},{"kind":"code","text":"`cancelled`"},{"kind":"text","text":", or\n"},{"kind":"code","text":"`error`"},{"kind":"text","text":" has no effect."}]},"type":{"type":"intrinsic","name":"void"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.cancel"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.cancel"}},{"name":"downloadAsync","variant":"declaration","kind":2048,"signatures":[{"name":"downloadAsync","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Starts the download operation.\n\nThis method can only be called once, while the task is "},{"kind":"code","text":"`idle`"},{"kind":"text","text":". The promise is fulfilled with\nthe downloaded file when the transfer completes, or with "},{"kind":"code","text":"`null`"},{"kind":"text","text":" if the task is paused before\ncompletion. It is rejected when the request fails or the task is cancelled.\n\nIf "},{"kind":"code","text":"`options.signal`"},{"kind":"text","text":" is aborted, the promise is rejected with an "},{"kind":"code","text":"`AbortError`"},{"kind":"text","text":"."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A promise fulfilled with the downloaded file, or "},{"kind":"code","text":"`null`"},{"kind":"text","text":" when the task is paused."}]}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"union","types":[{"type":"reference","name":"File","package":"expo-file-system"},{"type":"literal","value":null}]}],"name":"Promise","package":"typescript"}}]},{"name":"emit","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"emit","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Synchronously calls all the listeners attached to that specific event.\nThe event can include any number of arguments that will be passed to the listeners."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}},{"name":"args","variant":"param","kind":32768,"flags":{"isRest":true},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Parameters"},"typeArguments":[{"type":"indexedAccess","indexType":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true},"objectType":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.ts","qualifiedName":"DownloadTaskEvents"},"name":"DownloadTaskEvents","package":"expo-file-system"}}],"name":"Parameters","package":"typescript"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.emit","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.emit","package":"expo-modules-core"}},{"name":"listenerCount","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"listenerCount","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Returns a number of listeners added to the given event."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}}],"type":{"type":"intrinsic","name":"number"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.listenerCount","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.listenerCount","package":"expo-modules-core"}},{"name":"pause","variant":"declaration","kind":2048,"signatures":[{"name":"pause","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Requests pausing the active download operation.\n\nThe pending "},{"kind":"code","text":"`downloadAsync()`"},{"kind":"text","text":" or "},{"kind":"code","text":"`resumeAsync()`"},{"kind":"text","text":" promise is fulfilled with "},{"kind":"code","text":"`null`"},{"kind":"text","text":" after native\ncode produces resume data and the task enters the "},{"kind":"code","text":"`paused`"},{"kind":"text","text":" state. Use "},{"kind":"code","text":"`pauseAsync()`"},{"kind":"text","text":" if you\nneed to wait until the task is ready to resume or save."}]},"type":{"type":"intrinsic","name":"void"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.pause"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.pause"}},{"name":"pauseAsync","variant":"declaration","kind":2048,"signatures":[{"name":"pauseAsync","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Requests pausing the active download operation and waits until the task reaches the "},{"kind":"code","text":"`paused`"},{"kind":"text","text":"\nstate."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A promise fulfilled after resume data is available."}]}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"}}]},{"name":"release","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"release","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A function that detaches the JS and native objects to let the native object deallocate\nbefore the JS object gets deallocated by the JS garbage collector. Any subsequent calls to native\nfunctions of the object will throw an error as it is no longer associated with its native counterpart.\n\nIn most cases, you should never need to use this function, except some specific performance-critical cases when\nmanual memory management makes sense and the native object is known to exclusively retain some native memory\n(such as binary data or image bitmap). Before calling this function, you should ensure that nothing else will use\nthis object later on. Shared objects created by React hooks are usually automatically released in the effect's cleanup phase,\nfor example: "},{"kind":"code","text":"`useVideoPlayer()`"},{"kind":"text","text":" from "},{"kind":"code","text":"`expo-video`"},{"kind":"text","text":" and "},{"kind":"code","text":"`useImage()`"},{"kind":"text","text":" from "},{"kind":"code","text":"`expo-image`"},{"kind":"text","text":"."}]},"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.release","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.release","package":"expo-modules-core"}},{"name":"removeAllListeners","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"removeAllListeners","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Removes all listeners for the given event name."}]},"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"literal","value":"progress"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.removeAllListeners","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.removeAllListeners","package":"expo-modules-core"}},{"name":"removeListener","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"removeListener","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Removes a listener for the given event name."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}},{"name":"listener","variant":"param","kind":32768,"type":{"type":"indexedAccess","indexType":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true},"objectType":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.ts","qualifiedName":"DownloadTaskEvents"},"name":"DownloadTaskEvents","package":"expo-file-system"}}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.removeListener","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.removeListener","package":"expo-modules-core"}},{"name":"resumeAsync","variant":"declaration","kind":2048,"signatures":[{"name":"resumeAsync","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Resumes a paused download operation.\n\nThe promise is fulfilled with the downloaded file when the transfer completes, or with "},{"kind":"code","text":"`null`"},{"kind":"text","text":"\nif the task is paused again before completion. It is rejected when the request fails or the task\nis cancelled."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A promise fulfilled with the downloaded file, or "},{"kind":"code","text":"`null`"},{"kind":"text","text":" when the task is paused."}]}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"union","types":[{"type":"reference","name":"File","package":"expo-file-system"},{"type":"literal","value":null}]}],"name":"Promise","package":"typescript"}}]},{"name":"savable","variant":"declaration","kind":2048,"signatures":[{"name":"savable","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Returns the paused task state that can be persisted and restored later.\n\nThis method can only be called while the task is "},{"kind":"code","text":"`paused`"},{"kind":"text","text":". The returned state contains\nplatform-specific resume data and request metadata, but does not include callbacks or abort\nsignals."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A serializable paused download state."}]}]},"type":{"type":"reference","name":"DownloadPauseState","package":"expo-file-system"}}]},{"name":"startObserving","variant":"declaration","kind":2048,"flags":{"isOptional":true,"isInherited":true},"signatures":[{"name":"startObserving","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Function that is automatically invoked when the first listener for an event with the given name is added.\nOverride it in a subclass to perform some additional setup once the event started being observed."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.startObserving","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.startObserving","package":"expo-modules-core"}},{"name":"stopObserving","variant":"declaration","kind":2048,"flags":{"isOptional":true,"isInherited":true},"signatures":[{"name":"stopObserving","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Function that is automatically invoked when the last listener for an event with the given name is removed.\nOverride it in a subclass to perform some additional cleanup once the event is no longer observed."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.stopObserving","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemDownloadTask.stopObserving","package":"expo-modules-core"}},{"name":"fromSavable","variant":"declaration","kind":2048,"flags":{"isStatic":true},"signatures":[{"name":"fromSavable","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Creates a paused download task from saved state.\n\nUse this to continue a download after persisting the value returned by "},{"kind":"code","text":"`savable()`"},{"kind":"text","text":". New options\ncan attach progress callbacks or an abort signal because functions and signals are not stored\nin "},{"kind":"code","text":"`DownloadPauseState`"},{"kind":"text","text":". If both saved state and new options include headers, the new headers\noverride saved headers with the same names."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A download task in the "},{"kind":"code","text":"`paused`"},{"kind":"text","text":" state."}]}]},"parameters":[{"name":"state","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The saved pause state."}]},"type":{"type":"reference","name":"DownloadPauseState","package":"expo-file-system"}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Optional download task options to attach to the restored task."}]},"type":{"type":"reference","name":"DownloadTaskOptions","package":"expo-file-system"}}],"type":{"type":"reference","name":"DownloadTask","package":"expo-file-system"}}]}],"extendedTypes":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.ts","qualifiedName":"ExpoFileSystemModule.FileSystemDownloadTask"},"name":"FileSystemDownloadTask","package":"expo-file-system","qualifiedName":"ExpoFileSystemModule.FileSystemDownloadTask"}]},{"name":"File","variant":"declaration","kind":128,"comment":{"summary":[{"kind":"text","text":"Represents a file on the filesystem.\n\nA "},{"kind":"code","text":"`File`"},{"kind":"text","text":" instance can be created for any path, and does not need to exist on the filesystem during creation.\n\nThe constructor accepts an array of strings that are joined to create the file URI. The first argument can also be a "},{"kind":"code","text":"`Directory`"},{"kind":"text","text":" instance (like "},{"kind":"code","text":"`Paths.cache`"},{"kind":"text","text":") or a "},{"kind":"code","text":"`File`"},{"kind":"text","text":" instance (which creates a new reference to the same file)."}],"blockTags":[{"tag":"@example","content":[{"kind":"code","text":"```ts\nconst file = new File(Paths.cache, \"subdirName\", \"file.txt\");\n```"}]}]},"children":[{"name":"constructor","variant":"declaration","kind":512,"signatures":[{"name":"File","variant":"signature","kind":16384,"comment":{"summary":[{"kind":"text","text":"Creates an instance of a file. It can be created for any path, and does not need to exist on the filesystem during creation.\n\nThe constructor accepts an array of strings that are joined to create the file URI. The first argument can also be a "},{"kind":"code","text":"`Directory`"},{"kind":"text","text":" instance (like "},{"kind":"code","text":"`Paths.cache`"},{"kind":"text","text":") or a "},{"kind":"code","text":"`File`"},{"kind":"text","text":" instance (which creates a new reference to the same file)."}],"blockTags":[{"tag":"@example","content":[{"kind":"code","text":"```ts\nconst file = new File(Paths.cache, \"subdirName\", \"file.txt\");\n```"}]}]},"parameters":[{"name":"uris","variant":"param","kind":32768,"flags":{"isRest":true},"comment":{"summary":[{"kind":"text","text":"An array of: "},{"kind":"code","text":"`file:///`"},{"kind":"text","text":" string URIs, "},{"kind":"code","text":"`File`"},{"kind":"text","text":" instances, and "},{"kind":"code","text":"`Directory`"},{"kind":"text","text":" instances representing an arbitrary location on the file system."}]},"type":{"type":"array","elementType":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}}}],"type":{"type":"reference","name":"File","package":"expo-file-system"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.constructor","package":"expo-file-system"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.constructor","package":"expo-file-system"}},{"name":"contentUri","variant":"declaration","kind":1024,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A content URI to the file that can be shared to external applications."}],"blockTags":[{"tag":"@platform","content":[{"kind":"text","text":"android"}]}]},"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.contentUri"}},{"name":"creationTime","variant":"declaration","kind":1024,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A creation time of the file expressed in milliseconds since the epoch. Returns a "},{"kind":"code","text":"`null`"},{"kind":"text","text":" if the file does not exist, cannot be read or the Android version is earlier than API 26."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"number"},{"type":"literal","value":null}]},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.creationTime"}},{"name":"exists","variant":"declaration","kind":1024,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A boolean representing if a file exists. "},{"kind":"code","text":"`true`"},{"kind":"text","text":" if the file exists, "},{"kind":"code","text":"`false`"},{"kind":"text","text":" otherwise.\nAlso, "},{"kind":"code","text":"`false`"},{"kind":"text","text":" if the application does not have read access to the file."}]},"type":{"type":"intrinsic","name":"boolean"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.exists"}},{"name":"lastModified","variant":"declaration","kind":1024,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A last modification time of the file expressed in milliseconds since the epoch. Returns a "},{"kind":"code","text":"`null`"},{"kind":"text","text":" if the file does not exist, or if it cannot be read."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"number"},{"type":"literal","value":null}]},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.lastModified"}},{"name":"md5","variant":"declaration","kind":1024,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A md5 hash of the file. Null if the file does not exist, or it cannot be read."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"literal","value":null}]},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.md5"}},{"name":"modificationTime","variant":"declaration","kind":1024,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A last modification time of the file expressed in milliseconds since the epoch. Returns a "},{"kind":"code","text":"`null`"},{"kind":"text","text":" if the file does not exist, or if it cannot be read."}],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"In favor of "},{"kind":"code","text":"`lastModified`"},{"kind":"text","text":" to be more in line with web ["},{"kind":"code","text":"`File`"},{"kind":"text","text":"](https://developer.mozilla.org/en-US/docs/Web/API/File)"}]}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"number"},{"type":"literal","value":null}]},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.modificationTime"}},{"name":"size","variant":"declaration","kind":1024,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A size of the file in bytes. 0 if the file does not exist, or it cannot be read."}]},"type":{"type":"intrinsic","name":"number"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.size"},"implementationOf":{"type":"reference","name":"Blob.size"}},{"name":"type","variant":"declaration","kind":1024,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A mime type of the file. An empty string if the file does not exist, or it cannot be read."}]},"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.type"},"implementationOf":{"type":"reference","name":"Blob.type"}},{"name":"downloadFileAsync","variant":"declaration","kind":1024,"flags":{"isStatic":true},"comment":{"summary":[{"kind":"text","text":"A static method that downloads a file from the network.\n\nOn Android, the response body streams directly into the target file. If the download fails after\nit starts, a partially written file may remain at the destination. On iOS, the download first\ncompletes in a temporary location and the file is moved into place only after success, so no\nfile is left behind when the request fails."}],"blockTags":[{"tag":"@example","content":[{"kind":"code","text":"```ts\nconst file = await File.downloadFileAsync(\"https://example.com/image.png\", new Directory(Paths.document));\n```"}]}]},"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"signatures":[{"name":"__type","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A promise fulfilled with the downloaded file. When the server responds with\na non-2xx HTTP status, the promise rejects with an "},{"kind":"code","text":"`UnableToDownload`"},{"kind":"text","text":" error whose\nmessage includes the status code. No file is created in that scenario."}]}]},"parameters":[{"name":"url","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The URL of the file to download."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"destination","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The destination directory or file. If a directory is provided, the resulting filename will be determined based on the response headers."}]},"type":{"type":"union","types":[{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Download options. When the destination already contains a file, the promise rejects with a "},{"kind":"code","text":"`DestinationAlreadyExists`"},{"kind":"text","text":" error unless "},{"kind":"code","text":"`options.idempotent`"},{"kind":"text","text":" is set to "},{"kind":"code","text":"`true`"},{"kind":"text","text":". With "},{"kind":"code","text":"`idempotent: true`"},{"kind":"text","text":", the download overwrites the existing file instead of failing."}]},"type":{"type":"reference","name":"DownloadOptions","package":"expo-file-system"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","name":"File","package":"expo-file-system"}],"name":"Promise","package":"typescript"}}]}},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.downloadFileAsync"}},{"name":"extension","variant":"declaration","kind":262144,"getSignature":{"name":"extension","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"File extension."}],"blockTags":[{"tag":"@example","name":"'.png'","content":[]}]},"type":{"type":"intrinsic","name":"string"}}},{"name":"name","variant":"declaration","kind":262144,"getSignature":{"name":"name","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"File name. Includes the extension."}]},"type":{"type":"intrinsic","name":"string"}}},{"name":"parentDirectory","variant":"declaration","kind":262144,"getSignature":{"name":"parentDirectory","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"Directory containing the file."}]},"type":{"type":"reference","name":"Directory","package":"expo-file-system"}}},{"name":"uri","variant":"declaration","kind":262144,"flags":{"isInherited":true},"getSignature":{"name":"uri","variant":"signature","kind":524288,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Represents the file URI. The field is read-only, but it may change as a result of calling some methods such as "},{"kind":"code","text":"`move`"},{"kind":"text","text":"."}]},"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.uri"}},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.uri"}},{"name":"arrayBuffer","variant":"declaration","kind":2048,"signatures":[{"name":"arrayBuffer","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"The **"},{"kind":"code","text":"`arrayBuffer()`"},{"kind":"text","text":"** method of the Blob interface returns a Promise that resolves with the contents of the blob as binary data contained in an ArrayBuffer.\n\n[MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/arrayBuffer)"}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"ArrayBuffer"},"name":"ArrayBuffer","package":"typescript"}],"name":"Promise","package":"typescript"},"implementationOf":{"type":"reference","name":"Blob.arrayBuffer"}}],"implementationOf":{"type":"reference","name":"Blob.arrayBuffer"}},{"name":"base64","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"base64","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Retrieves content of the file as base64."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A promise fulfilled with the contents of the file as a base64 string."}]}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"string"}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.base64"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.base64"}},{"name":"base64Sync","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"base64Sync","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Retrieves content of the file as base64."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"The contents of the file as a base64 string."}]}]},"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.base64Sync"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.base64Sync"}},{"name":"bytes","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"bytes","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Retrieves byte content of the entire file."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A promise fulfilled with the contents of the file as a "},{"kind":"code","text":"`Uint8Array`"},{"kind":"text","text":"."}]}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Uint8Array"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"ArrayBuffer"},"name":"ArrayBuffer","package":"typescript"}],"name":"Uint8Array","package":"typescript"}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.bytes"},"implementationOf":{"type":"reference","name":"Blob.bytes"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.bytes"},"implementationOf":{"type":"reference","name":"Blob.bytes"}},{"name":"bytesSync","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"bytesSync","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Retrieves byte content of the entire file."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"The contents of the file as a "},{"kind":"code","text":"`Uint8Array`"},{"kind":"text","text":"."}]}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Uint8Array"},"name":"Uint8Array","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.bytesSync"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.bytesSync"}},{"name":"copy","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"copy","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Copies a file."}]},"parameters":[{"name":"destination","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"Directory"},"name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","name":"RelocationOptions","package":"expo-file-system"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.copy","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.copy","package":"expo-file-system"}},{"name":"copySync","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"copySync","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Copies a file synchronously."}]},"parameters":[{"name":"destination","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"Directory"},"name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","name":"RelocationOptions","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.copySync","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.copySync","package":"expo-file-system"}},{"name":"create","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"create","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Creates a file."}],"blockTags":[{"tag":"@throws","content":[{"kind":"text","text":"Error if the containing folder doesn't exist, the application has no read access to it or the file (or directory with the same path) already exists."}]}]},"parameters":[{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","name":"FileCreateOptions","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.create"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.create"}},{"name":"createUploadTask","variant":"declaration","kind":2048,"signatures":[{"name":"createUploadTask","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Creates an upload task for this file without starting it.\n\nCall "},{"kind":"code","text":"`uploadAsync()`"},{"kind":"text","text":" on the returned task to start the upload. Use this when you need to\ninspect task state, cancel the upload, or subscribe to progress manually."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"An upload task that can be started with "},{"kind":"code","text":"`uploadAsync()`"},{"kind":"text","text":"."}]},{"tag":"@example","content":[{"kind":"code","text":"```ts\nconst file = new File(Paths.document, 'photo.jpg');\nconst task = file.createUploadTask('https://example.com/upload', {\n uploadType: UploadType.MULTIPART,\n onProgress: ({ bytesSent, totalBytes }) => {\n console.log(`${bytesSent} / ${totalBytes}`);\n },\n});\n\nconst result = await task.uploadAsync();\n```"}]}]},"parameters":[{"name":"url","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The URL to upload the file to."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Upload options."}]},"type":{"type":"reference","name":"UploadOptions","package":"expo-file-system"}}],"type":{"type":"reference","name":"UploadTask","package":"expo-file-system"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.createUploadTask"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.createUploadTask"}},{"name":"delete","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"delete","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Deletes a file."}],"blockTags":[{"tag":"@throws","content":[{"kind":"text","text":"Error if the directory does not exist or cannot be deleted."}]}]},"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.delete"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.delete"}},{"name":"info","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"info","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Retrieves an object containing properties of a file"}],"blockTags":[{"tag":"@throws","content":[{"kind":"text","text":"Error If the application does not have read access to the file, or if the path does not point to a file (for example, it points to a directory)."}]},{"tag":"@returns","content":[{"kind":"text","text":"An object with file metadata (for example, size, creation date, and so on)."}]}]},"parameters":[{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","name":"InfoOptions","package":"expo-file-system"}}],"type":{"type":"reference","name":"FileInfo","package":"expo-file-system"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.info"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.info"}},{"name":"move","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"move","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Moves a directory. Updates the "},{"kind":"code","text":"`uri`"},{"kind":"text","text":" property that now points to the new location."}]},"parameters":[{"name":"destination","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"Directory"},"name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","name":"RelocationOptions","package":"expo-file-system"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.move","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.move","package":"expo-file-system"}},{"name":"moveSync","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"moveSync","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Moves a file synchronously. Updates the "},{"kind":"code","text":"`uri`"},{"kind":"text","text":" property that now points to the new location."}]},"parameters":[{"name":"destination","variant":"param","kind":32768,"type":{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"Directory"},"name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","name":"RelocationOptions","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.moveSync","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.moveSync","package":"expo-file-system"}},{"name":"open","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"open","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Returns A "},{"kind":"code","text":"`FileHandle`"},{"kind":"text","text":" object that can be used to read and write data to the file."}],"blockTags":[{"tag":"@throws","content":[{"kind":"text","text":"Error if the file does not exist or cannot be opened."}]}]},"parameters":[{"name":"mode","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The "},{"kind":"inline-tag","tag":"@link","text":"FileMode"},{"kind":"text","text":" to use.\n- On **Android**, SAF "},{"kind":"code","text":"`content://`"},{"kind":"text","text":" URIs do not support "},{"kind":"code","text":"`ReadWrite`"},{"kind":"text","text":" mode.\n- **Defaults**:\n - For SAF "},{"kind":"code","text":"`content://`"},{"kind":"text","text":" URIs, the default is "},{"kind":"code","text":"`FileMode.ReadOnly`"},{"kind":"text","text":".\n - For standard "},{"kind":"code","text":"`file://`"},{"kind":"text","text":" URIs, the default is "},{"kind":"code","text":"`FileMode.ReadWrite`"},{"kind":"text","text":"."}]},"type":{"type":"reference","name":"FileMode","package":"expo-file-system"}}],"type":{"type":"reference","name":"FileHandle","package":"expo-file-system"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.open"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.open"}},{"name":"readableStream","variant":"declaration","kind":2048,"signatures":[{"name":"readableStream","variant":"signature","kind":4096,"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.dom.d.ts","qualifiedName":"ReadableStream"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Uint8Array"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"ArrayBuffer"},"name":"ArrayBuffer","package":"typescript"}],"name":"Uint8Array","package":"typescript"}],"name":"ReadableStream","package":"typescript"}}]},{"name":"rename","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"rename","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Renames a file."}]},"parameters":[{"name":"newName","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.rename"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.rename"}},{"name":"slice","variant":"declaration","kind":2048,"signatures":[{"name":"slice","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"The **"},{"kind":"code","text":"`slice()`"},{"kind":"text","text":"** method of the Blob interface creates and returns a new "},{"kind":"code","text":"`Blob`"},{"kind":"text","text":" object which contains data from a subset of the blob on which it's called.\n\n[MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/slice)"}]},"parameters":[{"name":"start","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"intrinsic","name":"number"}},{"name":"end","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"intrinsic","name":"number"}},{"name":"contentType","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.dom.d.ts","qualifiedName":"Blob"},"name":"Blob","package":"typescript"},"implementationOf":{"type":"reference","name":"Blob.slice"}}],"implementationOf":{"type":"reference","name":"Blob.slice"}},{"name":"stream","variant":"declaration","kind":2048,"signatures":[{"name":"stream","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"The **"},{"kind":"code","text":"`stream()`"},{"kind":"text","text":"** method of the Blob interface returns a ReadableStream which upon reading returns the data contained within the "},{"kind":"code","text":"`Blob`"},{"kind":"text","text":".\n\n[MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/stream)"}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.dom.d.ts","qualifiedName":"ReadableStream"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Uint8Array"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"ArrayBuffer"},"name":"ArrayBuffer","package":"typescript"}],"name":"Uint8Array","package":"typescript"}],"name":"ReadableStream","package":"typescript"},"implementationOf":{"type":"reference","name":"Blob.stream"}}],"implementationOf":{"type":"reference","name":"Blob.stream"}},{"name":"text","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"text","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Retrieves text from the file."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A promise fulfilled with the contents of the file as string."}]}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"string"}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.text"},"implementationOf":{"type":"reference","name":"Blob.text"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.text"},"implementationOf":{"type":"reference","name":"Blob.text"}},{"name":"textSync","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"textSync","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Retrieves text from the file."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"The contents of the file as string."}]}]},"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.textSync"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.textSync"}},{"name":"upload","variant":"declaration","kind":2048,"signatures":[{"name":"upload","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Uploads this file to a server and starts the request immediately.\n\nThe promise is fulfilled with response metadata and body for completed HTTP responses,\nincluding non-2xx status codes. It is rejected only when the file cannot be read, the\nrequest fails, or the upload is cancelled."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A promise fulfilled with the upload response."}]}]},"parameters":[{"name":"url","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The URL to upload the file to."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Upload options."}]},"type":{"type":"reference","name":"UploadOptions","package":"expo-file-system"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","name":"UploadResult","package":"expo-file-system"}],"name":"Promise","package":"typescript"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.upload"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.upload"}},{"name":"watch","variant":"declaration","kind":2048,"signatures":[{"name":"watch","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Watches this file for changes on the filesystem.\n\nThe watcher automatically stops when the file is deleted or renamed. To stop watching manually,\ncall "},{"kind":"code","text":"`remove()`"},{"kind":"text","text":" on the returned subscription."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A subscription handle. Call "},{"kind":"code","text":"`remove()`"},{"kind":"text","text":" to stop watching."}]},{"tag":"@example","content":[{"kind":"code","text":"```ts\nconst file = new File(Paths.cache, 'data.json');\nconst subscription = file.watch((event) => {\n console.log(`File ${event.type}`);\n});\n\n// Later, stop watching:\nsubscription.remove();\n```"}]}]},"parameters":[{"name":"callback","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"Invoked when a change is detected. Receives a "},{"kind":"code","text":"`WatchEvent`"},{"kind":"text","text":" describing what changed."}]},"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"signatures":[{"name":"__type","variant":"signature","kind":4096,"parameters":[{"name":"event","variant":"param","kind":32768,"type":{"type":"reference","typeArguments":[{"type":"reference","name":"File","package":"expo-file-system"}],"name":"WatchEvent","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"}}]}}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Configuration for debouncing and filtering events."}]},"type":{"type":"reference","name":"WatchOptions","package":"expo-file-system"}}],"type":{"type":"reference","name":"WatchSubscription","package":"expo-file-system"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.watch","package":"expo-file-system"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.watch","package":"expo-file-system"}},{"name":"writableStream","variant":"declaration","kind":2048,"signatures":[{"name":"writableStream","variant":"signature","kind":4096,"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.dom.d.ts","qualifiedName":"WritableStream"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Uint8Array"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"ArrayBufferLike"},"name":"ArrayBufferLike","package":"typescript"}],"name":"Uint8Array","package":"typescript"}],"name":"WritableStream","package":"typescript"}}]},{"name":"write","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"write","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Writes content to the file."}]},"parameters":[{"name":"content","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The content to write into the file."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Uint8Array"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"ArrayBufferLike"},"name":"ArrayBufferLike","package":"typescript"}],"name":"Uint8Array","package":"typescript"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","name":"FileWriteOptions","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.write","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.write","package":"expo-file-system"}},{"name":"createDownloadTask","variant":"declaration","kind":2048,"flags":{"isStatic":true},"signatures":[{"name":"createDownloadTask","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Creates a download task without starting it.\n\nCall "},{"kind":"code","text":"`downloadAsync()`"},{"kind":"text","text":" on the returned task to start the download. Use this when you need\npause/resume support, task state, cancellation, or manual progress subscriptions."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A download task that can be started with "},{"kind":"code","text":"`downloadAsync()`"},{"kind":"text","text":"."}]},{"tag":"@example","content":[{"kind":"code","text":"```ts\nconst destination = new File(Paths.document, 'video.mp4');\nconst task = File.createDownloadTask('https://example.com/video.mp4', destination, {\n onProgress: ({ bytesWritten, totalBytes }) => {\n console.log(`${bytesWritten} / ${totalBytes}`);\n },\n});\n\nconst file = await task.downloadAsync();\n```"}]}]},"parameters":[{"name":"url","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The URL of the file to download."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"destination","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The destination file or directory. If a directory is provided, the\nresulting filename is determined from the response headers or URL."}]},"type":{"type":"union","types":[{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Download task options."}]},"type":{"type":"reference","name":"DownloadTaskOptions","package":"expo-file-system"}}],"type":{"type":"reference","name":"DownloadTask","package":"expo-file-system"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.createDownloadTask"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.createDownloadTask"}},{"name":"pickFileAsync","variant":"declaration","kind":2048,"flags":{"isStatic":true,"isInherited":true},"signatures":[{"name":"pickFileAsync","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Opens the system file picker for selecting a single file.\n\nThis overload requires "},{"kind":"code","text":"`options.multipleFiles`"},{"kind":"text","text":" to be "},{"kind":"code","text":"`undefined`"},{"kind":"text","text":" or "},{"kind":"code","text":"`false`"},{"kind":"text","text":"."}]},"parameters":[{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"File picker options."}]},"type":{"type":"reference","name":"PickSingleFileOptions","package":"expo-file-system"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","name":"PickSingleFileResult","package":"expo-file-system"}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.pickFileAsync"}},{"name":"pickFileAsync","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Opens the system file picker for selecting multiple files.\n\nThis overload requires "},{"kind":"code","text":"`options.multipleFiles`"},{"kind":"text","text":" to be "},{"kind":"code","text":"`true`"},{"kind":"text","text":"."}],"blockTags":[{"tag":"@example","content":[{"kind":"code","text":"```ts\nconst result = await File.pickFileAsync({\n multipleFiles: true,\n mimeTypes: ['image/*', 'application/pdf'],\n});\n\nif (!result.canceled) {\n for (const file of result.result) {\n console.log(file.uri);\n }\n}\n```"}]}]},"parameters":[{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"File picker options."}]},"type":{"type":"reference","name":"PickMultipleFilesOptions","package":"expo-file-system"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","name":"PickMultipleFilesResult","package":"expo-file-system"}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.pickFileAsync"}},{"name":"pickFileAsync","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A static method that opens a file picker to select a single file of specified type. On iOS, it returns a temporary copy of the file leaving the original file untouched.\n\nSelecting multiple files is not supported yet."}],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`pickFileAsync({initialUri, mimeTypes: mimeType})`"},{"kind":"text","text":" instead."}]},{"tag":"@returns","content":[{"kind":"text","text":"A "},{"kind":"code","text":"`File`"},{"kind":"text","text":" instance or an array of "},{"kind":"code","text":"`File`"},{"kind":"text","text":" instances."}]}]},"parameters":[{"name":"initialUri","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"An optional URI pointing to an initial folder on which the file picker is opened."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"mimeType","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"A mime type that is used to filter out files that can be picked out."}]},"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"array","elementType":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"}}]}],"name":"Promise","package":"typescript"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.pickFileAsync"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemFile.pickFileAsync"}}],"extendedTypes":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.ts","qualifiedName":"ExpoFileSystemModule.FileSystemFile"},"name":"FileSystemFile","package":"expo-file-system","qualifiedName":"ExpoFileSystemModule.FileSystemFile"}],"implementedTypes":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.dom.d.ts","qualifiedName":"Blob"},"name":"Blob","package":"typescript"}]},{"name":"Paths","variant":"declaration","kind":128,"children":[{"name":"constructor","variant":"declaration","kind":512,"signatures":[{"name":"Paths","variant":"signature","kind":16384,"type":{"type":"reference","name":"Paths","package":"expo-file-system"},"inheritedFrom":{"type":"reference","name":"PathUtilities.constructor","package":"expo-file-system"}}],"inheritedFrom":{"type":"reference","name":"PathUtilities.constructor","package":"expo-file-system"}},{"name":"appleSharedContainers","variant":"declaration","kind":262144,"flags":{"isStatic":true},"getSignature":{"name":"appleSharedContainers","variant":"signature","kind":524288,"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Record"},"typeArguments":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"Directory","package":"expo-file-system"}],"name":"Record","package":"typescript"}}},{"name":"availableDiskSpace","variant":"declaration","kind":262144,"flags":{"isStatic":true},"getSignature":{"name":"availableDiskSpace","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"A property that represents the available space on device's internal storage, represented in bytes."}]},"type":{"type":"intrinsic","name":"number"}}},{"name":"bundle","variant":"declaration","kind":262144,"flags":{"isStatic":true},"getSignature":{"name":"bundle","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"A property containing the bundle directory – the directory where assets bundled with the application are stored."}]},"type":{"type":"reference","name":"Directory","package":"expo-file-system"}}},{"name":"cache","variant":"declaration","kind":262144,"flags":{"isStatic":true},"getSignature":{"name":"cache","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"A property containing the cache directory – a place to store files that can be deleted by the system when the device runs low on storage."}]},"type":{"type":"reference","name":"Directory","package":"expo-file-system"}}},{"name":"document","variant":"declaration","kind":262144,"flags":{"isStatic":true},"getSignature":{"name":"document","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"A property containing the document directory – a place to store files that are safe from being deleted by the system."}]},"type":{"type":"reference","name":"Directory","package":"expo-file-system"}}},{"name":"totalDiskSpace","variant":"declaration","kind":262144,"flags":{"isStatic":true},"getSignature":{"name":"totalDiskSpace","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"A property that represents the total space on device's internal storage, represented in bytes."}]},"type":{"type":"intrinsic","name":"number"}}},{"name":"basename","variant":"declaration","kind":2048,"flags":{"isStatic":true,"isInherited":true},"signatures":[{"name":"basename","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Returns the base name of a path."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A string representing the base name."}]}]},"parameters":[{"name":"path","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The path to get the base name from."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}},{"name":"ext","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"An optional file extension."}]},"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"PathUtilities.basename"}}],"inheritedFrom":{"type":"reference","name":"PathUtilities.basename"}},{"name":"dirname","variant":"declaration","kind":2048,"flags":{"isStatic":true,"isInherited":true},"signatures":[{"name":"dirname","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Returns the directory name of a path."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A string representing the directory name."}]}]},"parameters":[{"name":"path","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The path to get the directory name from."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}}],"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"PathUtilities.dirname"}}],"inheritedFrom":{"type":"reference","name":"PathUtilities.dirname"}},{"name":"extname","variant":"declaration","kind":2048,"flags":{"isStatic":true,"isInherited":true},"signatures":[{"name":"extname","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Returns the extension of a path."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A string representing the extension."}]}]},"parameters":[{"name":"path","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The path to get the extension from."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}}],"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"PathUtilities.extname"}}],"inheritedFrom":{"type":"reference","name":"PathUtilities.extname"}},{"name":"info","variant":"declaration","kind":2048,"flags":{"isStatic":true},"signatures":[{"name":"info","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Returns an object that indicates if the specified path represents a directory."}]},"parameters":[{"name":"uris","variant":"param","kind":32768,"flags":{"isRest":true},"type":{"type":"array","elementType":{"type":"intrinsic","name":"string"}}}],"type":{"type":"reference","name":"PathInfo","package":"expo-file-system"}}]},{"name":"isAbsolute","variant":"declaration","kind":2048,"flags":{"isStatic":true,"isInherited":true},"signatures":[{"name":"isAbsolute","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Checks if a path is absolute."}],"blockTags":[{"tag":"@returns","content":[{"kind":"code","text":"`true`"},{"kind":"text","text":" if the path is absolute, "},{"kind":"code","text":"`false`"},{"kind":"text","text":" otherwise."}]}]},"parameters":[{"name":"path","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The path to check."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}}],"type":{"type":"intrinsic","name":"boolean"},"inheritedFrom":{"type":"reference","name":"PathUtilities.isAbsolute"}}],"inheritedFrom":{"type":"reference","name":"PathUtilities.isAbsolute"}},{"name":"join","variant":"declaration","kind":2048,"flags":{"isStatic":true,"isInherited":true},"signatures":[{"name":"join","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Joins path segments into a single path."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A string representing the joined path."}]}]},"parameters":[{"name":"paths","variant":"param","kind":32768,"flags":{"isRest":true},"comment":{"summary":[{"kind":"text","text":"An array of path segments."}]},"type":{"type":"array","elementType":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}}}],"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"PathUtilities.join"}}],"inheritedFrom":{"type":"reference","name":"PathUtilities.join"}},{"name":"normalize","variant":"declaration","kind":2048,"flags":{"isStatic":true,"isInherited":true},"signatures":[{"name":"normalize","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Normalizes a path."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A string representing the normalized path."}]}]},"parameters":[{"name":"path","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The path to normalize."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}}],"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"PathUtilities.normalize"}}],"inheritedFrom":{"type":"reference","name":"PathUtilities.normalize"}},{"name":"parse","variant":"declaration","kind":2048,"flags":{"isStatic":true,"isInherited":true},"signatures":[{"name":"parse","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Parses a path into its components."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"An object containing the parsed path components."}]}]},"parameters":[{"name":"path","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The path to parse."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}}],"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"children":[{"name":"base","variant":"declaration","kind":1024,"type":{"type":"intrinsic","name":"string"}},{"name":"dir","variant":"declaration","kind":1024,"type":{"type":"intrinsic","name":"string"}},{"name":"ext","variant":"declaration","kind":1024,"type":{"type":"intrinsic","name":"string"}},{"name":"name","variant":"declaration","kind":1024,"type":{"type":"intrinsic","name":"string"}},{"name":"root","variant":"declaration","kind":1024,"type":{"type":"intrinsic","name":"string"}}]}},"inheritedFrom":{"type":"reference","name":"PathUtilities.parse"}}],"inheritedFrom":{"type":"reference","name":"PathUtilities.parse"}},{"name":"relative","variant":"declaration","kind":2048,"flags":{"isStatic":true,"isInherited":true},"signatures":[{"name":"relative","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Resolves a relative path to an absolute path."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A string representing the resolved path."}]}]},"parameters":[{"name":"from","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The base path."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}},{"name":"to","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The relative path."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"reference","name":"File","package":"expo-file-system"},{"type":"reference","name":"Directory","package":"expo-file-system"}]}}],"type":{"type":"intrinsic","name":"string"},"inheritedFrom":{"type":"reference","name":"PathUtilities.relative"}}],"inheritedFrom":{"type":"reference","name":"PathUtilities.relative"}}],"extendedTypes":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/pathUtilities/index.ts","qualifiedName":"PathUtilities"},"name":"PathUtilities","package":"expo-file-system"}]},{"name":"UploadTask","variant":"declaration","kind":128,"comment":{"summary":[{"kind":"text","text":"Represents an upload task with progress tracking and cancellation support.\n\nUpload tasks start in the "},{"kind":"code","text":"`idle`"},{"kind":"text","text":" state. Calling "},{"kind":"code","text":"`uploadAsync()`"},{"kind":"text","text":" moves the task to "},{"kind":"code","text":"`active`"},{"kind":"text","text":",\nthen to "},{"kind":"code","text":"`completed`"},{"kind":"text","text":", "},{"kind":"code","text":"`cancelled`"},{"kind":"text","text":", or "},{"kind":"code","text":"`error`"},{"kind":"text","text":"."}]},"children":[{"name":"constructor","variant":"declaration","kind":512,"signatures":[{"name":"UploadTask","variant":"signature","kind":16384,"comment":{"summary":[{"kind":"text","text":"Creates an upload task.\n\nThe task does not start automatically. Call "},{"kind":"code","text":"`uploadAsync()`"},{"kind":"text","text":" to begin uploading."}]},"parameters":[{"name":"file","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The file to upload."}]},"type":{"type":"reference","name":"File","package":"expo-file-system"}},{"name":"url","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The URL to upload the file to."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Upload options."}]},"type":{"type":"reference","name":"UploadOptions","package":"expo-file-system"}}],"type":{"type":"reference","name":"UploadTask","package":"expo-file-system"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.constructor","package":"expo-file-system"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.constructor","package":"expo-file-system"}},{"name":"state","variant":"declaration","kind":262144,"getSignature":{"name":"state","variant":"signature","kind":524288,"comment":{"summary":[{"kind":"text","text":"The current state of the upload task."}]},"type":{"type":"reference","name":"UploadTaskState","package":"expo-file-system"}}},{"name":"addListener","variant":"declaration","kind":2048,"signatures":[{"name":"addListener","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Adds a listener for upload progress events.\n\n> **Note:** Prefer the "},{"kind":"code","text":"`onProgress`"},{"kind":"text","text":" option unless you need manual subscription control."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A subscription handle. Call "},{"kind":"code","text":"`remove()`"},{"kind":"text","text":" to stop listening."}]}]},"parameters":[{"name":"eventName","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The event to listen to. Only "},{"kind":"code","text":"`'progress'`"},{"kind":"text","text":" is supported."}]},"type":{"type":"literal","value":"progress"}},{"name":"listener","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"Invoked with upload progress updates."}]},"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"signatures":[{"name":"__type","variant":"signature","kind":4096,"parameters":[{"name":"data","variant":"param","kind":32768,"type":{"type":"reference","name":"UploadProgress","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"}}]}}}],"type":{"type":"reference","target":{"packageName":"expo-modules-core","packagePath":"src/EventEmitter.ts","qualifiedName":"EventSubscription"},"name":"EventSubscription","package":"expo-modules-core"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.addListener","package":"expo-modules-core"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.addListener","package":"expo-modules-core"}},{"name":"cancel","variant":"declaration","kind":2048,"signatures":[{"name":"cancel","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Cancels the upload operation.\n\nIf "},{"kind":"code","text":"`uploadAsync()`"},{"kind":"text","text":" is pending, its promise is rejected after the native request is cancelled.\nCalling this method after the task reaches "},{"kind":"code","text":"`completed`"},{"kind":"text","text":", "},{"kind":"code","text":"`cancelled`"},{"kind":"text","text":", or "},{"kind":"code","text":"`error`"},{"kind":"text","text":" has no effect."}]},"type":{"type":"intrinsic","name":"void"},"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.cancel"}}],"overwrites":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.cancel"}},{"name":"emit","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"emit","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Synchronously calls all the listeners attached to that specific event.\nThe event can include any number of arguments that will be passed to the listeners."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}},{"name":"args","variant":"param","kind":32768,"flags":{"isRest":true},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Parameters"},"typeArguments":[{"type":"indexedAccess","indexType":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true},"objectType":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.ts","qualifiedName":"UploadTaskEvents"},"name":"UploadTaskEvents","package":"expo-file-system"}}],"name":"Parameters","package":"typescript"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.emit","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.emit","package":"expo-modules-core"}},{"name":"listenerCount","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"listenerCount","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Returns a number of listeners added to the given event."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}}],"type":{"type":"intrinsic","name":"number"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.listenerCount","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.listenerCount","package":"expo-modules-core"}},{"name":"release","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"release","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"A function that detaches the JS and native objects to let the native object deallocate\nbefore the JS object gets deallocated by the JS garbage collector. Any subsequent calls to native\nfunctions of the object will throw an error as it is no longer associated with its native counterpart.\n\nIn most cases, you should never need to use this function, except some specific performance-critical cases when\nmanual memory management makes sense and the native object is known to exclusively retain some native memory\n(such as binary data or image bitmap). Before calling this function, you should ensure that nothing else will use\nthis object later on. Shared objects created by React hooks are usually automatically released in the effect's cleanup phase,\nfor example: "},{"kind":"code","text":"`useVideoPlayer()`"},{"kind":"text","text":" from "},{"kind":"code","text":"`expo-video`"},{"kind":"text","text":" and "},{"kind":"code","text":"`useImage()`"},{"kind":"text","text":" from "},{"kind":"code","text":"`expo-image`"},{"kind":"text","text":"."}]},"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.release","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.release","package":"expo-modules-core"}},{"name":"removeAllListeners","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"removeAllListeners","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Removes all listeners for the given event name."}]},"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"literal","value":"progress"}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.removeAllListeners","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.removeAllListeners","package":"expo-modules-core"}},{"name":"removeListener","variant":"declaration","kind":2048,"flags":{"isInherited":true},"signatures":[{"name":"removeListener","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Removes a listener for the given event name."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}},{"name":"listener","variant":"param","kind":32768,"type":{"type":"indexedAccess","indexType":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true},"objectType":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.ts","qualifiedName":"UploadTaskEvents"},"name":"UploadTaskEvents","package":"expo-file-system"}}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.removeListener","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.removeListener","package":"expo-modules-core"}},{"name":"startObserving","variant":"declaration","kind":2048,"flags":{"isOptional":true,"isInherited":true},"signatures":[{"name":"startObserving","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Function that is automatically invoked when the first listener for an event with the given name is added.\nOverride it in a subclass to perform some additional setup once the event started being observed."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.startObserving","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.startObserving","package":"expo-modules-core"}},{"name":"stopObserving","variant":"declaration","kind":2048,"flags":{"isOptional":true,"isInherited":true},"signatures":[{"name":"stopObserving","variant":"signature","kind":4096,"flags":{"isInherited":true},"comment":{"summary":[{"kind":"text","text":"Function that is automatically invoked when the last listener for an event with the given name is removed.\nOverride it in a subclass to perform some additional cleanup once the event is no longer observed."}]},"typeParameters":[{"name":"EventName","variant":"typeParam","kind":131072,"type":{"type":"literal","value":"progress"}}],"parameters":[{"name":"eventName","variant":"param","kind":32768,"type":{"type":"reference","name":"EventName","package":"expo-modules-core","refersToTypeParameter":true}}],"type":{"type":"intrinsic","name":"void"},"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.stopObserving","package":"expo-modules-core"}}],"inheritedFrom":{"type":"reference","name":"ExpoFileSystem.FileSystemUploadTask.stopObserving","package":"expo-modules-core"}},{"name":"uploadAsync","variant":"declaration","kind":2048,"signatures":[{"name":"uploadAsync","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Starts the upload operation.\n\nThis method can only be called once, while the task is "},{"kind":"code","text":"`idle`"},{"kind":"text","text":". The promise is fulfilled\nwith response metadata and body for completed HTTP responses, including non-2xx status codes.\nIt is rejected when the file cannot be read, the request fails, or the task is cancelled.\n\nIf "},{"kind":"code","text":"`options.signal`"},{"kind":"text","text":" is aborted, the promise is rejected with an "},{"kind":"code","text":"`AbortError`"},{"kind":"text","text":"."}],"blockTags":[{"tag":"@returns","content":[{"kind":"text","text":"A promise fulfilled with the upload response."}]}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","name":"UploadResult","package":"expo-file-system"}],"name":"Promise","package":"typescript"}}]}],"extendedTypes":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.ts","qualifiedName":"ExpoFileSystemModule.FileSystemUploadTask"},"name":"FileSystemUploadTask","package":"expo-file-system","qualifiedName":"ExpoFileSystemModule.FileSystemUploadTask"}]},{"name":"FileHandle","variant":"declaration","kind":256,"children":[{"name":"offset","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"A property that indicates the current byte offset in the file. Calling "},{"kind":"code","text":"`readBytes`"},{"kind":"text","text":" or "},{"kind":"code","text":"`writeBytes`"},{"kind":"text","text":" will read or write a specified amount of bytes starting from this offset. The offset is incremented by the number of bytes read or written.\nThe offset can be set to any value within the file size. If the offset is set to a value greater than the file size, the next write operation will append data to the end of the file.\nNull if the file handle is closed."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"number"},{"type":"literal","value":null}]}},{"name":"size","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"A size of the file in bytes or "},{"kind":"code","text":"`null`"},{"kind":"text","text":" if the file handle is closed."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"number"},{"type":"literal","value":null}]}},{"name":"close","variant":"declaration","kind":2048,"signatures":[{"name":"close","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Closes the file handle. This allows the file to be deleted, moved or read by a different process. Subsequent calls to "},{"kind":"code","text":"`readBytes`"},{"kind":"text","text":" or "},{"kind":"code","text":"`writeBytes`"},{"kind":"text","text":" will throw an error."}]},"type":{"type":"intrinsic","name":"void"}}]},{"name":"readBytes","variant":"declaration","kind":2048,"signatures":[{"name":"readBytes","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Reads the specified amount of bytes from the file at the current offset. Max amount of bytes read at once is capped by ArrayBuffer max size (32 bit signed MAX_INT on Android and 64 bit on iOS), but you can read from a FileHandle multiple times."}]},"parameters":[{"name":"length","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"The number of bytes to read."}]},"type":{"type":"intrinsic","name":"number"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Uint8Array"},"typeArguments":[{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"ArrayBuffer"},"name":"ArrayBuffer","package":"typescript"}],"name":"Uint8Array","package":"typescript"}}]},{"name":"writeBytes","variant":"declaration","kind":2048,"signatures":[{"name":"writeBytes","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Writes the specified bytes to the file at the current offset."}]},"parameters":[{"name":"bytes","variant":"param","kind":32768,"comment":{"summary":[{"kind":"text","text":"A "},{"kind":"code","text":"`Uint8Array`"},{"kind":"text","text":" array containing bytes to write."}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Uint8Array"},"name":"Uint8Array","package":"typescript"}}],"type":{"type":"intrinsic","name":"void"}}]}]},{"name":"DirectoryCreateOptions","variant":"declaration","kind":2097152,"children":[{"name":"idempotent","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"This flag controls whether the "},{"kind":"code","text":"`create`"},{"kind":"text","text":" operation is idempotent\n(safe to call multiple times without error).\n\nIf "},{"kind":"code","text":"`true`"},{"kind":"text","text":", creating a file or directory that already exists will succeed silently.\nIf "},{"kind":"code","text":"`false`"},{"kind":"text","text":", an error will be thrown when the target already exists."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"false"}]}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"intermediates","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Whether to create intermediate directories if they do not exist."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"false"}]}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"overwrite","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Whether to overwrite the directory if it exists."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"false"}]}]},"type":{"type":"intrinsic","name":"boolean"}}]},{"name":"DirectoryInfo","variant":"declaration","kind":2097152,"children":[{"name":"creationTime","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"A creation time of the directory expressed in milliseconds since epoch. Returns null if the Android version is earlier than API 26."}]},"type":{"type":"intrinsic","name":"number"}},{"name":"exists","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Indicates whether the directory exists."}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"files","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"A list of file names contained within a directory."}]},"type":{"type":"array","elementType":{"type":"intrinsic","name":"string"}}},{"name":"modificationTime","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The last modification time of the directory expressed in milliseconds since epoch."}]},"type":{"type":"intrinsic","name":"number"}},{"name":"size","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The size of the file in bytes."}]},"type":{"type":"intrinsic","name":"number"}},{"name":"uri","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"A "},{"kind":"code","text":"`file://`"},{"kind":"text","text":" URI pointing to the directory."}]},"type":{"type":"intrinsic","name":"string"}}]},{"name":"DownloadOptions","variant":"declaration","kind":2097152,"children":[{"name":"headers","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The headers to send with the request."}]},"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"indexSignatures":[{"name":"__index","variant":"signature","kind":8192,"parameters":[{"name":"key","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"intrinsic","name":"string"}}]}}},{"name":"idempotent","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"This flag controls whether the "},{"kind":"code","text":"`download`"},{"kind":"text","text":" operation is idempotent\n(safe to call multiple times without error).\n\nIf "},{"kind":"code","text":"`true`"},{"kind":"text","text":", downloading a file that already exists overwrites the previous one.\nIf "},{"kind":"code","text":"`false`"},{"kind":"text","text":", an error is thrown when the target file already exists."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"false"}]}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"onProgress","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"A callback that is invoked with progress updates during the download."}]},"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"signatures":[{"name":"__type","variant":"signature","kind":4096,"parameters":[{"name":"data","variant":"param","kind":32768,"type":{"type":"reference","name":"DownloadProgress","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"}}]}}},{"name":"signal","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"An "},{"kind":"code","text":"`AbortSignal`"},{"kind":"text","text":" that can be used to cancel the download.\nWhen the signal is aborted, the download is cancelled and the promise rejects with an "},{"kind":"code","text":"`AbortError`"},{"kind":"text","text":"."}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.dom.d.ts","qualifiedName":"AbortSignal"},"name":"AbortSignal","package":"typescript"}}]},{"name":"DownloadPauseState","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Represents the state of a paused download that can be persisted and resumed later."}]},"children":[{"name":"fileUri","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The destination file or directory URI."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"headers","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Custom headers that were used for the download request."}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Record"},"typeArguments":[{"type":"intrinsic","name":"string"},{"type":"intrinsic","name":"string"}],"name":"Record","package":"typescript"}},{"name":"isDirectory","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Whether the destination is a directory. When "},{"kind":"code","text":"`true`"},{"kind":"text","text":", the filename is derived from the URL."}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"resumeData","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Platform-specific opaque resume data."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"url","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The URL of the download."}]},"type":{"type":"intrinsic","name":"string"}}]},{"name":"DownloadProgress","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Data provided to the "},{"kind":"code","text":"`onProgress`"},{"kind":"text","text":" callback during a file download."}]},"children":[{"name":"bytesWritten","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The number of bytes written so far."}]},"type":{"type":"intrinsic","name":"number"}},{"name":"totalBytes","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The total number of bytes expected to be downloaded. "},{"kind":"code","text":"`-1`"},{"kind":"text","text":" if the server did not provide a "},{"kind":"code","text":"`Content-Length`"},{"kind":"text","text":" header."}]},"type":{"type":"intrinsic","name":"number"}}]},{"name":"DownloadTaskOptions","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Options for download task operations."}]},"children":[{"name":"headers","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Custom headers to include in the request."}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Record"},"typeArguments":[{"type":"intrinsic","name":"string"},{"type":"intrinsic","name":"string"}],"name":"Record","package":"typescript"}},{"name":"onProgress","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Callback for download progress updates."}]},"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"signatures":[{"name":"__type","variant":"signature","kind":4096,"parameters":[{"name":"data","variant":"param","kind":32768,"type":{"type":"reference","name":"DownloadProgress","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"}}]}}},{"name":"sessionType","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Determines whether the iOS native session should continue in the background.\nAndroid accepts this option for API consistency and ignores it.\n\nWhen set to "},{"kind":"code","text":"`'background'`"},{"kind":"text","text":", the native transfer may continue after the app is\nsuspended. However, the JavaScript "},{"kind":"code","text":"`DownloadTask`"},{"kind":"text","text":" instance is not\nrestored if the app is terminated or relaunched, so its promise, progress\ncallbacks, and cancellation state are only available while the original JS\nruntime is still alive."}],"blockTags":[{"tag":"@platform","content":[{"kind":"text","text":"ios"}]},{"tag":"@default","content":[{"kind":"text","text":"'background'"}]}]},"type":{"type":"reference","name":"NetworkTaskSessionType","package":"expo-file-system"}},{"name":"signal","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"AbortSignal to cancel the download."}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.dom.d.ts","qualifiedName":"AbortSignal"},"name":"AbortSignal","package":"typescript"}}]},{"name":"DownloadTaskState","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Represents the current state of a download task."}]},"type":{"type":"union","types":[{"type":"literal","value":"idle"},{"type":"literal","value":"active"},{"type":"literal","value":"paused"},{"type":"literal","value":"completed"},{"type":"literal","value":"cancelled"},{"type":"literal","value":"error"}]}},{"name":"FileCreateOptions","variant":"declaration","kind":2097152,"children":[{"name":"intermediates","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Whether to create intermediate directories if they do not exist."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"false"}]}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"overwrite","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Whether to overwrite the file if it exists."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"false"}]}]},"type":{"type":"intrinsic","name":"boolean"}}]},{"name":"FileInfo","variant":"declaration","kind":2097152,"children":[{"name":"creationTime","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"A creation time of the file expressed in milliseconds since epoch. Returns null if the Android version is earlier than API 26."}]},"type":{"type":"intrinsic","name":"number"}},{"name":"exists","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Indicates whether the file exists."}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"md5","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Present if the "},{"kind":"code","text":"`md5`"},{"kind":"text","text":" option was truthy. Contains the MD5 hash of the file."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"modificationTime","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The last modification time of the file expressed in milliseconds since epoch."}]},"type":{"type":"intrinsic","name":"number"}},{"name":"size","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The size of the file in bytes."}]},"type":{"type":"intrinsic","name":"number"}},{"name":"uri","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"A URI pointing to the file. This is the same as the "},{"kind":"code","text":"`fileUri`"},{"kind":"text","text":" input parameter\nand preserves its scheme (for example, "},{"kind":"code","text":"`file://`"},{"kind":"text","text":" or "},{"kind":"code","text":"`content://`"},{"kind":"text","text":")."}]},"type":{"type":"intrinsic","name":"string"}}]},{"name":"FileWriteOptions","variant":"declaration","kind":2097152,"children":[{"name":"append","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Whether to append the contents to the end of the file or overwrite the existing file."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"false"}]}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"encoding","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The encoding format to use when writing the file."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"FileSystem.EncodingType.UTF8"}]}]},"type":{"type":"union","types":[{"type":"reference","name":"EncodingType","package":"expo-file-system"},{"type":"literal","value":"utf8"},{"type":"literal","value":"base64"}]}}]},{"name":"InfoOptions","variant":"declaration","kind":2097152,"children":[{"name":"md5","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Whether to return the MD5 hash of the file."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"false"}]}]},"type":{"type":"intrinsic","name":"boolean"}}]},{"name":"NetworkTaskSessionType","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"The native URL session mode used by iOS upload and download tasks."}]},"type":{"type":"union","types":[{"type":"literal","value":"background"},{"type":"literal","value":"foreground"}]}},{"name":"PathInfo","variant":"declaration","kind":2097152,"children":[{"name":"exists","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Indicates whether the path exists. Returns true if it exists; false if the path does not exist or if there is no read permission."}]},"type":{"type":"intrinsic","name":"boolean"}},{"name":"isDirectory","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Indicates whether the path is a directory. Returns true or false if the path exists; otherwise, returns null."}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"boolean"},{"type":"literal","value":null}]}}]},{"name":"PickFileGeneralOptions","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Shared options accepted by file picker calls."}]},"children":[{"name":"initialUri","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"A URI pointing to an initial folder in which the file picker is opened."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"mimeTypes","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The [MIME type(s)](https://en.wikipedia.org/wiki/Media_type) of the documents that are available\nto be picked. It also supports wildcards like "},{"kind":"code","text":"`'image/*'`"},{"kind":"text","text":" to choose any image. To allow any type\nof document you can use "},{"kind":"code","text":"`'*/*'`"},{"kind":"text","text":"."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"'*/*'"}]}]},"type":{"type":"union","types":[{"type":"intrinsic","name":"string"},{"type":"array","elementType":{"type":"intrinsic","name":"string"}}]}},{"name":"multipleFiles","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Allows multiple files to be selected from the system UI."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"false"}]}]},"type":{"type":"intrinsic","name":"boolean"}}]},{"name":"PickMultipleFilesOptions","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Options for picking multiple files."}]},"type":{"type":"intersection","types":[{"type":"reference","name":"PickFileGeneralOptions","package":"expo-file-system"},{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"children":[{"name":"multipleFiles","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Allows multiple files to be selected from the system UI."}]},"type":{"type":"literal","value":true}}]}}]}},{"name":"PickMultipleFilesResult","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Result type for picking multiple files.\n\nSuccessful picks return "},{"kind":"code","text":"`{ result: File[], canceled: false }`"},{"kind":"text","text":". Canceled picks return\n"},{"kind":"code","text":"`{ result: null, canceled: true }`"},{"kind":"text","text":"."}]},"type":{"type":"union","types":[{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"children":[{"name":"canceled","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Indicates that the picker completed with selected files."}]},"type":{"type":"literal","value":false}},{"name":"result","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The selected files."}]},"type":{"type":"array","elementType":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"}}}]}},{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"children":[{"name":"canceled","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Indicates that the user canceled the picker without selecting files."}]},"type":{"type":"literal","value":true}},{"name":"result","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Always "},{"kind":"code","text":"`null`"},{"kind":"text","text":" when the picker is canceled."}]},"type":{"type":"literal","value":null}}]}}]}},{"name":"PickSingleFileOptions","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Options for picking a single file."}]},"type":{"type":"intersection","types":[{"type":"reference","name":"PickFileGeneralOptions","package":"expo-file-system"},{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"children":[{"name":"multipleFiles","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Keeps the picker in single-file mode. Omit this property or set it to "},{"kind":"code","text":"`false`"},{"kind":"text","text":" when selecting one file."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"false"}]}]},"type":{"type":"literal","value":false}}]}}]}},{"name":"PickSingleFileResult","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Result type for picking a single file.\n\nSuccessful picks return "},{"kind":"code","text":"`{ result: File, canceled: false }`"},{"kind":"text","text":". Canceled picks return\n"},{"kind":"code","text":"`{ result: null, canceled: true }`"},{"kind":"text","text":"."}]},"type":{"type":"union","types":[{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"children":[{"name":"canceled","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Indicates that the picker completed with a selected file."}]},"type":{"type":"literal","value":false}},{"name":"result","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The selected file."}]},"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"}}]}},{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"children":[{"name":"canceled","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Indicates that the user canceled the picker without selecting files."}]},"type":{"type":"literal","value":true}},{"name":"result","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"Always "},{"kind":"code","text":"`null`"},{"kind":"text","text":" when the picker is canceled."}]},"type":{"type":"literal","value":null}}]}}]}},{"name":"RelocationOptions","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Options for moving or copying files and directories."}]},"children":[{"name":"overwrite","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Whether to overwrite the destination if it exists."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"false"}]}]},"type":{"type":"intrinsic","name":"boolean"}}]},{"name":"UploadOptions","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Options for upload operations."}]},"children":[{"name":"fieldName","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The field name for the file in multipart uploads."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"'file'"}]}]},"type":{"type":"intrinsic","name":"string"}},{"name":"headers","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Custom headers to include in the request."}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Record"},"typeArguments":[{"type":"intrinsic","name":"string"},{"type":"intrinsic","name":"string"}],"name":"Record","package":"typescript"}},{"name":"httpMethod","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The HTTP method to use."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"'POST'"}]}]},"type":{"type":"union","types":[{"type":"literal","value":"POST"},{"type":"literal","value":"PUT"},{"type":"literal","value":"PATCH"}]}},{"name":"mimeType","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The MIME type of the file."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"onProgress","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Callback for upload progress updates.\n\n> **Note:** For multipart uploads, the reported bytes may include multipart framing overhead\n> (boundary strings, headers, form parameters) in addition to the file content."}]},"type":{"type":"reflection","declaration":{"name":"__type","variant":"declaration","kind":65536,"signatures":[{"name":"__type","variant":"signature","kind":4096,"parameters":[{"name":"data","variant":"param","kind":32768,"type":{"type":"reference","name":"UploadProgress","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"void"}}]}}},{"name":"parameters","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Additional form parameters to include in multipart uploads."}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Record"},"typeArguments":[{"type":"intrinsic","name":"string"},{"type":"intrinsic","name":"string"}],"name":"Record","package":"typescript"}},{"name":"sessionType","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Determines whether the iOS native session should continue in the background.\n\nWhen set to "},{"kind":"code","text":"`'background'`"},{"kind":"text","text":", the native transfer may continue after the app is\nsuspended. However, the JavaScript "},{"kind":"code","text":"`UploadTask`"},{"kind":"text","text":" instance is not\nrestored if the app is terminated or relaunched, so its promise, progress\ncallbacks, and cancellation state are only available while the original JS\nruntime is still alive."}],"blockTags":[{"tag":"@platform","content":[{"kind":"text","text":"ios"}]},{"tag":"@default","content":[{"kind":"text","text":"'background'"}]}]},"type":{"type":"reference","name":"NetworkTaskSessionType","package":"expo-file-system"}},{"name":"signal","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"An "},{"kind":"code","text":"`AbortSignal`"},{"kind":"text","text":" that can be used to cancel the upload.\nWhen the signal is aborted, the upload is cancelled and the promise rejects with an "},{"kind":"code","text":"`AbortError`"},{"kind":"text","text":"."}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.dom.d.ts","qualifiedName":"AbortSignal"},"name":"AbortSignal","package":"typescript"}},{"name":"uploadType","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The type of upload operation."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"UploadType.BINARY_CONTENT"}]}]},"type":{"type":"reference","name":"UploadType","package":"expo-file-system"}}]},{"name":"UploadProgress","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Represents upload progress data."}]},"children":[{"name":"bytesSent","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The number of bytes sent so far."}]},"type":{"type":"intrinsic","name":"number"}},{"name":"totalBytes","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The total number of bytes to send."}]},"type":{"type":"intrinsic","name":"number"}}]},{"name":"UploadResult","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Represents the result of an upload operation."}]},"children":[{"name":"body","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The response body as a string."}]},"type":{"type":"intrinsic","name":"string"}},{"name":"headers","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The response headers."}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Record"},"typeArguments":[{"type":"intrinsic","name":"string"},{"type":"intrinsic","name":"string"}],"name":"Record","package":"typescript"}},{"name":"status","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The HTTP status code."}]},"type":{"type":"intrinsic","name":"number"}}]},{"name":"UploadTaskState","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Represents the current state of an upload task."}],"blockTags":[{"tag":"@expandType","content":[{"kind":"text","text":"TaskState"}]}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Exclude"},"typeArguments":[{"type":"union","types":[{"type":"literal","value":"idle"},{"type":"literal","value":"active"},{"type":"literal","value":"paused"},{"type":"literal","value":"completed"},{"type":"literal","value":"cancelled"},{"type":"literal","value":"error"}]},{"type":"literal","value":"paused"}],"name":"Exclude","package":"typescript"}},{"name":"WatchEvent","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Describes a change detected by a file system watcher."}]},"children":[{"name":"nativeEventFlags","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Raw platform-specific event flags for advanced use cases.\nOn Android: FileObserver event flags.\nOn iOS: DispatchSource.FileSystemEvent flags."}]},"type":{"type":"intrinsic","name":"number"}},{"name":"newTarget","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"For rename events, the new path after rename.\nPopulated when MOVED_FROM and MOVED_TO events are correlated within the debounce window."}],"blockTags":[{"tag":"@platform","content":[{"kind":"text","text":"android"}]}]},"type":{"type":"reference","name":"T","package":"expo-file-system","refersToTypeParameter":true}},{"name":"target","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The file or directory that changed. For "},{"kind":"code","text":"`renamed`"},{"kind":"text","text":" events, this is the original path before the rename."}]},"type":{"type":"reference","name":"T","package":"expo-file-system","refersToTypeParameter":true}},{"name":"type","variant":"declaration","kind":1024,"comment":{"summary":[{"kind":"text","text":"The kind of change that occurred."}]},"type":{"type":"reference","name":"WatchEventType","package":"expo-file-system"}}],"typeParameters":[{"name":"T","variant":"typeParam","kind":131072,"type":{"type":"union","types":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"File"},"name":"File","package":"expo-file-system"},{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/ExpoFileSystem.types.ts","qualifiedName":"Directory"},"name":"Directory","package":"expo-file-system"}]}}]},{"name":"WatchEventType","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"The type of change that triggered a watcher event.\n- "},{"kind":"code","text":"`created`"},{"kind":"text","text":" — a new file or directory was created\n- "},{"kind":"code","text":"`modified`"},{"kind":"text","text":" — the file contents or metadata changed\n- "},{"kind":"code","text":"`deleted`"},{"kind":"text","text":" — the file or directory was removed\n- "},{"kind":"code","text":"`renamed`"},{"kind":"text","text":" — the file or directory was renamed or moved"}]},"type":{"type":"union","types":[{"type":"literal","value":"created"},{"type":"literal","value":"modified"},{"type":"literal","value":"deleted"},{"type":"literal","value":"renamed"}]}},{"name":"WatchOptions","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"Options for configuring a file system watcher."}]},"children":[{"name":"debounce","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"The debounce interval in milliseconds for coalescing rapid successive events into a single callback."}],"blockTags":[{"tag":"@default","content":[{"kind":"text","text":"100"}]}]},"type":{"type":"intrinsic","name":"number"}},{"name":"events","variant":"declaration","kind":1024,"flags":{"isOptional":true},"comment":{"summary":[{"kind":"text","text":"Limits which event types trigger the callback. If omitted, all event types are observed.\n\nOn iOS, directory watchers only provide coarse-grained notifications that the directory itself\nchanged, so filtering for child-level "},{"kind":"code","text":"`created`"},{"kind":"text","text":", "},{"kind":"code","text":"`deleted`"},{"kind":"text","text":", or "},{"kind":"code","text":"`renamed`"},{"kind":"text","text":" events is not reliable."}]},"type":{"type":"array","elementType":{"type":"reference","name":"WatchEventType","package":"expo-file-system"}}}]},{"name":"WatchSubscription","variant":"declaration","kind":2097152,"comment":{"summary":[{"kind":"text","text":"A handle to an active file system watcher. Call "},{"kind":"code","text":"`remove()`"},{"kind":"text","text":" to stop watching and release resources."}]},"children":[{"name":"remove","variant":"declaration","kind":2048,"signatures":[{"name":"remove","variant":"signature","kind":4096,"comment":{"summary":[{"kind":"text","text":"Stops watching for changes and releases native resources.\nAfter calling this method, the callback will no longer be invoked."}]},"type":{"type":"intrinsic","name":"void"}}]}]},{"name":"copyAsync","variant":"declaration","kind":64,"signatures":[{"name":"copyAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`new File().copy()`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"options","variant":"param","kind":32768,"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"RelocatingOptions"},"name":"RelocatingOptions","package":"expo-file-system"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"}}]},{"name":"createDownloadResumable","variant":"declaration","kind":64,"signatures":[{"name":"createDownloadResumable","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"uri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"DownloadOptions"},"name":"DownloadOptions","package":"expo-file-system"}},{"name":"callback","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"FileSystemNetworkTaskProgressCallback"},"typeArguments":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"DownloadProgressData"},"name":"DownloadProgressData","package":"expo-file-system"}],"name":"FileSystemNetworkTaskProgressCallback","package":"expo-file-system"}},{"name":"resumeData","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"intrinsic","name":"any"}}]},{"name":"createUploadTask","variant":"declaration","kind":64,"signatures":[{"name":"createUploadTask","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"url","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"FileSystemUploadOptions"},"name":"FileSystemUploadOptions","package":"expo-file-system"}},{"name":"callback","variant":"param","kind":32768,"flags":{"isOptional":true},"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"FileSystemNetworkTaskProgressCallback"},"typeArguments":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"UploadProgressData"},"name":"UploadProgressData","package":"expo-file-system"}],"name":"FileSystemNetworkTaskProgressCallback","package":"expo-file-system"}}],"type":{"type":"intrinsic","name":"any"}}]},{"name":"deleteAsync","variant":"declaration","kind":64,"signatures":[{"name":"deleteAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`new File().delete()`"},{"kind":"text","text":" or "},{"kind":"code","text":"`new Directory().delete()`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"DeletingOptions"},"name":"DeletingOptions","package":"expo-file-system"},"defaultValue":"{}"}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"}}]},{"name":"deleteLegacyDocumentDirectoryAndroid","variant":"declaration","kind":64,"signatures":[{"name":"deleteLegacyDocumentDirectoryAndroid","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[]}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"}}]},{"name":"downloadAsync","variant":"declaration","kind":64,"signatures":[{"name":"downloadAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`File.downloadFileAsync`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"uri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"DownloadOptions"},"name":"DownloadOptions","package":"expo-file-system"},"defaultValue":"{}"}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"FileSystemDownloadResult"},"name":"FileSystemDownloadResult","package":"expo-file-system"}],"name":"Promise","package":"typescript"}}]},{"name":"getContentUriAsync","variant":"declaration","kind":64,"signatures":[{"name":"getContentUriAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"string"}],"name":"Promise","package":"typescript"}}]},{"name":"getFreeDiskStorageAsync","variant":"declaration","kind":64,"signatures":[{"name":"getFreeDiskStorageAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`Paths.availableDiskSpace`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"number"}],"name":"Promise","package":"typescript"}}]},{"name":"getInfoAsync","variant":"declaration","kind":64,"signatures":[{"name":"getInfoAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`new File().info`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"InfoOptions"},"name":"InfoOptions","package":"expo-file-system"},"defaultValue":"{}"}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"FileInfo"},"name":"FileInfo","package":"expo-file-system"}],"name":"Promise","package":"typescript"}}]},{"name":"getTotalDiskCapacityAsync","variant":"declaration","kind":64,"signatures":[{"name":"getTotalDiskCapacityAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`Paths.totalDiskSpace`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"number"}],"name":"Promise","package":"typescript"}}]},{"name":"makeDirectoryAsync","variant":"declaration","kind":64,"signatures":[{"name":"makeDirectoryAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`new Directory().create()`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"MakeDirectoryOptions"},"name":"MakeDirectoryOptions","package":"expo-file-system"},"defaultValue":"{}"}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"}}]},{"name":"moveAsync","variant":"declaration","kind":64,"signatures":[{"name":"moveAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`new File().move()`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"options","variant":"param","kind":32768,"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"RelocatingOptions"},"name":"RelocatingOptions","package":"expo-file-system"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"}}]},{"name":"readAsStringAsync","variant":"declaration","kind":64,"signatures":[{"name":"readAsStringAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`new File().text()`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"ReadingOptions"},"name":"ReadingOptions","package":"expo-file-system"},"defaultValue":"{}"}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"string"}],"name":"Promise","package":"typescript"}}]},{"name":"readDirectoryAsync","variant":"declaration","kind":64,"signatures":[{"name":"readDirectoryAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`new Directory().list()`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"array","elementType":{"type":"intrinsic","name":"string"}}],"name":"Promise","package":"typescript"}}]},{"name":"uploadAsync","variant":"declaration","kind":64,"signatures":[{"name":"uploadAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`@expo/fetch`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"url","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"FileSystemUploadOptions"},"name":"FileSystemUploadOptions","package":"expo-file-system"},"defaultValue":"{}"}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"FileSystemUploadResult"},"name":"FileSystemUploadResult","package":"expo-file-system"}],"name":"Promise","package":"typescript"}}]},{"name":"writeAsStringAsync","variant":"declaration","kind":64,"signatures":[{"name":"writeAsStringAsync","variant":"signature","kind":4096,"comment":{"summary":[],"blockTags":[{"tag":"@deprecated","content":[{"kind":"text","text":"Use "},{"kind":"code","text":"`new File().write()`"},{"kind":"text","text":" or import this method from "},{"kind":"code","text":"`expo-file-system/legacy`"},{"kind":"text","text":". This method will throw in runtime."}]}]},"parameters":[{"name":"fileUri","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"contents","variant":"param","kind":32768,"type":{"type":"intrinsic","name":"string"}},{"name":"options","variant":"param","kind":32768,"type":{"type":"reference","target":{"packageName":"expo-file-system","packagePath":"src/legacy/FileSystem.types.ts","qualifiedName":"WritingOptions"},"name":"WritingOptions","package":"expo-file-system"},"defaultValue":"{}"}],"type":{"type":"reference","target":{"packageName":"typescript","packagePath":"lib/lib.es5.d.ts","qualifiedName":"Promise"},"typeArguments":[{"type":"intrinsic","name":"void"}],"name":"Promise","package":"typescript"}}]}],"packageName":"expo-file-system"} \ No newline at end of file diff --git a/docs/public/static/images/expo-ui/alertdialog/android-dark.webp b/docs/public/static/images/expo-ui/alertdialog/android-dark.webp new file mode 100644 index 00000000000000..043a86e02bbba8 Binary files /dev/null and b/docs/public/static/images/expo-ui/alertdialog/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/alertdialog/android-light.webp b/docs/public/static/images/expo-ui/alertdialog/android-light.webp new file mode 100644 index 00000000000000..b7236325ba0178 Binary files /dev/null and b/docs/public/static/images/expo-ui/alertdialog/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/badge/android-dark.webp b/docs/public/static/images/expo-ui/badge/android-dark.webp new file mode 100644 index 00000000000000..b67c1ace5a6c58 Binary files /dev/null and b/docs/public/static/images/expo-ui/badge/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/badge/android-light.webp b/docs/public/static/images/expo-ui/badge/android-light.webp new file mode 100644 index 00000000000000..c7deb28da9509e Binary files /dev/null and b/docs/public/static/images/expo-ui/badge/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/badgedbox/android-dark.webp b/docs/public/static/images/expo-ui/badgedbox/android-dark.webp new file mode 100644 index 00000000000000..b67c1ace5a6c58 Binary files /dev/null and b/docs/public/static/images/expo-ui/badgedbox/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/badgedbox/android-light.webp b/docs/public/static/images/expo-ui/badgedbox/android-light.webp new file mode 100644 index 00000000000000..c7deb28da9509e Binary files /dev/null and b/docs/public/static/images/expo-ui/badgedbox/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/basicalertdialog/android-dark.webp b/docs/public/static/images/expo-ui/basicalertdialog/android-dark.webp new file mode 100644 index 00000000000000..7dd386d780c97d Binary files /dev/null and b/docs/public/static/images/expo-ui/basicalertdialog/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/basicalertdialog/android-light.webp b/docs/public/static/images/expo-ui/basicalertdialog/android-light.webp new file mode 100644 index 00000000000000..5dee01d6fe1d4d Binary files /dev/null and b/docs/public/static/images/expo-ui/basicalertdialog/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/bottomsheet/android-dark.webp b/docs/public/static/images/expo-ui/bottomsheet/android-dark.webp new file mode 100644 index 00000000000000..4da8be8de13a46 Binary files /dev/null and b/docs/public/static/images/expo-ui/bottomsheet/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/bottomsheet/android-light.webp b/docs/public/static/images/expo-ui/bottomsheet/android-light.webp new file mode 100644 index 00000000000000..8cedb350f28589 Binary files /dev/null and b/docs/public/static/images/expo-ui/bottomsheet/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/box/android-dark.webp b/docs/public/static/images/expo-ui/box/android-dark.webp new file mode 100644 index 00000000000000..4ac1389f9b3cca Binary files /dev/null and b/docs/public/static/images/expo-ui/box/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/box/android-light.webp b/docs/public/static/images/expo-ui/box/android-light.webp new file mode 100644 index 00000000000000..0eee5f6aef0fc9 Binary files /dev/null and b/docs/public/static/images/expo-ui/box/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/button/android-dark.webp b/docs/public/static/images/expo-ui/button/android-dark.webp new file mode 100644 index 00000000000000..449f33981e5fce Binary files /dev/null and b/docs/public/static/images/expo-ui/button/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/button/android-light.webp b/docs/public/static/images/expo-ui/button/android-light.webp new file mode 100644 index 00000000000000..0600d306b2fb89 Binary files /dev/null and b/docs/public/static/images/expo-ui/button/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/card/android-dark.webp b/docs/public/static/images/expo-ui/card/android-dark.webp new file mode 100644 index 00000000000000..c96fb5b9544b32 Binary files /dev/null and b/docs/public/static/images/expo-ui/card/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/card/android-light.webp b/docs/public/static/images/expo-ui/card/android-light.webp new file mode 100644 index 00000000000000..55ae3cb0ca9590 Binary files /dev/null and b/docs/public/static/images/expo-ui/card/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/carousel/android-dark.webp b/docs/public/static/images/expo-ui/carousel/android-dark.webp new file mode 100644 index 00000000000000..b76dbfd5a598e5 Binary files /dev/null and b/docs/public/static/images/expo-ui/carousel/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/carousel/android-light.webp b/docs/public/static/images/expo-ui/carousel/android-light.webp new file mode 100644 index 00000000000000..a2b6b59364d0ba Binary files /dev/null and b/docs/public/static/images/expo-ui/carousel/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/checkbox/android-dark.webp b/docs/public/static/images/expo-ui/checkbox/android-dark.webp new file mode 100644 index 00000000000000..b97f2a197eb77f Binary files /dev/null and b/docs/public/static/images/expo-ui/checkbox/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/checkbox/android-light.webp b/docs/public/static/images/expo-ui/checkbox/android-light.webp new file mode 100644 index 00000000000000..17d6ee3ce3c9aa Binary files /dev/null and b/docs/public/static/images/expo-ui/checkbox/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/chip/android-dark.webp b/docs/public/static/images/expo-ui/chip/android-dark.webp new file mode 100644 index 00000000000000..62b0f1b8d0206c Binary files /dev/null and b/docs/public/static/images/expo-ui/chip/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/chip/android-light.webp b/docs/public/static/images/expo-ui/chip/android-light.webp new file mode 100644 index 00000000000000..bacc41130721b7 Binary files /dev/null and b/docs/public/static/images/expo-ui/chip/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/column/android-dark.webp b/docs/public/static/images/expo-ui/column/android-dark.webp new file mode 100644 index 00000000000000..72de860fcd2dc8 Binary files /dev/null and b/docs/public/static/images/expo-ui/column/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/column/android-light.webp b/docs/public/static/images/expo-ui/column/android-light.webp new file mode 100644 index 00000000000000..8e93b562f146cd Binary files /dev/null and b/docs/public/static/images/expo-ui/column/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/contextMenu/ios.png b/docs/public/static/images/expo-ui/contextMenu/ios.png deleted file mode 100644 index 8956b8d5dc2064..00000000000000 Binary files a/docs/public/static/images/expo-ui/contextMenu/ios.png and /dev/null differ diff --git a/docs/public/static/images/expo-ui/datetimepicker/android-dark.webp b/docs/public/static/images/expo-ui/datetimepicker/android-dark.webp new file mode 100644 index 00000000000000..3e76e579b124d9 Binary files /dev/null and b/docs/public/static/images/expo-ui/datetimepicker/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/datetimepicker/android-light.webp b/docs/public/static/images/expo-ui/datetimepicker/android-light.webp new file mode 100644 index 00000000000000..57c8fa0068a812 Binary files /dev/null and b/docs/public/static/images/expo-ui/datetimepicker/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/divider/android-dark.webp b/docs/public/static/images/expo-ui/divider/android-dark.webp new file mode 100644 index 00000000000000..759349a9b492b0 Binary files /dev/null and b/docs/public/static/images/expo-ui/divider/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/divider/android-light.webp b/docs/public/static/images/expo-ui/divider/android-light.webp new file mode 100644 index 00000000000000..3998d212f5b227 Binary files /dev/null and b/docs/public/static/images/expo-ui/divider/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/dockedsearchbar/android-dark.webp b/docs/public/static/images/expo-ui/dockedsearchbar/android-dark.webp new file mode 100644 index 00000000000000..937b074147ded7 Binary files /dev/null and b/docs/public/static/images/expo-ui/dockedsearchbar/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/dockedsearchbar/android-light.webp b/docs/public/static/images/expo-ui/dockedsearchbar/android-light.webp new file mode 100644 index 00000000000000..d8422f6af152f6 Binary files /dev/null and b/docs/public/static/images/expo-ui/dockedsearchbar/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/dropdownmenu/android-dark.webp b/docs/public/static/images/expo-ui/dropdownmenu/android-dark.webp new file mode 100644 index 00000000000000..179fc9debe23c3 Binary files /dev/null and b/docs/public/static/images/expo-ui/dropdownmenu/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/dropdownmenu/android-light.webp b/docs/public/static/images/expo-ui/dropdownmenu/android-light.webp new file mode 100644 index 00000000000000..e10a9999481d53 Binary files /dev/null and b/docs/public/static/images/expo-ui/dropdownmenu/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/exposeddropdownmenubox/android-dark.webp b/docs/public/static/images/expo-ui/exposeddropdownmenubox/android-dark.webp new file mode 100644 index 00000000000000..9e708afd670d03 Binary files /dev/null and b/docs/public/static/images/expo-ui/exposeddropdownmenubox/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/exposeddropdownmenubox/android-light.webp b/docs/public/static/images/expo-ui/exposeddropdownmenubox/android-light.webp new file mode 100644 index 00000000000000..b3a4a4c59ca298 Binary files /dev/null and b/docs/public/static/images/expo-ui/exposeddropdownmenubox/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/floatingactionbutton/android-dark.webp b/docs/public/static/images/expo-ui/floatingactionbutton/android-dark.webp new file mode 100644 index 00000000000000..7f75c65ce479ae Binary files /dev/null and b/docs/public/static/images/expo-ui/floatingactionbutton/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/floatingactionbutton/android-light.webp b/docs/public/static/images/expo-ui/floatingactionbutton/android-light.webp new file mode 100644 index 00000000000000..79c8256aa95222 Binary files /dev/null and b/docs/public/static/images/expo-ui/floatingactionbutton/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/flowrow/android-dark.webp b/docs/public/static/images/expo-ui/flowrow/android-dark.webp new file mode 100644 index 00000000000000..98846d32de26d4 Binary files /dev/null and b/docs/public/static/images/expo-ui/flowrow/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/flowrow/android-light.webp b/docs/public/static/images/expo-ui/flowrow/android-light.webp new file mode 100644 index 00000000000000..e6d677673239d6 Binary files /dev/null and b/docs/public/static/images/expo-ui/flowrow/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/horizontalfloatingtoolbar/android-dark.webp b/docs/public/static/images/expo-ui/horizontalfloatingtoolbar/android-dark.webp new file mode 100644 index 00000000000000..25fbfeabd00b2f Binary files /dev/null and b/docs/public/static/images/expo-ui/horizontalfloatingtoolbar/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/horizontalfloatingtoolbar/android-light.webp b/docs/public/static/images/expo-ui/horizontalfloatingtoolbar/android-light.webp new file mode 100644 index 00000000000000..b1a86e2f1c0525 Binary files /dev/null and b/docs/public/static/images/expo-ui/horizontalfloatingtoolbar/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/horizontalpager/android-dark.webp b/docs/public/static/images/expo-ui/horizontalpager/android-dark.webp new file mode 100644 index 00000000000000..2c2b505184929e Binary files /dev/null and b/docs/public/static/images/expo-ui/horizontalpager/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/horizontalpager/android-light.webp b/docs/public/static/images/expo-ui/horizontalpager/android-light.webp new file mode 100644 index 00000000000000..c54df9d67a3e46 Binary files /dev/null and b/docs/public/static/images/expo-ui/horizontalpager/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/icon/android-dark.webp b/docs/public/static/images/expo-ui/icon/android-dark.webp new file mode 100644 index 00000000000000..e574d0791a6574 Binary files /dev/null and b/docs/public/static/images/expo-ui/icon/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/icon/android-light.webp b/docs/public/static/images/expo-ui/icon/android-light.webp new file mode 100644 index 00000000000000..a0654311a411f5 Binary files /dev/null and b/docs/public/static/images/expo-ui/icon/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/iconbutton/android-dark.webp b/docs/public/static/images/expo-ui/iconbutton/android-dark.webp new file mode 100644 index 00000000000000..b13af1fce3d032 Binary files /dev/null and b/docs/public/static/images/expo-ui/iconbutton/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/iconbutton/android-light.webp b/docs/public/static/images/expo-ui/iconbutton/android-light.webp new file mode 100644 index 00000000000000..9c9dd571d9cf6c Binary files /dev/null and b/docs/public/static/images/expo-ui/iconbutton/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/lazycolumn/android-dark.webp b/docs/public/static/images/expo-ui/lazycolumn/android-dark.webp new file mode 100644 index 00000000000000..6d269d208ce9cd Binary files /dev/null and b/docs/public/static/images/expo-ui/lazycolumn/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/lazycolumn/android-light.webp b/docs/public/static/images/expo-ui/lazycolumn/android-light.webp new file mode 100644 index 00000000000000..5553c5db1d34aa Binary files /dev/null and b/docs/public/static/images/expo-ui/lazycolumn/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/lazyrow/android-dark.webp b/docs/public/static/images/expo-ui/lazyrow/android-dark.webp new file mode 100644 index 00000000000000..d225e7f7e862f5 Binary files /dev/null and b/docs/public/static/images/expo-ui/lazyrow/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/lazyrow/android-light.webp b/docs/public/static/images/expo-ui/lazyrow/android-light.webp new file mode 100644 index 00000000000000..afbe8938193988 Binary files /dev/null and b/docs/public/static/images/expo-ui/lazyrow/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/listitem/android-dark.webp b/docs/public/static/images/expo-ui/listitem/android-dark.webp new file mode 100644 index 00000000000000..49a277a45765a8 Binary files /dev/null and b/docs/public/static/images/expo-ui/listitem/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/listitem/android-light.webp b/docs/public/static/images/expo-ui/listitem/android-light.webp new file mode 100644 index 00000000000000..2182a1e8a30c21 Binary files /dev/null and b/docs/public/static/images/expo-ui/listitem/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/progressview/android-dark.webp b/docs/public/static/images/expo-ui/progressview/android-dark.webp new file mode 100644 index 00000000000000..da1f80879f75de Binary files /dev/null and b/docs/public/static/images/expo-ui/progressview/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/progressview/android-light.webp b/docs/public/static/images/expo-ui/progressview/android-light.webp new file mode 100644 index 00000000000000..b828bb463834f1 Binary files /dev/null and b/docs/public/static/images/expo-ui/progressview/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/pulltorefreshbox/android-dark.webp b/docs/public/static/images/expo-ui/pulltorefreshbox/android-dark.webp new file mode 100644 index 00000000000000..2c38b97c9e51ed Binary files /dev/null and b/docs/public/static/images/expo-ui/pulltorefreshbox/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/pulltorefreshbox/android-light.webp b/docs/public/static/images/expo-ui/pulltorefreshbox/android-light.webp new file mode 100644 index 00000000000000..3cf5484ca472c3 Binary files /dev/null and b/docs/public/static/images/expo-ui/pulltorefreshbox/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/radiobutton/android-dark.webp b/docs/public/static/images/expo-ui/radiobutton/android-dark.webp new file mode 100644 index 00000000000000..5500eb19d74a6f Binary files /dev/null and b/docs/public/static/images/expo-ui/radiobutton/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/radiobutton/android-light.webp b/docs/public/static/images/expo-ui/radiobutton/android-light.webp new file mode 100644 index 00000000000000..53ad34a184e305 Binary files /dev/null and b/docs/public/static/images/expo-ui/radiobutton/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/row/android-dark.webp b/docs/public/static/images/expo-ui/row/android-dark.webp new file mode 100644 index 00000000000000..6ba33938e601ff Binary files /dev/null and b/docs/public/static/images/expo-ui/row/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/row/android-light.webp b/docs/public/static/images/expo-ui/row/android-light.webp new file mode 100644 index 00000000000000..338182baa416f7 Binary files /dev/null and b/docs/public/static/images/expo-ui/row/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/searchbar/android-dark.webp b/docs/public/static/images/expo-ui/searchbar/android-dark.webp new file mode 100644 index 00000000000000..dc586c98c5a7b6 Binary files /dev/null and b/docs/public/static/images/expo-ui/searchbar/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/searchbar/android-light.webp b/docs/public/static/images/expo-ui/searchbar/android-light.webp new file mode 100644 index 00000000000000..17cc7cce16af20 Binary files /dev/null and b/docs/public/static/images/expo-ui/searchbar/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/segmentedbutton/android-dark.webp b/docs/public/static/images/expo-ui/segmentedbutton/android-dark.webp new file mode 100644 index 00000000000000..ef883aa09a45c5 Binary files /dev/null and b/docs/public/static/images/expo-ui/segmentedbutton/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/segmentedbutton/android-light.webp b/docs/public/static/images/expo-ui/segmentedbutton/android-light.webp new file mode 100644 index 00000000000000..8c5827d958a316 Binary files /dev/null and b/docs/public/static/images/expo-ui/segmentedbutton/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/shape/android-dark.webp b/docs/public/static/images/expo-ui/shape/android-dark.webp new file mode 100644 index 00000000000000..6d6f4d7fb2e637 Binary files /dev/null and b/docs/public/static/images/expo-ui/shape/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/shape/android-light.webp b/docs/public/static/images/expo-ui/shape/android-light.webp new file mode 100644 index 00000000000000..0701bba50fcfbe Binary files /dev/null and b/docs/public/static/images/expo-ui/shape/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/slider/android-dark.webp b/docs/public/static/images/expo-ui/slider/android-dark.webp new file mode 100644 index 00000000000000..633e658570b534 Binary files /dev/null and b/docs/public/static/images/expo-ui/slider/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/slider/android-light.webp b/docs/public/static/images/expo-ui/slider/android-light.webp new file mode 100644 index 00000000000000..c14a25f7b41b0e Binary files /dev/null and b/docs/public/static/images/expo-ui/slider/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/spacer/android-dark.webp b/docs/public/static/images/expo-ui/spacer/android-dark.webp new file mode 100644 index 00000000000000..255eea120fb82d Binary files /dev/null and b/docs/public/static/images/expo-ui/spacer/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/spacer/android-light.webp b/docs/public/static/images/expo-ui/spacer/android-light.webp new file mode 100644 index 00000000000000..47f8c10f1cf2ad Binary files /dev/null and b/docs/public/static/images/expo-ui/spacer/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/surface/android-dark.webp b/docs/public/static/images/expo-ui/surface/android-dark.webp new file mode 100644 index 00000000000000..1136ec8abaf2b6 Binary files /dev/null and b/docs/public/static/images/expo-ui/surface/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/surface/android-light.webp b/docs/public/static/images/expo-ui/surface/android-light.webp new file mode 100644 index 00000000000000..6cd309e721e3eb Binary files /dev/null and b/docs/public/static/images/expo-ui/surface/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/switch/android-dark.webp b/docs/public/static/images/expo-ui/switch/android-dark.webp new file mode 100644 index 00000000000000..f2830cdb12d188 Binary files /dev/null and b/docs/public/static/images/expo-ui/switch/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/switch/android-light.webp b/docs/public/static/images/expo-ui/switch/android-light.webp new file mode 100644 index 00000000000000..4ca4e6aa718446 Binary files /dev/null and b/docs/public/static/images/expo-ui/switch/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/text/android-dark.webp b/docs/public/static/images/expo-ui/text/android-dark.webp new file mode 100644 index 00000000000000..69773abeae9b94 Binary files /dev/null and b/docs/public/static/images/expo-ui/text/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/text/android-light.webp b/docs/public/static/images/expo-ui/text/android-light.webp new file mode 100644 index 00000000000000..b8b7bd6124f3a1 Binary files /dev/null and b/docs/public/static/images/expo-ui/text/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/textfield/android-dark.webp b/docs/public/static/images/expo-ui/textfield/android-dark.webp new file mode 100644 index 00000000000000..fd30082b1b9fcd Binary files /dev/null and b/docs/public/static/images/expo-ui/textfield/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/textfield/android-light.webp b/docs/public/static/images/expo-ui/textfield/android-light.webp new file mode 100644 index 00000000000000..97bceffc344cec Binary files /dev/null and b/docs/public/static/images/expo-ui/textfield/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/togglebutton/android-dark.webp b/docs/public/static/images/expo-ui/togglebutton/android-dark.webp new file mode 100644 index 00000000000000..64e6c2342a9681 Binary files /dev/null and b/docs/public/static/images/expo-ui/togglebutton/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/togglebutton/android-light.webp b/docs/public/static/images/expo-ui/togglebutton/android-light.webp new file mode 100644 index 00000000000000..19a09a8125d2b9 Binary files /dev/null and b/docs/public/static/images/expo-ui/togglebutton/android-light.webp differ diff --git a/docs/public/static/images/expo-ui/tooltip/android-dark.webp b/docs/public/static/images/expo-ui/tooltip/android-dark.webp new file mode 100644 index 00000000000000..7c9a2c71c62fe9 Binary files /dev/null and b/docs/public/static/images/expo-ui/tooltip/android-dark.webp differ diff --git a/docs/public/static/images/expo-ui/tooltip/android-light.webp b/docs/public/static/images/expo-ui/tooltip/android-light.webp new file mode 100644 index 00000000000000..d5b1a3406f8357 Binary files /dev/null and b/docs/public/static/images/expo-ui/tooltip/android-light.webp differ diff --git a/packages/@expo/cli/CHANGELOG.md b/packages/@expo/cli/CHANGELOG.md index d18a6bfe6d30de..43f3e03d522bfb 100644 --- a/packages/@expo/cli/CHANGELOG.md +++ b/packages/@expo/cli/CHANGELOG.md @@ -14,10 +14,13 @@ - Prevent Metro loading indicator from showing broken states in headless runs. ([#45513](https://github.com/expo/expo/pull/45513) by [@EvanBacon](https://github.com/EvanBacon)) - Fix `--port 0` exiting silently in `expo start` when the port is busy. ([#45513](https://github.com/expo/expo/pull/45513) by [@EvanBacon](https://github.com/EvanBacon)) - Apply printf-style format substitution for web client logs forwarded from the browser. ([#45516](https://github.com/expo/expo/pull/45516) by [@EvanBacon](https://github.com/EvanBacon)) +- Fix @react-navigation/core rewrite to expo-router/react-navigation ([#45543](https://github.com/expo/expo/pull/45543) by [@Ubax](https://github.com/Ubax)) + ### 💡 Others - Replace deprecated `url.parse()` with WHATWG `URL` API in Metro dev server. ([#45524](https://github.com/expo/expo/pull/45524) by [@EvanBacon](https://github.com/EvanBacon)) - Remove pinned dependencies ([#45520](https://github.com/expo/expo/pull/45520) by [@kitten](https://githun.com/kitten)) +- Adopt `experiments.onDemandFilesystem` on `@expo/config-types` ([#45555](https://github.com/expo/expo/pull/45555) by [@kitten](https://github.com/kitten)) ## 56.0.6 — 2026-05-07 diff --git a/packages/@expo/cli/src/start/server/metro/instantiateMetro.ts b/packages/@expo/cli/src/start/server/metro/instantiateMetro.ts index f92432d932f672..f197a6a0512841 100644 --- a/packages/@expo/cli/src/start/server/metro/instantiateMetro.ts +++ b/packages/@expo/cli/src/start/server/metro/instantiateMetro.ts @@ -248,7 +248,7 @@ export async function loadMetroConfigAsync( // On-Demand Filesystem is enabled by default // TODO(@kitten): Add to config-types JSON schema - const onDemandFilesystem = (exp.experiments as any)?.onDemandFilesystem ?? true; + const onDemandFilesystem = exp.experiments?.onDemandFilesystem ?? true; asWritable(config.resolver).unstable_onDemandFilesystem = onDemandFilesystem; // NOTE(@kitten): `useWatchman` is currently enabled by default, but it also disables `forceNodeFilesystemAPI`. diff --git a/packages/@expo/cli/src/start/server/metro/withMetroMultiPlatform.ts b/packages/@expo/cli/src/start/server/metro/withMetroMultiPlatform.ts index 52df861b5fa2f1..e0fda146d9b99c 100644 --- a/packages/@expo/cli/src/start/server/metro/withMetroMultiPlatform.ts +++ b/packages/@expo/cli/src/start/server/metro/withMetroMultiPlatform.ts @@ -640,7 +640,7 @@ export function withExtendedResolver( } if (moduleName === '@react-navigation/core') { // We already checked if expo-router resolves - return doResolve('expo-router'); + return doResolve('expo-router/react-navigation'); } } } diff --git a/packages/@expo/config-types/build/ExpoConfig.d.ts b/packages/@expo/config-types/build/ExpoConfig.d.ts index 53c4fe073a3155..03c1273cc6f66c 100644 --- a/packages/@expo/config-types/build/ExpoConfig.d.ts +++ b/packages/@expo/config-types/build/ExpoConfig.d.ts @@ -205,6 +205,10 @@ export interface ExpoConfig { * Enable experimental features that may be unstable, unsupported, or removed without deprecation notices. */ experiments?: { + /** + * Enables Expo's On-Demand Filesystem allowing Metro bundling outside of the watchFolders and with package manager global virtual stores. + */ + onDemandFilesystem?: boolean; /** * Apply Expo Autolinking's search results to Metro's module resolution. This forces your project's dependencies on `react`, `react-dom`, and `react-native`, and the autolinked versions of any Expo and React Native modules to be resolved when bundling your app. This prevents version misalignment and is useful for monorepos and to prevent conflicts. */ @@ -226,10 +230,6 @@ export interface ExpoConfig { * If true, indicates that this project does not support tablets or handsets, and only supports Apple TV and Android TV */ supportsTVOnly?: boolean; - /** - * Enable React-based CSS support for native platforms. Only supports a subset of CSS properties, class names selectors, and has no cascading. - */ - functionalCSS?: boolean; /** * Enable tsconfig/jsconfig `compilerOptions.paths` and `compilerOptions.baseUrl` support for import aliases in Metro. */ diff --git a/packages/@expo/config-types/src/ExpoConfig.ts b/packages/@expo/config-types/src/ExpoConfig.ts index 97df9ef898b90a..af8142ef2eb9cb 100644 --- a/packages/@expo/config-types/src/ExpoConfig.ts +++ b/packages/@expo/config-types/src/ExpoConfig.ts @@ -211,6 +211,10 @@ export interface ExpoConfig { * Enable experimental features that may be unstable, unsupported, or removed without deprecation notices. */ experiments?: { + /** + * Enables Expo's On-Demand Filesystem allowing Metro bundling outside of the watchFolders and with package manager global virtual stores. + */ + onDemandFilesystem?: boolean; /** * Apply Expo Autolinking's search results to Metro's module resolution. This forces your project's dependencies on `react`, `react-dom`, and `react-native`, and the autolinked versions of any Expo and React Native modules to be resolved when bundling your app. This prevents version misalignment and is useful for monorepos and to prevent conflicts. */ @@ -234,10 +238,6 @@ export interface ExpoConfig { * If true, indicates that this project does not support tablets or handsets, and only supports Apple TV and Android TV */ supportsTVOnly?: boolean; - /** - * Enable React-based CSS support for native platforms. Only supports a subset of CSS properties, class names selectors, and has no cascading. - */ - functionalCSS?: boolean; /** * Enable tsconfig/jsconfig `compilerOptions.paths` and `compilerOptions.baseUrl` support for import aliases in Metro. */ diff --git a/packages/@expo/metro-file-map/CHANGELOG.md b/packages/@expo/metro-file-map/CHANGELOG.md index f8d11cba9e3d54..650f373a74c87b 100644 --- a/packages/@expo/metro-file-map/CHANGELOG.md +++ b/packages/@expo/metro-file-map/CHANGELOG.md @@ -10,6 +10,8 @@ ### 💡 Others +- Reduce crawl time further by embedding VCS check and reducing redundant checks ([#45550](https://github.com/expo/expo/pull/45550) by [@kitten](https://github.com/kitten)) + ## 56.0.0-2 — 2026-05-06 ### 🎉 New features diff --git a/packages/@expo/metro-file-map/build/Watcher.d.ts b/packages/@expo/metro-file-map/build/Watcher.d.ts index ec54ba94458931..cdd6311d4c7756 100644 --- a/packages/@expo/metro-file-map/build/Watcher.d.ts +++ b/packages/@expo/metro-file-map/build/Watcher.d.ts @@ -14,9 +14,9 @@ interface WatcherOptions { extensions: readonly string[]; /** @deprecated */ forceNodeFilesystemAPI?: boolean; - healthCheckFilePrefix: string; + healthCheckFilePrefix: string | null; ignoreForCrawl: (filePath: string) => boolean; - ignorePatternForWatch: RegExp; + ignorePatternForWatch: RegExp | null; previousState: CrawlerOptions['previousState']; perfLogger: PerfLogger | undefined | null; roots: readonly string[]; diff --git a/packages/@expo/metro-file-map/build/Watcher.js b/packages/@expo/metro-file-map/build/Watcher.js index 894f6708ca53a2..fc512de3ee01c2 100644 --- a/packages/@expo/metro-file-map/build/Watcher.js +++ b/packages/@expo/metro-file-map/build/Watcher.js @@ -60,8 +60,23 @@ class Watcher extends events_1.default { async #crawl(crawlOptions) { const options = this.#options; const { useWatchman, subpath } = crawlOptions; - const ignoreForCrawl = (filePath) => options.ignoreForCrawl(filePath) || - path_1.default.basename(filePath).startsWith(this.#options.healthCheckFilePrefix); + const ignoreForCrawl = (() => { + if (options.ignoreForCrawl && options.healthCheckFilePrefix) { + const baseIgnore = options.ignoreForCrawl; + const prefix = options.healthCheckFilePrefix; + return (filePath) => baseIgnore(filePath) || filePath.startsWith(prefix, filePath.lastIndexOf(path_1.default.sep) + 1); + } + else if (options.ignoreForCrawl) { + return options.ignoreForCrawl; + } + else if (options.healthCheckFilePrefix) { + const prefix = options.healthCheckFilePrefix; + return (filePath) => filePath.startsWith(prefix, filePath.lastIndexOf(path_1.default.sep) + 1); + } + else { + return () => false; + } + })(); const crawl = useWatchman ? watchman_1.default : node_1.default; let crawler = crawl === watchman_1.default ? 'watchman' : 'node'; options.abortSignal.throwIfAborted(); @@ -146,14 +161,17 @@ class Watcher extends events_1.default { const watcher = new WatcherImpl(root, watcherOptions); return new Promise(async (resolve, reject) => { const rejectTimeout = setTimeout(() => reject(new Error('Failed to start watch mode.')), MAX_WAIT_TIME); + const healthCheckFilePrefix = this.#options.healthCheckFilePrefix; watcher.onFileEvent((change) => { - const basename = path_1.default.basename(change.relativePath); - if (basename.startsWith(this.#options.healthCheckFilePrefix)) { - if (change.event === common_1.TOUCH_EVENT) { - debug('Observed possible health check cookie: %s in %s', change.relativePath, root); - this.#handleHealthCheckObservation(basename); + if (healthCheckFilePrefix) { + const isHealthCheckFile = change.relativePath.startsWith(healthCheckFilePrefix, change.relativePath.lastIndexOf(path_1.default.sep) + 1); + if (isHealthCheckFile) { + if (change.event === common_1.TOUCH_EVENT) { + debug('Observed possible health check cookie: %s in %s', change.relativePath, root); + this.#handleHealthCheckObservation(path_1.default.basename(change.relativePath)); + } + return; } - return; } // Watchman handles recrawls internally - receiving a recrawl event // when using Watchman would indicate a bug. Log an error and ignore. diff --git a/packages/@expo/metro-file-map/build/crawlers/node/fallback.js b/packages/@expo/metro-file-map/build/crawlers/node/fallback.js index 1ddecd5e089e82..a8fcd9bdad65ee 100644 --- a/packages/@expo/metro-file-map/build/crawlers/node/fallback.js +++ b/packages/@expo/metro-file-map/build/crawlers/node/fallback.js @@ -67,7 +67,8 @@ function createFallbackFilesystem(opts) { continue; } if (entry.isDirectory()) { - if (!result.has(name)) { + // NOTE(@kitten): ".git" and ".hg" check replace the VCS_DIRECTORIES ignore pattern + if (!result.has(name) && name !== '.git' && name !== '.hg') { const childDir = new Map(); markDir(childDir, FallbackFlag.VISITED); result.set(name, childDir); diff --git a/packages/@expo/metro-file-map/build/crawlers/node/index.js b/packages/@expo/metro-file-map/build/crawlers/node/index.js index be2cb0f118c89f..7a399db33a8b21 100644 --- a/packages/@expo/metro-file-map/build/crawlers/node/index.js +++ b/packages/@expo/metro-file-map/build/crawlers/node/index.js @@ -63,7 +63,12 @@ function find(roots, extensions, ignore, includeSymlinks, rootDir, console, prev else { for (let idx = 0; idx < entries.length; idx++) { const entry = entries[idx]; - const name = entry.name.toString(); + const name = entry.name; + // NOTE(@kitten): This replaces the VCS_DIRECTORIES ignore pattern + const isDirectory = entry.isDirectory(); + if (isDirectory && (name === '.git' || name === '.hg')) { + continue; + } const file = directory + path.sep + name; const isSymbolicLink = entry.isSymbolicLink(); if (ignore(file) || (!includeSymlinks && isSymbolicLink)) { @@ -77,7 +82,7 @@ function find(roots, extensions, ignore, includeSymlinks, rootDir, console, prev : dirNormal === '' ? name : dirNormal + path.sep + name; - if (entry.isDirectory()) { + if (isDirectory) { // NOTE(@kitten): We'd like to be able to apply excludes to directories selectively based // on their normal paths, so we can exclude using `^...` if (!ignore(childNormal)) { diff --git a/packages/@expo/metro-file-map/build/crawlers/watchman/index.js b/packages/@expo/metro-file-map/build/crawlers/watchman/index.js index 3432701efcbe47..68d9e2c082734c 100644 --- a/packages/@expo/metro-file-map/build/crawlers/watchman/index.js +++ b/packages/@expo/metro-file-map/build/crawlers/watchman/index.js @@ -49,6 +49,7 @@ const path = __importStar(require("path")); const perf_hooks_1 = require("perf_hooks"); const planQuery_1 = require("./planQuery"); const RootPathUtils_1 = require("../../lib/RootPathUtils"); +const isVcsPath_1 = __importDefault(require("../../lib/isVcsPath")); const normalizePathSeparatorsToPosix_1 = __importDefault(require("../../lib/normalizePathSeparatorsToPosix")); const normalizePathSeparatorsToSystem_1 = __importDefault(require("../../lib/normalizePathSeparatorsToSystem")); const WATCHMAN_WARNING_INITIAL_DELAY_MILLISECONDS = 10000; @@ -247,7 +248,7 @@ async function watchmanCrawl({ abortSignal, computeSha1, extensions, ignore, inc // Whether watchman can return exists: false in a fresh instance // response is unknown, but there's nothing we need to do in that case. } - else if (!ignore(filePath)) { + else if (!(0, isVcsPath_1.default)(fileData.name) && !ignore(filePath)) { const { mtime_ms, size } = fileData; (0, invariant_1.default)(mtime_ms != null && size != null, 'missing file data in watchman response'); const mtime = typeof mtime_ms === 'number' ? mtime_ms : mtime_ms.toNumber(); diff --git a/packages/@expo/metro-file-map/build/index.js b/packages/@expo/metro-file-map/build/index.js index 912978d405f05b..f51c2c76bdeb97 100644 --- a/packages/@expo/metro-file-map/build/index.js +++ b/packages/@expo/metro-file-map/build/index.js @@ -77,7 +77,6 @@ Object.defineProperty(exports, "HastePlugin", { enumerable: true, get: function const CACHE_BREAKER = '12'; const CHANGE_INTERVAL = 30; const NODE_MODULES = path.sep + 'node_modules' + path.sep; -const VCS_DIRECTORIES = /[/\\]\.(git|hg)[/\\]/.source; const WATCHMAN_REQUIRED_CAPABILITIES = [ 'field-content.sha1hex', 'relative_root', @@ -189,19 +188,9 @@ class FileMap extends events_1.default { this.#startupPerfLogger = options.perfLoggerFactory?.('START_UP').subSpan('fileMap') ?? null; this.#startupPerfLogger?.point('constructor_start'); } - // Add VCS_DIRECTORIES to provided ignorePattern - let ignorePattern; - if (options.ignorePattern) { - const inputIgnorePattern = options.ignorePattern; - if (inputIgnorePattern instanceof RegExp) { - ignorePattern = new RegExp(inputIgnorePattern.source.concat('|' + VCS_DIRECTORIES), inputIgnorePattern.flags); - } - else { - throw new Error('metro-file-map: the `ignorePattern` option must be a RegExp'); - } - } - else { - ignorePattern = new RegExp(VCS_DIRECTORIES); + const ignorePattern = options.ignorePattern ?? null; + if (ignorePattern && !(ignorePattern instanceof RegExp)) { + throw new Error('metro-file-map: the `ignorePattern` option must be a RegExp'); } this.#console = options.console || globalThis.console; let dataSlot = constants_1.default.PLUGINDATA; @@ -279,6 +268,7 @@ class FileMap extends events_1.default { debug('Cache loaded (%d clock(s))', initialData.clocks.size); } const rootDir = this.#options.rootDir; + const ignorePattern = this.#options.ignorePattern; this.#startupPerfLogger?.point('constructFileSystem_start'); const processFile = async (normalPath, metadata, opts) => { const result = await this.#fileProcessor.processRegularFile(normalPath, metadata, { @@ -294,7 +284,7 @@ class FileMap extends events_1.default { ? (0, fallback_1.default)({ rootPathUtils: this.#pathUtils, extensions: this.#options.extensions, - ignore: (filePath) => this.#options.ignorePattern.test(filePath), + ignore: ignorePattern ? (filePath) => ignorePattern.test(filePath) : () => false, includeSymlinks: this.#options.enableSymlinks, }) : null; @@ -395,6 +385,20 @@ class FileMap extends events_1.default { async #buildFileDelta(previousState) { this.#startupPerfLogger?.point('buildFileDelta_start'); const { computeSha1, enableSymlinks, extensions, forceNodeFilesystemAPI, ignorePattern, retainAllFiles, roots, rootDir, watch, watchmanDeferStates, } = this.#options; + const ignoreForCrawl = (() => { + if (ignorePattern && !retainAllFiles) { + return (filePath) => ignorePattern.test(filePath) || filePath.includes(NODE_MODULES); + } + else if (ignorePattern) { + return (filePath) => ignorePattern.test(filePath); + } + else if (!retainAllFiles) { + return (filePath) => filePath.includes(NODE_MODULES); + } + else { + return () => false; + } + })(); this.#watcher = new Watcher_1.Watcher({ abortSignal: this.#crawlerAbortController.signal, computeSha1, @@ -402,12 +406,10 @@ class FileMap extends events_1.default { enableSymlinks, extensions, forceNodeFilesystemAPI, - healthCheckFilePrefix: this.#options.healthCheck.filePrefix, - // TODO: Refactor out the two different ignore strategies here. - ignoreForCrawl: (filePath) => { - const ignoreMatched = ignorePattern.test(filePath); - return ignoreMatched || (!retainAllFiles && filePath.includes(NODE_MODULES)); - }, + healthCheckFilePrefix: this.#options.healthCheck.enabled + ? this.#options.healthCheck.filePrefix + : null, + ignoreForCrawl, ignorePatternForWatch: ignorePattern, perfLogger: this.#startupPerfLogger, previousState, @@ -630,7 +632,8 @@ class FileMap extends events_1.default { const absoluteFilePath = path.join(change.root, (0, normalizePathSeparatorsToSystem_1.default)(change.relativePath)); // Ignore files (including symlinks) whose path matches ignorePattern // (we don't ignore node_modules in watch mode) - if (this.#options.ignorePattern.test(absoluteFilePath)) { + // TODO(@kitten): Can be dropped, assuming that regexes aren't violating constraints + if (this.#options.ignorePattern?.test(absoluteFilePath) === true) { return; } const relativeFilePath = this.#pathUtils.absoluteToNormal(absoluteFilePath); diff --git a/packages/@expo/metro-file-map/build/lib/TreeFS.js b/packages/@expo/metro-file-map/build/lib/TreeFS.js index af297e8142b1cd..dc67fc74ab943d 100644 --- a/packages/@expo/metro-file-map/build/lib/TreeFS.js +++ b/packages/@expo/metro-file-map/build/lib/TreeFS.js @@ -787,8 +787,8 @@ class TreeFS { } return null; } - *metadataIterator(opts) { - yield* this.#metadataIterator(this.#rootNode, opts); + metadataIterator(opts) { + return this.#metadataIterator(this.#rootNode, opts); } *#metadataIterator(rootNode, opts, prefix = '') { for (const [name, node] of rootNode) { diff --git a/packages/@expo/metro-file-map/build/lib/isVcsPath.d.ts b/packages/@expo/metro-file-map/build/lib/isVcsPath.d.ts new file mode 100644 index 00000000000000..c9d22207d5d7a8 --- /dev/null +++ b/packages/@expo/metro-file-map/build/lib/isVcsPath.d.ts @@ -0,0 +1 @@ +export default function isVcsPath(filePath: string): boolean; diff --git a/packages/@expo/metro-file-map/build/lib/isVcsPath.js b/packages/@expo/metro-file-map/build/lib/isVcsPath.js new file mode 100644 index 00000000000000..033bee0f86c459 --- /dev/null +++ b/packages/@expo/metro-file-map/build/lib/isVcsPath.js @@ -0,0 +1,7 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = isVcsPath; +const VCS_DIR_SEGMENT = /(?:^|[/\\])\.(?:git|hg)[/\\]/; +function isVcsPath(filePath) { + return VCS_DIR_SEGMENT.test(filePath); +} diff --git a/packages/@expo/metro-file-map/build/lib/rootRelativeCacheKeys.js b/packages/@expo/metro-file-map/build/lib/rootRelativeCacheKeys.js index 21277bab7a3926..7f500254462775 100644 --- a/packages/@expo/metro-file-map/build/lib/rootRelativeCacheKeys.js +++ b/packages/@expo/metro-file-map/build/lib/rootRelativeCacheKeys.js @@ -32,7 +32,7 @@ function rootRelativeCacheKeys(buildParameters) { case 'retainAllFiles': return buildParameters[key] ?? null; case 'ignorePattern': - return buildParameters[key].toString(); + return buildParameters[key]?.toString() ?? null; case 'forceNodeFilesystemAPI': return null; default: diff --git a/packages/@expo/metro-file-map/build/types.d.ts b/packages/@expo/metro-file-map/build/types.d.ts index f2ac3a051fd489..6c4bdb6d065271 100644 --- a/packages/@expo/metro-file-map/build/types.d.ts +++ b/packages/@expo/metro-file-map/build/types.d.ts @@ -14,7 +14,7 @@ export interface BuildParameters { readonly extensions: readonly string[]; /** @deprecated */ readonly forceNodeFilesystemAPI?: boolean; - readonly ignorePattern: RegExp; + readonly ignorePattern: RegExp | null; readonly plugins: readonly InputFileMapPlugin[]; readonly retainAllFiles: boolean; readonly rootDir: string; diff --git a/packages/@expo/metro-file-map/build/watchers/AbstractWatcher.js b/packages/@expo/metro-file-map/build/watchers/AbstractWatcher.js index 71f2ad1eac218c..b0eb4bf2c04939 100644 --- a/packages/@expo/metro-file-map/build/watchers/AbstractWatcher.js +++ b/packages/@expo/metro-file-map/build/watchers/AbstractWatcher.js @@ -45,6 +45,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.AbstractWatcher = void 0; const events_1 = __importDefault(require("events")); const path = __importStar(require("path")); +const isVcsPath_1 = __importDefault(require("../lib/isVcsPath")); const common_1 = require("./common"); class AbstractWatcher { root; @@ -59,8 +60,8 @@ class AbstractWatcher { this.ignored = ignored; this.globs = globs; this.doIgnore = ignored - ? (filePath) => (0, common_1.posixPathMatchesPattern)(ignored, filePath) - : () => false; + ? (filePath) => (0, isVcsPath_1.default)(filePath) || (0, common_1.posixPathMatchesPattern)(ignored, filePath) + : isVcsPath_1.default; this.root = path.resolve(dir); } onFileEvent(listener) { diff --git a/packages/@expo/metro-file-map/src/Watcher.ts b/packages/@expo/metro-file-map/src/Watcher.ts index 8adbaa6e67278f..7d580369019d2d 100644 --- a/packages/@expo/metro-file-map/src/Watcher.ts +++ b/packages/@expo/metro-file-map/src/Watcher.ts @@ -46,9 +46,9 @@ interface WatcherOptions { extensions: readonly string[]; /** @deprecated */ forceNodeFilesystemAPI?: boolean; - healthCheckFilePrefix: string; + healthCheckFilePrefix: string | null; ignoreForCrawl: (filePath: string) => boolean; - ignorePatternForWatch: RegExp; + ignorePatternForWatch: RegExp | null; previousState: CrawlerOptions['previousState']; perfLogger: PerfLogger | undefined | null; roots: readonly string[]; @@ -122,9 +122,23 @@ export class Watcher extends EventEmitter { const options = this.#options; const { useWatchman, subpath } = crawlOptions; - const ignoreForCrawl = (filePath: string) => - options.ignoreForCrawl(filePath) || - path.basename(filePath).startsWith(this.#options.healthCheckFilePrefix); + const ignoreForCrawl = (() => { + if (options.ignoreForCrawl && options.healthCheckFilePrefix) { + const baseIgnore = options.ignoreForCrawl; + const prefix = options.healthCheckFilePrefix; + return (filePath: string) => + baseIgnore(filePath) || filePath.startsWith(prefix, filePath.lastIndexOf(path.sep) + 1); + } else if (options.ignoreForCrawl) { + return options.ignoreForCrawl; + } else if (options.healthCheckFilePrefix) { + const prefix = options.healthCheckFilePrefix; + return (filePath: string) => + filePath.startsWith(prefix, filePath.lastIndexOf(path.sep) + 1); + } else { + return () => false; + } + })(); + const crawl = useWatchman ? watchmanCrawl : nodeCrawl; let crawler = crawl === watchmanCrawl ? 'watchman' : 'node'; @@ -233,15 +247,22 @@ export class Watcher extends EventEmitter { MAX_WAIT_TIME ); + const healthCheckFilePrefix = this.#options.healthCheckFilePrefix; watcher.onFileEvent((change) => { - const basename = path.basename(change.relativePath); - if (basename.startsWith(this.#options.healthCheckFilePrefix)) { - if (change.event === TOUCH_EVENT) { - debug('Observed possible health check cookie: %s in %s', change.relativePath, root); - this.#handleHealthCheckObservation(basename); + if (healthCheckFilePrefix) { + const isHealthCheckFile = change.relativePath.startsWith( + healthCheckFilePrefix, + change.relativePath.lastIndexOf(path.sep) + 1 + ); + if (isHealthCheckFile) { + if (change.event === TOUCH_EVENT) { + debug('Observed possible health check cookie: %s in %s', change.relativePath, root); + this.#handleHealthCheckObservation(path.basename(change.relativePath)); + } + return; } - return; } + // Watchman handles recrawls internally - receiving a recrawl event // when using Watchman would indicate a bug. Log an error and ignore. if (change.event === 'recrawl' && useWatchman) { diff --git a/packages/@expo/metro-file-map/src/__tests__/Watcher.test.ts b/packages/@expo/metro-file-map/src/__tests__/Watcher.test.ts new file mode 100644 index 00000000000000..a9159b95f95598 --- /dev/null +++ b/packages/@expo/metro-file-map/src/__tests__/Watcher.test.ts @@ -0,0 +1,144 @@ +/** + * Copyright (c) 650 Industries, Inc. (Expo). + */ + +import { vol } from 'memfs'; + +import { Watcher } from '../Watcher'; +import TreeFS from '../lib/TreeFS'; +import type { CrawlerOptions, FileData } from '../types'; + +const rootDir = '/project'; +const processFile = async () => null; + +function makeTreeFS(files?: FileData): TreeFS { + return new TreeFS({ rootDir, files, processFile }); +} + +function makeWatcher( + overrides: { + ignoreForCrawl?: (filePath: string) => boolean; + healthCheckFilePrefix?: string | null; + roots?: readonly string[]; + } = {} +) { + return new Watcher({ + abortSignal: new AbortController().signal, + computeSha1: false, + console, + enableSymlinks: false, + extensions: ['js'], + forceNodeFilesystemAPI: true, + healthCheckFilePrefix: overrides.healthCheckFilePrefix ?? null, + ignoreForCrawl: overrides.ignoreForCrawl ?? (() => false), + ignorePatternForWatch: null, + perfLogger: null, + previousState: { + fileSystem: makeTreeFS(), + clocks: new Map(), + } as CrawlerOptions['previousState'], + rootDir, + roots: overrides.roots ?? [rootDir], + useWatchman: false, + watch: false, + watchmanDeferStates: [], + }); +} + +function sorted(iter: IterableIterator): string[] { + return Array.from(iter).sort(); +} + +describe('Watcher.crawl ignoreForCrawl composition', () => { + beforeEach(() => { + vol.reset(); + }); + + test('filters health-check-prefixed files when prefix is set', async () => { + vol.fromJSON({ + '/project/a.js': 'a', + '/project/.metro-health-check-1.js': 'hc', + '/project/sub/.metro-health-check-2.js': 'hc', + '/project/sub/b.js': 'b', + }); + + const { changedFiles } = await makeWatcher({ + healthCheckFilePrefix: '.metro-health-check', + }).crawl(); + + expect(sorted(changedFiles.keys())).toEqual(['a.js', 'sub/b.js']); + }); + + test('does not filter health-check files when prefix is null (default)', async () => { + vol.fromJSON({ + '/project/a.js': 'a', + '/project/.metro-health-check-1.js': 'hc', + }); + + const { changedFiles } = await makeWatcher({ + healthCheckFilePrefix: null, + }).crawl(); + + expect(sorted(changedFiles.keys())).toEqual(['.metro-health-check-1.js', 'a.js']); + }); + + test('applies user ignoreForCrawl alongside health-check filter', async () => { + vol.fromJSON({ + '/project/keep.js': 'k', + '/project/blocked.js': 'b', + '/project/.metro-health-check.js': 'hc', + }); + + const { changedFiles } = await makeWatcher({ + ignoreForCrawl: (filePath) => filePath.includes('blocked'), + healthCheckFilePrefix: '.metro-health-check', + }).crawl(); + + expect(sorted(changedFiles.keys())).toEqual(['keep.js']); + }); + + test('only matches the prefix at the start of the basename', async () => { + vol.fromJSON({ + // The prefix string appears mid-basename — must NOT be filtered, since + // we only match when the basename *starts with* the prefix. + '/project/x.metro-health-check.js': 'a', + '/project/sub/y.metro-health-check.js': 'b', + }); + + const { changedFiles } = await makeWatcher({ + healthCheckFilePrefix: '.metro-health-check', + }).crawl(); + + expect(sorted(changedFiles.keys())).toEqual([ + 'sub/y.metro-health-check.js', + 'x.metro-health-check.js', + ]); + }); + + test('matches a basename-only path (no separator) against the prefix', async () => { + vol.fromJSON({ + '/project/.metro-health-check.js': 'hc', + '/project/other.js': 'o', + }); + + const { changedFiles } = await makeWatcher({ + healthCheckFilePrefix: '.metro-health-check', + }).crawl(); + + expect(sorted(changedFiles.keys())).toEqual(['other.js']); + }); + + test('user ignoreForCrawl alone suffices when prefix is null', async () => { + vol.fromJSON({ + '/project/keep.js': 'k', + '/project/blocked.js': 'b', + }); + + const { changedFiles } = await makeWatcher({ + ignoreForCrawl: (filePath) => filePath.includes('blocked'), + healthCheckFilePrefix: null, + }).crawl(); + + expect(sorted(changedFiles.keys())).toEqual(['keep.js']); + }); +}); diff --git a/packages/@expo/metro-file-map/src/crawlers/node/__tests__/fallback.test.ts b/packages/@expo/metro-file-map/src/crawlers/node/__tests__/fallback.test.ts index 412c7143a89c9c..91b21d7f9e4eb8 100644 --- a/packages/@expo/metro-file-map/src/crawlers/node/__tests__/fallback.test.ts +++ b/packages/@expo/metro-file-map/src/crawlers/node/__tests__/fallback.test.ts @@ -216,6 +216,32 @@ describe('createFallbackFilesystem', () => { expect(result!.get('file.js')?.[0]).toBe(999); // preserved }); + + test('skips .git and .hg directories', () => { + vol.fromJSON({ + '/project/src/keep.js': 'a', + '/project/src/.git/HEAD': 'ref', + '/project/src/.hg/store/data': 'binary', + }); + const fallback = createFallback(); + const result = fallback.readdir('src', '/project/src', undefined); + + expect(result).toBeInstanceOf(Map); + expect(result!.has('keep.js')).toBe(true); + expect(result!.has('.git')).toBe(false); + expect(result!.has('.hg')).toBe(false); + }); + + test('skips .git and .hg even when ignore would not match them', () => { + vol.fromJSON({ + '/project/src/.git/HEAD': 'ref', + '/project/src/keep.js': 'a', + }); + const fallback = createFallback({ ignore: () => false }); + const result = fallback.readdir('src', '/project/src', undefined); + + expect(result!.has('.git')).toBe(false); + }); }); describe('directory marking (isFallbackDir)', () => { diff --git a/packages/@expo/metro-file-map/src/crawlers/node/__tests__/index.test.ts b/packages/@expo/metro-file-map/src/crawlers/node/__tests__/index.test.ts index 11a4790d7d1fd0..290bf609953266 100644 --- a/packages/@expo/metro-file-map/src/crawlers/node/__tests__/index.test.ts +++ b/packages/@expo/metro-file-map/src/crawlers/node/__tests__/index.test.ts @@ -375,6 +375,58 @@ describe('node crawler', () => { expect(sorted(changedFiles.keys())).toEqual(['fruits/apple.js', 'fruits/tropical.js']); }); + describe('VCS directories', () => { + test('skips .git and .hg directories without consulting ignore', async () => { + const ignore = jest.fn(() => false); + + vol.fromJSON({ + '/project/fruits/apple.js': 'a', + '/project/fruits/.git/HEAD': 'ref', + '/project/fruits/.git/objects/abc': 'binary', + '/project/fruits/.hg/store/data': 'binary', + }); + + const { changedFiles } = await crawl({ ignore }); + + expect(sorted(changedFiles.keys())).toEqual(['fruits/apple.js']); + // The early-skip happens before any `ignore()` call for the .git/.hg + // directory entries, so the matcher is never asked about those paths. + const seenPaths = ignore.mock.calls.map((args) => args[0] as string); + expect(seenPaths.some((p) => p.includes('.git'))).toBe(false); + expect(seenPaths.some((p) => p.includes('.hg'))).toBe(false); + }); + + test('skips .git directory even when ignore would otherwise allow it', async () => { + vol.fromJSON({ + '/project/fruits/apple.js': 'a', + '/project/fruits/.git/HEAD': 'ref', + }); + + const { changedFiles } = await crawl({ + // ignore returns false for everything, including .git contents + ignore: () => false, + }); + + expect(sorted(changedFiles.keys())).toEqual(['fruits/apple.js']); + }); + + test('does not skip files merely named .git or .hg', async () => { + // A *file* named `.git` (e.g. a git submodule pointer file) matches the + // basename equality but `entry.isDirectory()` is false, so it falls + // through to the regular ignore/extension pipeline. + vol.fromJSON({ + '/project/fruits/apple.js': 'a', + '/project/fruits/.git': 'gitdir: ../.git/modules/fruits', + }); + + const { changedFiles } = await crawl({ extensions: ['js'] }); + + // The `.git` file has no matching extension, so it isn't included; but + // the directory traversal didn't bail out either. + expect(sorted(changedFiles.keys())).toEqual(['fruits/apple.js']); + }); + }); + describe('abort signal', () => { test('aborts on pre-aborted signal', async () => { const err = new Error('aborted for test'); diff --git a/packages/@expo/metro-file-map/src/crawlers/node/fallback.ts b/packages/@expo/metro-file-map/src/crawlers/node/fallback.ts index 2c1fe1717f0811..a02fcca842889d 100644 --- a/packages/@expo/metro-file-map/src/crawlers/node/fallback.ts +++ b/packages/@expo/metro-file-map/src/crawlers/node/fallback.ts @@ -91,7 +91,8 @@ export default function createFallbackFilesystem( } if (entry.isDirectory()) { - if (!result.has(name)) { + // NOTE(@kitten): ".git" and ".hg" check replace the VCS_DIRECTORIES ignore pattern + if (!result.has(name) && name !== '.git' && name !== '.hg') { const childDir = new Map(); markDir(childDir, FallbackFlag.VISITED); result.set(name, childDir); diff --git a/packages/@expo/metro-file-map/src/crawlers/node/index.ts b/packages/@expo/metro-file-map/src/crawlers/node/index.ts index a566ed4b350059..dbae9e6677009c 100644 --- a/packages/@expo/metro-file-map/src/crawlers/node/index.ts +++ b/packages/@expo/metro-file-map/src/crawlers/node/index.ts @@ -55,9 +55,15 @@ function find( } else { for (let idx = 0; idx < entries.length; idx++) { const entry = entries[idx]!; - const name = entry.name.toString(); - const file = directory + path.sep + name; + const name = entry.name; + // NOTE(@kitten): This replaces the VCS_DIRECTORIES ignore pattern + const isDirectory = entry.isDirectory(); + if (isDirectory && (name === '.git' || name === '.hg')) { + continue; + } + + const file = directory + path.sep + name; const isSymbolicLink = entry.isSymbolicLink(); if (ignore(file) || (!includeSymlinks && isSymbolicLink)) { continue; @@ -72,7 +78,7 @@ function find( ? name : dirNormal + path.sep + name; - if (entry.isDirectory()) { + if (isDirectory) { // NOTE(@kitten): We'd like to be able to apply excludes to directories selectively based // on their normal paths, so we can exclude using `^...` if (!ignore(childNormal)) { diff --git a/packages/@expo/metro-file-map/src/crawlers/watchman/index.ts b/packages/@expo/metro-file-map/src/crawlers/watchman/index.ts index 27bd557740c7f0..de875fbb6daeb3 100644 --- a/packages/@expo/metro-file-map/src/crawlers/watchman/index.ts +++ b/packages/@expo/metro-file-map/src/crawlers/watchman/index.ts @@ -13,6 +13,7 @@ import { performance } from 'perf_hooks'; import { planQuery } from './planQuery'; import { RootPathUtils } from '../../lib/RootPathUtils'; +import isVcsPath from '../../lib/isVcsPath'; import normalizePathSeparatorsToPosix from '../../lib/normalizePathSeparatorsToPosix'; import normalizePathSeparatorsToSystem from '../../lib/normalizePathSeparatorsToSystem'; import type { @@ -292,7 +293,7 @@ export default async function watchmanCrawl({ } // Whether watchman can return exists: false in a fresh instance // response is unknown, but there's nothing we need to do in that case. - } else if (!ignore(filePath)) { + } else if (!isVcsPath(fileData.name) && !ignore(filePath)) { const { mtime_ms, size } = fileData; invariant(mtime_ms != null && size != null, 'missing file data in watchman response'); const mtime = typeof mtime_ms === 'number' ? mtime_ms : mtime_ms.toNumber(); diff --git a/packages/@expo/metro-file-map/src/index.ts b/packages/@expo/metro-file-map/src/index.ts index 0674742627e739..5841be1e7d984b 100644 --- a/packages/@expo/metro-file-map/src/index.ts +++ b/packages/@expo/metro-file-map/src/index.ts @@ -160,7 +160,6 @@ const CACHE_BREAKER = '12'; const CHANGE_INTERVAL = 30; const NODE_MODULES = path.sep + 'node_modules' + path.sep; -const VCS_DIRECTORIES = /[/\\]\.(git|hg)[/\\]/.source; const WATCHMAN_REQUIRED_CAPABILITIES = [ 'field-content.sha1hex', 'relative_root', @@ -278,20 +277,9 @@ export default class FileMap extends EventEmitter { this.#startupPerfLogger?.point('constructor_start'); } - // Add VCS_DIRECTORIES to provided ignorePattern - let ignorePattern; - if (options.ignorePattern) { - const inputIgnorePattern = options.ignorePattern; - if (inputIgnorePattern instanceof RegExp) { - ignorePattern = new RegExp( - inputIgnorePattern.source.concat('|' + VCS_DIRECTORIES), - inputIgnorePattern.flags - ); - } else { - throw new Error('metro-file-map: the `ignorePattern` option must be a RegExp'); - } - } else { - ignorePattern = new RegExp(VCS_DIRECTORIES); + const ignorePattern: RegExp | null = options.ignorePattern ?? null; + if (ignorePattern && !(ignorePattern instanceof RegExp)) { + throw new Error('metro-file-map: the `ignorePattern` option must be a RegExp'); } this.#console = options.console || globalThis.console; @@ -379,6 +367,7 @@ export default class FileMap extends EventEmitter { } const rootDir = this.#options.rootDir; + const ignorePattern = this.#options.ignorePattern; this.#startupPerfLogger?.point('constructFileSystem_start'); const processFile: ProcessFileFunction = async (normalPath, metadata, opts) => { const result = await this.#fileProcessor.processRegularFile(normalPath, metadata, { @@ -394,7 +383,7 @@ export default class FileMap extends EventEmitter { ? createFallbackFilesystem({ rootPathUtils: this.#pathUtils, extensions: this.#options.extensions, - ignore: (filePath) => this.#options.ignorePattern.test(filePath), + ignore: ignorePattern ? (filePath) => ignorePattern.test(filePath) : () => false, includeSymlinks: this.#options.enableSymlinks, }) : null; @@ -525,6 +514,19 @@ export default class FileMap extends EventEmitter { watchmanDeferStates, } = this.#options; + const ignoreForCrawl = (() => { + if (ignorePattern && !retainAllFiles) { + return (filePath: string) => + ignorePattern.test(filePath) || filePath.includes(NODE_MODULES); + } else if (ignorePattern) { + return (filePath: string) => ignorePattern.test(filePath); + } else if (!retainAllFiles) { + return (filePath: string) => filePath.includes(NODE_MODULES); + } else { + return () => false; + } + })(); + this.#watcher = new Watcher({ abortSignal: this.#crawlerAbortController.signal, computeSha1, @@ -532,12 +534,10 @@ export default class FileMap extends EventEmitter { enableSymlinks, extensions, forceNodeFilesystemAPI, - healthCheckFilePrefix: this.#options.healthCheck.filePrefix, - // TODO: Refactor out the two different ignore strategies here. - ignoreForCrawl: (filePath) => { - const ignoreMatched = ignorePattern.test(filePath); - return ignoreMatched || (!retainAllFiles && filePath.includes(NODE_MODULES)); - }, + healthCheckFilePrefix: this.#options.healthCheck.enabled + ? this.#options.healthCheck.filePrefix + : null, + ignoreForCrawl, ignorePatternForWatch: ignorePattern, perfLogger: this.#startupPerfLogger, previousState, @@ -842,7 +842,8 @@ export default class FileMap extends EventEmitter { // Ignore files (including symlinks) whose path matches ignorePattern // (we don't ignore node_modules in watch mode) - if (this.#options.ignorePattern.test(absoluteFilePath)) { + // TODO(@kitten): Can be dropped, assuming that regexes aren't violating constraints + if (this.#options.ignorePattern?.test(absoluteFilePath) === true) { return; } diff --git a/packages/@expo/metro-file-map/src/lib/TreeFS.ts b/packages/@expo/metro-file-map/src/lib/TreeFS.ts index 5f88bde567eafa..93c50f202df8c4 100644 --- a/packages/@expo/metro-file-map/src/lib/TreeFS.ts +++ b/packages/@expo/metro-file-map/src/lib/TreeFS.ts @@ -1109,12 +1109,12 @@ export default class TreeFS implements MutableFileSystem { return null; } - *metadataIterator(opts: MetadataIteratorOptions): Generator<{ + metadataIterator(opts: MetadataIteratorOptions): Generator<{ baseName: string; canonicalPath: string; metadata: FileMetadata; }> { - yield* this.#metadataIterator(this.#rootNode, opts); + return this.#metadataIterator(this.#rootNode, opts); } *#metadataIterator( diff --git a/packages/@expo/metro-file-map/src/lib/__tests__/isVcsPath.test.ts b/packages/@expo/metro-file-map/src/lib/__tests__/isVcsPath.test.ts new file mode 100644 index 00000000000000..cc1f2c2bf90d9a --- /dev/null +++ b/packages/@expo/metro-file-map/src/lib/__tests__/isVcsPath.test.ts @@ -0,0 +1,52 @@ +/** + * Copyright (c) 650 Industries, Inc. (Expo). + */ + +import isVcsPath from '../isVcsPath'; + +describe('isVcsPath', () => { + test('matches .git and .hg segments at the start of a relative path', () => { + expect(isVcsPath('.git/HEAD')).toBe(true); + expect(isVcsPath('.hg/store/data')).toBe(true); + }); + + test('matches .git and .hg segments in the middle of a path', () => { + expect(isVcsPath('foo/.git/HEAD')).toBe(true); + expect(isVcsPath('a/b/c/.hg/store')).toBe(true); + }); + + test('matches .git and .hg segments in absolute paths', () => { + expect(isVcsPath('/repo/.git/HEAD')).toBe(true); + expect(isVcsPath('/repo/.hg/store')).toBe(true); + }); + + test('matches with backslash separators (Windows)', () => { + expect(isVcsPath('C:\\repo\\.git\\HEAD')).toBe(true); + expect(isVcsPath('.git\\HEAD')).toBe(true); + expect(isVcsPath('foo\\.hg\\store')).toBe(true); + }); + + test('does not match files that merely contain .git or .hg in their name', () => { + expect(isVcsPath('foo.git')).toBe(false); + expect(isVcsPath('foo/bar.git')).toBe(false); + expect(isVcsPath('foo/my.git.txt')).toBe(false); + expect(isVcsPath('foo/.gitignore')).toBe(false); + }); + + test('does not match the bare .git or .hg basename without a trailing separator', () => { + // Preserves the original VCS_DIRECTORIES `[/\\]\.(git|hg)[/\\]` semantics: + // a path ending at the VCS directory itself (no trailing separator) is not + // matched. Crawlers and walkers handle the directory entry case via a + // dedicated basename string check. + expect(isVcsPath('/repo/.git')).toBe(false); + expect(isVcsPath('/repo/.hg')).toBe(false); + expect(isVcsPath('.git')).toBe(false); + expect(isVcsPath('.hg')).toBe(false); + }); + + test('does not match unrelated paths', () => { + expect(isVcsPath('src/index.ts')).toBe(false); + expect(isVcsPath('/repo/src/index.ts')).toBe(false); + expect(isVcsPath('node_modules/foo/index.js')).toBe(false); + }); +}); diff --git a/packages/@expo/metro-file-map/src/lib/isVcsPath.ts b/packages/@expo/metro-file-map/src/lib/isVcsPath.ts new file mode 100644 index 00000000000000..c5aed6da9cd4dd --- /dev/null +++ b/packages/@expo/metro-file-map/src/lib/isVcsPath.ts @@ -0,0 +1,5 @@ +const VCS_DIR_SEGMENT = /(?:^|[/\\])\.(?:git|hg)[/\\]/; + +export default function isVcsPath(filePath: string): boolean { + return VCS_DIR_SEGMENT.test(filePath); +} diff --git a/packages/@expo/metro-file-map/src/lib/rootRelativeCacheKeys.ts b/packages/@expo/metro-file-map/src/lib/rootRelativeCacheKeys.ts index fceeeaf6bda850..3873a486e3ecc7 100644 --- a/packages/@expo/metro-file-map/src/lib/rootRelativeCacheKeys.ts +++ b/packages/@expo/metro-file-map/src/lib/rootRelativeCacheKeys.ts @@ -36,7 +36,7 @@ export default function rootRelativeCacheKeys(buildParameters: BuildParameters): case 'retainAllFiles': return buildParameters[key] ?? null; case 'ignorePattern': - return buildParameters[key].toString(); + return buildParameters[key]?.toString() ?? null; case 'forceNodeFilesystemAPI': return null; default: diff --git a/packages/@expo/metro-file-map/src/types.ts b/packages/@expo/metro-file-map/src/types.ts index a6625bb46c5329..3722a3f738cbc6 100644 --- a/packages/@expo/metro-file-map/src/types.ts +++ b/packages/@expo/metro-file-map/src/types.ts @@ -21,7 +21,7 @@ export interface BuildParameters { readonly extensions: readonly string[]; /** @deprecated */ readonly forceNodeFilesystemAPI?: boolean; - readonly ignorePattern: RegExp; + readonly ignorePattern: RegExp | null; readonly plugins: readonly InputFileMapPlugin[]; readonly retainAllFiles: boolean; readonly rootDir: string; diff --git a/packages/@expo/metro-file-map/src/watchers/AbstractWatcher.ts b/packages/@expo/metro-file-map/src/watchers/AbstractWatcher.ts index 3aff1e816a6537..ed525c8dc7c610 100644 --- a/packages/@expo/metro-file-map/src/watchers/AbstractWatcher.ts +++ b/packages/@expo/metro-file-map/src/watchers/AbstractWatcher.ts @@ -8,6 +8,7 @@ import EventEmitter from 'events'; import * as path from 'path'; +import isVcsPath from '../lib/isVcsPath'; import type { WatcherBackend, WatcherBackendChangeEvent, WatcherBackendOptions } from '../types'; import { posixPathMatchesPattern } from './common'; @@ -35,8 +36,8 @@ export class AbstractWatcher implements WatcherBackend { this.ignored = ignored; this.globs = globs; this.doIgnore = ignored - ? (filePath: string) => posixPathMatchesPattern(ignored, filePath) - : () => false; + ? (filePath: string) => isVcsPath(filePath) || posixPathMatchesPattern(ignored, filePath) + : isVcsPath; this.root = path.resolve(dir); } diff --git a/packages/@expo/metro-file-map/src/watchers/__tests__/AbstractWatcher.test.ts b/packages/@expo/metro-file-map/src/watchers/__tests__/AbstractWatcher.test.ts new file mode 100644 index 00000000000000..6a0befe74d7cf1 --- /dev/null +++ b/packages/@expo/metro-file-map/src/watchers/__tests__/AbstractWatcher.test.ts @@ -0,0 +1,56 @@ +/** + * Copyright (c) 650 Industries, Inc. (Expo). + */ + +import { AbstractWatcher } from '../AbstractWatcher'; + +describe('AbstractWatcher.doIgnore', () => { + test('rejects .git and .hg path segments without a user pattern', () => { + const watcher = new AbstractWatcher('/project', { + dot: true, + globs: [], + ignored: null, + watchmanDeferStates: [], + }); + + expect(watcher.doIgnore('.git/HEAD')).toBe(true); + expect(watcher.doIgnore('foo/.git/HEAD')).toBe(true); + expect(watcher.doIgnore('.hg/store/data')).toBe(true); + expect(watcher.doIgnore('foo/.hg/data')).toBe(true); + }); + + test('passes non-VCS paths through when no user pattern is set', () => { + const watcher = new AbstractWatcher('/project', { + dot: true, + globs: [], + ignored: null, + watchmanDeferStates: [], + }); + + expect(watcher.doIgnore('src/index.ts')).toBe(false); + expect(watcher.doIgnore('node_modules/foo/index.js')).toBe(false); + }); + + test('rejects VCS paths even when user pattern would not match', () => { + const watcher = new AbstractWatcher('/project', { + dot: true, + globs: [], + ignored: /never-matches-anything-xyz/, + watchmanDeferStates: [], + }); + + expect(watcher.doIgnore('foo/.git/HEAD')).toBe(true); + }); + + test('still applies the user pattern alongside the VCS check', () => { + const watcher = new AbstractWatcher('/project', { + dot: true, + globs: [], + ignored: /__tests__\//, + watchmanDeferStates: [], + }); + + expect(watcher.doIgnore('src/__tests__/foo.test.js')).toBe(true); + expect(watcher.doIgnore('src/index.ts')).toBe(false); + }); +}); diff --git a/packages/expo-app-metrics/android/src/main/java/expo/modules/appmetrics/AppMetricsModule.kt b/packages/expo-app-metrics/android/src/main/java/expo/modules/appmetrics/AppMetricsModule.kt index 594bb11b25b464..c347a45bcbd87e 100644 --- a/packages/expo-app-metrics/android/src/main/java/expo/modules/appmetrics/AppMetricsModule.kt +++ b/packages/expo-app-metrics/android/src/main/java/expo/modules/appmetrics/AppMetricsModule.kt @@ -3,6 +3,7 @@ package expo.modules.appmetrics import android.content.Context import expo.modules.appmetrics.appstartup.AppStartupManager import expo.modules.appmetrics.memory.MemoryMetricsManager +import expo.modules.appmetrics.storage.JsSession import expo.modules.appmetrics.storage.Metric import expo.modules.appmetrics.storage.SessionManager import expo.modules.appmetrics.updates.UpdatesMonitoring @@ -19,7 +20,9 @@ import expo.modules.updatesinterface.UpdatesControllerRegistry import expo.modules.updatesinterface.UpdatesStateChangeListener import expo.modules.updatesinterface.UpdatesStateChangeSubscription import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import kotlinx.serialization.json.Json class AppMetricsModule : Module(), UpdatesStateChangeListener { @@ -39,6 +42,11 @@ class AppMetricsModule : Module(), UpdatesStateChangeListener { lateinit var sessionManager: SessionManager + // Tracks the in-flight session-row INSERT kicked off in `OnCreate`. `OnDestroy` + // joins it before stamping `endTimestamp` so the UPDATE doesn't race with the + // INSERT and silently no-op. + private var sessionStartJob: Job? = null + private var didSaveStartupMetrics: Boolean = false // Lazy-initialized metadata - created once when first needed @@ -65,12 +73,22 @@ class AppMetricsModule : Module(), UpdatesStateChangeListener { OnCreate { sessionManager = SessionManager(context) - // Deactivate all sessions from previous app runs - scope.launch { + appSessionId = sessionManager.createSessionId() + + // Persist the session row eagerly so it's visible to readers + // (`getAllSessions`, `addCustomMetricToSession`, …) before any startup + // metrics arrive. Older app runs are deactivated in the same coroutine + // to keep the order well-defined. The `Job` is captured so `OnDestroy` + // can wait for the INSERT before stamping `endTimestamp`. + sessionStartJob = scope.launch { sessionManager.deactivateAllSessionsBefore(moduleCreationTimestamp) + sessionManager.startSessionWithIdAt( + sessionId = appSessionId, + timestamp = TimeUtils.getProcessStartTimestamp(), + metadata = metadata + ) } - appSessionId = sessionManager.createSessionId() memoryMetricsManager = MemoryMetricsManager( context = context, sessionManager = sessionManager @@ -92,8 +110,24 @@ class AppMetricsModule : Module(), UpdatesStateChangeListener { subscription?.remove() } + OnDestroy { + // `modulesQueue` is cancelled immediately after this hook returns, so + // run the UPDATE on the calling thread to make sure the end timestamp + // is persisted before teardown. Joining `sessionStartJob` first + // guarantees the INSERT lands before the UPDATE so the stamp doesn't + // silently no-op on a missing row. + runBlocking { + sessionStartJob?.join() + sessionManager.stopSession(appSessionId) + } + } + AsyncFunction("getStoredEntries") Coroutine { -> sessionManager.getAllSessions() } + AsyncFunction("getAllSessions") Coroutine { -> + sessionManager.getAllSessions().map { JsSession.fromSessionWithMetrics(it) } + } + AsyncFunction("takeMemoryUsageSnapshotAsync") Coroutine { sessionId: String? -> return@Coroutine memoryMetricsManager.takeMemorySnapshot(sessionId) } @@ -155,14 +189,9 @@ class AppMetricsModule : Module(), UpdatesStateChangeListener { // TODO(@lukmccall): Potential race condition - multiple coroutines could enter the block simultaneously, causing duplicates. internal suspend fun saveStartupMetricsIfNotSaved() { if (!didSaveStartupMetrics) { - // This function should be called, after all startup events are collected - // This seems to be the best place right now, because it will not slow down the app startup - sessionManager.startSessionWithIdAndMetricsAt( - id = appSessionId, - timestamp = TimeUtils.getProcessStartTimestamp(), - metrics = AppStartupManager.metrics, - metadata = metadata - ) + // The session row is written eagerly in `OnCreate`, so we only need to + // attach the startup metrics here once they've been collected. + sessionManager.addMetrics(AppStartupManager.metrics, sessionId = appSessionId) didSaveStartupMetrics = true } } diff --git a/packages/expo-app-metrics/android/src/main/java/expo/modules/appmetrics/storage/MetricsDatabase.kt b/packages/expo-app-metrics/android/src/main/java/expo/modules/appmetrics/storage/MetricsDatabase.kt index 1a5d7b3d45f969..813bc812ebc4b7 100644 --- a/packages/expo-app-metrics/android/src/main/java/expo/modules/appmetrics/storage/MetricsDatabase.kt +++ b/packages/expo-app-metrics/android/src/main/java/expo/modules/appmetrics/storage/MetricsDatabase.kt @@ -26,7 +26,7 @@ object MetricsConstants { @Database( entities = [Metric::class, Session::class], - version = 13, + version = 14, exportSchema = false ) abstract class MetricsDatabase : RoomDatabase() { @@ -62,6 +62,7 @@ abstract class MetricsDatabase : RoomDatabase() { data class Session( @PrimaryKey @Field val id: String, @Field val startTimestamp: String, // ISO 8601 date string + @Field val endTimestamp: String? = null, // ISO 8601 date string. `null` while the session is still active. @Field val isActive: Boolean = true, // Environment @Field val environment: String? = null, @@ -134,9 +135,6 @@ interface MetricDao { @Delete suspend fun delete(metrics: List) - - @Query("DELETE FROM metrics WHERE timestamp < :cutoffTimestamp") - suspend fun deleteMetricsOlderThan(cutoffTimestamp: String) } @Dao @@ -147,15 +145,25 @@ interface SessionDao { @Query("SELECT * FROM sessions WHERE id = :id") suspend fun getById(id: String): Session? - @Query("UPDATE sessions SET isActive = :isActive WHERE id = :id") - suspend fun updateActiveStatus( + @Query("UPDATE sessions SET isActive = 0, endTimestamp = :endTimestamp WHERE id = :id") + suspend fun stopSessionAt( id: String, - isActive: Boolean + endTimestamp: String ) - @Query("UPDATE sessions SET isActive = 0 WHERE startTimestamp < :timestamp") + // Stamps stale sessions as ended at `:timestamp`. Used at module creation + // to clean up sessions left behind when the previous process died (force-quit, + // OOM kill, crash) without an `OnActivityDestroys` callback. + @Query("UPDATE sessions SET isActive = 0, endTimestamp = :timestamp WHERE startTimestamp < :timestamp AND endTimestamp IS NULL") suspend fun deactivateAllSessionsBefore(timestamp: String) + // Drops sessions whose `startTimestamp` is older than the cutoff. Cascade + // deletes their metrics via the foreign-key relation. Live (`isActive = 1`) + // sessions are excluded so a long-running process doesn't lose its current + // session out from under it. + @Query("DELETE FROM sessions WHERE startTimestamp < :cutoffTimestamp AND isActive = 0") + suspend fun deleteSessionsOlderThan(cutoffTimestamp: String) + @Query("UPDATE sessions SET environment = :environment WHERE id = :id") suspend fun updateEnvironment( id: String, diff --git a/packages/expo-app-metrics/android/src/main/java/expo/modules/appmetrics/storage/SessionManager.kt b/packages/expo-app-metrics/android/src/main/java/expo/modules/appmetrics/storage/SessionManager.kt index 4793430e0775d7..e43d61d98280c2 100644 --- a/packages/expo-app-metrics/android/src/main/java/expo/modules/appmetrics/storage/SessionManager.kt +++ b/packages/expo-app-metrics/android/src/main/java/expo/modules/appmetrics/storage/SessionManager.kt @@ -90,7 +90,10 @@ class SessionManager( } suspend fun stopSession(sessionId: String) { - database.sessionDao().updateActiveStatus(sessionId, isActive = false) + database.sessionDao().stopSessionAt( + sessionId, + endTimestamp = TimeUtils.getCurrentTimestampInISOFormat() + ) } suspend fun addMetrics( @@ -125,9 +128,13 @@ class SessionManager( database.sessionDao().deactivateAllSessionsBefore(timestamp) } - suspend fun cleanupOldMetrics() { + /** + * Prunes inactive sessions whose `startTimestamp` is older than the + * retention window. Their metrics are removed via the foreign-key cascade. + */ + suspend fun cleanupOldSessions() { val cutoffTimestamp = TimeUtils.getTimestampInISOFormatFromPast(MetricsConstants.SECONDS_TO_REMOVE_OLD_METRICS) - database.metricDao().deleteMetricsOlderThan(cutoffTimestamp) + database.sessionDao().deleteSessionsOlderThan(cutoffTimestamp) } suspend fun updateEnvironmentForActiveSessions(environment: String) { diff --git a/packages/expo-app-metrics/android/src/main/java/expo/modules/appmetrics/storage/SessionMappers.kt b/packages/expo-app-metrics/android/src/main/java/expo/modules/appmetrics/storage/SessionMappers.kt new file mode 100644 index 00000000000000..9a001b561da69b --- /dev/null +++ b/packages/expo-app-metrics/android/src/main/java/expo/modules/appmetrics/storage/SessionMappers.kt @@ -0,0 +1,106 @@ +package expo.modules.appmetrics.storage + +import expo.modules.kotlin.records.Field +import expo.modules.kotlin.records.Record +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonNull +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.booleanOrNull +import kotlinx.serialization.json.doubleOrNull +import kotlinx.serialization.json.longOrNull + +/** + * JS-facing shape of a session. Field names mirror the TypeScript `Session` + * type (`startDate` / `endDate`), distinct from the Room column names + * (`startTimestamp` / `endTimestamp`). + * + * `type` is hard-coded to `"main"` since the per-launch session opened in + * `AppMetricsModule.OnCreate` is the only one we track. A future change + * should add a real `type` column and lifecycle hooks for + * foreground/screen/custom sessions. + */ +data class JsSession( + @Field val id: String, + @Field val type: String, + @Field val startDate: String, + @Field val endDate: String?, + @Field val metrics: List, + // Android doesn't collect log events yet; emitted as an empty list so + // consumers can rely on the same shape iOS produces. + @Field val logs: List = emptyList() +) : Record { + companion object { + fun fromSessionWithMetrics(value: SessionWithMetrics): JsSession = + JsSession( + id = value.session.id, + type = "main", + startDate = value.session.startTimestamp, + endDate = value.session.endTimestamp, + metrics = value.metrics.map { JsMetric.fromMetric(it) } + ) + } +} + +data class JsMetric( + @Field val metricId: String, + @Field val sessionId: String, + @Field val timestamp: String, + @Field val category: String, + @Field val name: String, + @Field val value: Double, + @Field val routeName: String?, + @Field val updateId: String?, + @Field val params: Map? +) : Record { + companion object { + fun fromMetric(metric: Metric): JsMetric = + JsMetric( + metricId = metric.metricId, + sessionId = metric.sessionId, + timestamp = metric.timestamp, + category = metric.category, + name = metric.name, + value = metric.value, + routeName = metric.routeName, + updateId = metric.updateId, + params = decodeJsonObject(metric.params) + ) + } +} + +/** + * Decodes a JSON-encoded object string into a `Map` whose values + * are plain Kotlin primitives (`String`, `Long`, `Double`, `Boolean`, `List`, + * `Map`, or `null`). Returns `null` if the input is `null`/empty or if parsing + * fails — JS code treats `null` as "no extras". + */ +private fun decodeJsonObject(jsonString: String?): Map? { + if (jsonString.isNullOrEmpty()) { + return null + } + return runCatching { + val element = Json.decodeFromString(jsonString) + if (element !is JsonObject) { + return@runCatching null + } + element.mapValues { (_, v) -> jsonElementToAny(v) } + }.getOrNull() +} + +private fun jsonElementToAny(element: JsonElement): Any? { + return when (element) { + is JsonNull -> null + is JsonPrimitive -> when { + element.isString -> element.content + else -> element.booleanOrNull + ?: element.longOrNull + ?: element.doubleOrNull + ?: element.content + } + is JsonObject -> element.mapValues { (_, v) -> jsonElementToAny(v) } + is JsonArray -> element.map { jsonElementToAny(it) } + } +} diff --git a/packages/expo-app-metrics/android/src/test/java/expo/modules/appmetrics/storage/SessionManagerTest.kt b/packages/expo-app-metrics/android/src/test/java/expo/modules/appmetrics/storage/SessionManagerTest.kt index d3c82d135691bb..f0c6f7b89dabf5 100644 --- a/packages/expo-app-metrics/android/src/test/java/expo/modules/appmetrics/storage/SessionManagerTest.kt +++ b/packages/expo-app-metrics/android/src/test/java/expo/modules/appmetrics/storage/SessionManagerTest.kt @@ -207,6 +207,21 @@ class SessionManagerTest { assertFalse(allSessions[0].session.isActive) } + @Test + fun `stopSession stamps endTimestamp`() = + runTest { + // Arrange + val sessionId = "test-session" + sessionManager.startSessionWithIdAt(sessionId, "2025-01-01T00:00:00.000Z") + + // Act + sessionManager.stopSession(sessionId) + + // Assert + val stopped = sessionManager.getAllSessions().single() + assertNotNull("endTimestamp should be set after stopSession", stopped.session.endTimestamp) + } + @Test fun `deactivateAllSessionsBefore deactivates old sessions only`() = runTest { @@ -225,6 +240,46 @@ class SessionManagerTest { assertEquals(newSession, activeSessions[0].session.id) } + @Test + fun `deactivateAllSessionsBefore stamps endTimestamp on orphan sessions`() = + runTest { + // Arrange — a session left active across launches (force-killed process, + // OOM, etc.). On the next module create we deactivate it, and the cutoff + // timestamp is the heuristic end-time we record. + val orphan = "orphan-session" + sessionManager.startSessionWithIdAt(orphan, "2025-01-01T00:00:00.000Z") + + // Act + val cutoff = "2025-01-10T00:00:00.000Z" + sessionManager.deactivateAllSessionsBefore(cutoff) + + // Assert + val deactivated = sessionManager.getAllSessions().single { it.session.id == orphan } + assertFalse(deactivated.session.isActive) + assertEquals(cutoff, deactivated.session.endTimestamp) + } + + @Test + fun `deactivateAllSessionsBefore preserves existing endTimestamps`() = + runTest { + // Arrange — a session that was properly stopped via stopSession should + // keep its real end time even if it predates the deactivate cutoff. + val cleanlyStopped = "clean-session" + sessionManager.startSessionWithIdAt(cleanlyStopped, "2025-01-01T00:00:00.000Z") + sessionManager.stopSession(cleanlyStopped) + val originalEnd = sessionManager.getAllSessions() + .single { it.session.id == cleanlyStopped } + .session.endTimestamp + assertNotNull("precondition: stopSession should have stamped endTimestamp", originalEnd) + + // Act + sessionManager.deactivateAllSessionsBefore("2025-01-10T00:00:00.000Z") + + // Assert — the cleanly-stopped session keeps its original end time. + val preserved = sessionManager.getAllSessions().single { it.session.id == cleanlyStopped } + assertEquals(originalEnd, preserved.session.endTimestamp) + } + @Test fun `updateEnvironmentForActiveSessions updates only active sessions`() = runTest { @@ -599,6 +654,45 @@ class SessionManagerTest { assertEquals(0, sessionManager.getAllSessions().size) } + @Test + fun `cleanupOldSessions removes inactive sessions older than the retention window`() = + runTest { + // Arrange — three sessions across the cutoff. We can't pick a static + // timestamp like the other tests because the retention window is computed + // from `now`, so we anchor against the current time. + val now = System.currentTimeMillis() + val retentionMs = MetricsConstants.SECONDS_TO_REMOVE_OLD_METRICS * 1000 + val isoFormatter = java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", java.util.Locale.US) + .apply { timeZone = java.util.TimeZone.getTimeZone("UTC") } + + val staleStoppedId = "stale-stopped" + val staleActiveId = "stale-active" + val freshStoppedId = "fresh-stopped" + + val staleStart = isoFormatter.format(java.util.Date(now - retentionMs - 60_000)) + val freshStart = isoFormatter.format(java.util.Date(now - 60_000)) + + sessionManager.startSessionWithIdAt(staleStoppedId, staleStart) + sessionManager.stopSession(staleStoppedId) + + sessionManager.startSessionWithIdAt(staleActiveId, staleStart) + // Intentionally not stopped — simulates a long-running session. + + sessionManager.startSessionWithIdAt(freshStoppedId, freshStart) + sessionManager.stopSession(freshStoppedId) + + // Act + sessionManager.cleanupOldSessions() + + // Assert — only the stopped, stale session is gone. The active stale + // session is preserved (we don't pull a session out from under a + // long-running process), and the fresh stopped session is preserved. + val remaining = sessionManager.getAllSessions().map { it.session.id }.toSet() + assertFalse("stale stopped session should be cleaned up", remaining.contains(staleStoppedId)) + assertTrue("stale but active session should be preserved", remaining.contains(staleActiveId)) + assertTrue("fresh stopped session should be preserved", remaining.contains(freshStoppedId)) + } + // endregion // region Helper Methods diff --git a/packages/expo-app-metrics/android/src/test/java/expo/modules/appmetrics/storage/SessionMappersTest.kt b/packages/expo-app-metrics/android/src/test/java/expo/modules/appmetrics/storage/SessionMappersTest.kt new file mode 100644 index 00000000000000..a01182b551482e --- /dev/null +++ b/packages/expo-app-metrics/android/src/test/java/expo/modules/appmetrics/storage/SessionMappersTest.kt @@ -0,0 +1,103 @@ +package expo.modules.appmetrics.storage + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config + +@RunWith(RobolectricTestRunner::class) +@Config(manifest = Config.NONE, sdk = [28]) +class SessionMappersTest { + private fun makeSession( + id: String = "session-1", + startTimestamp: String = "2025-01-01T00:00:00.000Z", + endTimestamp: String? = null + ): Session = Session( + id = id, + startTimestamp = startTimestamp, + endTimestamp = endTimestamp, + isActive = endTimestamp == null + ) + + private fun makeMetric( + metricId: String = "metric-1", + sessionId: String = "session-1", + params: String? = null + ): Metric = Metric( + metricId = metricId, + sessionId = sessionId, + timestamp = "2025-01-01T00:00:01.000Z", + category = "appStartup", + name = "timeToInteractive", + value = 1.5, + params = params + ) + + @Test + fun `JsSession_fromSessionWithMetrics exposes the JS-facing field names`() { + val swm = SessionWithMetrics( + session = makeSession(id = "abc", startTimestamp = "2025-06-15T10:00:00.000Z"), + metrics = emptyList() + ) + + val js = JsSession.fromSessionWithMetrics(swm) + + assertEquals("abc", js.id) + assertEquals("main", js.type) + assertEquals("2025-06-15T10:00:00.000Z", js.startDate) + assertNull(js.endDate) + assertEquals(emptyList(), js.metrics) + } + + @Test + fun `JsSession_fromSessionWithMetrics surfaces endDate when set`() { + val swm = SessionWithMetrics( + session = makeSession(endTimestamp = "2025-01-02T00:00:00.000Z"), + metrics = emptyList() + ) + + val js = JsSession.fromSessionWithMetrics(swm) + + assertEquals("2025-01-02T00:00:00.000Z", js.endDate) + } + + @Test + fun `JsMetric_fromMetric decodes params from JSON`() { + val metric = makeMetric(params = """{"screen":"Home","attempt":3,"flag":true}""") + + val js = JsMetric.fromMetric(metric) + + val params = js.params + assertEquals("Home", params?.get("screen")) + assertEquals(3L, params?.get("attempt")) + assertEquals(true, params?.get("flag")) + } + + @Test + fun `JsMetric_fromMetric yields null params when storage column is null`() { + val js = JsMetric.fromMetric(makeMetric(params = null)) + + assertNull(js.params) + } + + @Test + fun `JsMetric_fromMetric yields null params when storage column is malformed JSON`() { + val js = JsMetric.fromMetric(makeMetric(params = "{ this is not valid json")) + + assertNull(js.params) + } + + @Test + fun `JsMetric_fromMetric copies scalar fields verbatim`() { + val js = JsMetric.fromMetric(makeMetric(metricId = "m-42", sessionId = "session-1")) + + assertEquals("m-42", js.metricId) + assertEquals("session-1", js.sessionId) + assertEquals("appStartup", js.category) + assertEquals("timeToInteractive", js.name) + assertEquals(1.5, js.value, 0.0) + assertEquals("2025-01-01T00:00:01.000Z", js.timestamp) + } +} diff --git a/packages/expo-file-system/CHANGELOG.md b/packages/expo-file-system/CHANGELOG.md index ba4b8ef527548a..966f2ebab8b444 100644 --- a/packages/expo-file-system/CHANGELOG.md +++ b/packages/expo-file-system/CHANGELOG.md @@ -10,6 +10,8 @@ ### 💡 Others +- Improved public API docs. ([#45530](https://github.com/expo/expo/pull/45530) by [@barthap](https://github.com/barthap)) + ## 56.0.3 — 2026-05-06 _This version does not introduce any user-facing changes._ diff --git a/packages/expo-file-system/build/ExpoFileSystem.d.ts b/packages/expo-file-system/build/ExpoFileSystem.d.ts index c3c8e9f0bd9ef5..e21f71f13d16a5 100644 --- a/packages/expo-file-system/build/ExpoFileSystem.d.ts +++ b/packages/expo-file-system/build/ExpoFileSystem.d.ts @@ -13,13 +13,31 @@ type DownloadTaskEvents = { progress: (data: DownloadProgress) => void; }; declare class FileSystemUploadTask extends SharedObject { + /** + * @hidden + */ start(url: string, file: File, options: Record): Promise; + /** + * @hidden + */ cancel(): void; } declare class FileSystemDownloadTask extends SharedObject { + /** + * @hidden + */ start(url: string, to: File | Directory, options?: Record): Promise; + /** + * @hidden + */ pause(): any; + /** + * @hidden + */ resume(url: string, to: File | Directory, resumeData: string, options?: Record): Promise; + /** + * @hidden + */ cancel(): void; } type FileSystemWatcherEvent = { diff --git a/packages/expo-file-system/build/ExpoFileSystem.d.ts.map b/packages/expo-file-system/build/ExpoFileSystem.d.ts.map index 811f0f98bc11cd..db58fe2452ae3b 100644 --- a/packages/expo-file-system/build/ExpoFileSystem.d.ts.map +++ b/packages/expo-file-system/build/ExpoFileSystem.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"ExpoFileSystem.d.ts","sourceRoot":"","sources":["../src/ExpoFileSystem.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"ExpoFileSystem.d.ts","sourceRoot":"","sources":["../src/ExpoFileSystem.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/expo-file-system/build/ExpoFileSystem.types.d.ts b/packages/expo-file-system/build/ExpoFileSystem.types.d.ts index 609d89a8323466..aa17291c009ac2 100644 --- a/packages/expo-file-system/build/ExpoFileSystem.types.d.ts +++ b/packages/expo-file-system/build/ExpoFileSystem.types.d.ts @@ -10,6 +10,9 @@ export type FileCreateOptions = { */ overwrite?: boolean; }; +/** + * Options for moving or copying files and directories. + */ export type RelocationOptions = { /** * Whether to overwrite the destination if it exists. @@ -41,6 +44,7 @@ export type FileWriteOptions = { }; /** * The default debounce time for file system watcher events in milliseconds. + * @hidden */ export declare const DEFAULT_DEBOUNCE_MS = 100; /** @@ -82,7 +86,7 @@ export type WatchEvent = { export type WatchOptions = { /** * The debounce interval in milliseconds for coalescing rapid successive events into a single callback. - * @default DEFAULT_DEBOUNCE_MS + * @default 100 */ debounce?: number; /** @@ -323,7 +327,7 @@ export declare class File { validatePath(): void; /** * Retrieves text from the file. - * @returns A promise that resolves with the contents of the file as string. + * @returns A promise fulfilled with the contents of the file as string. */ text(): Promise; /** @@ -333,7 +337,7 @@ export declare class File { textSync(): string; /** * Retrieves content of the file as base64. - * @returns A promise that resolves with the contents of the file as a base64 string. + * @returns A promise fulfilled with the contents of the file as a base64 string. */ base64(): Promise; /** @@ -343,7 +347,7 @@ export declare class File { base64Sync(): string; /** * Retrieves byte content of the entire file. - * @returns A promise that resolves with the contents of the file as a `Uint8Array`. + * @returns A promise fulfilled with the contents of the file as a `Uint8Array`. */ bytes(): Promise>; /** @@ -423,7 +427,7 @@ export declare class File { * @param destination - The destination directory or file. If a directory is provided, the resulting filename will be determined based on the response headers. * @param options - Download options. When the destination already contains a file, the promise rejects with a `DestinationAlreadyExists` error unless `options.idempotent` is set to `true`. With `idempotent: true`, the download overwrites the existing file instead of failing. * - * @returns A promise that resolves to the downloaded file. When the server responds with + * @returns A promise fulfilled with the downloaded file. When the server responds with * a non-2xx HTTP status, the promise rejects with an `UnableToDownload` error whose * message includes the status code. No file is created in that scenario. * @@ -436,7 +440,7 @@ export declare class File { /** * Uploads this file to the network. * - * The promise resolves with the HTTP response metadata and body for any completed response, + * The promise is fulfilled with the HTTP response metadata and body for any completed response, * including non-2xx status codes. It rejects only for local file errors, transport failures, * or cancellation. * @@ -445,15 +449,33 @@ export declare class File { */ upload(url: string, options?: UploadOptions): Promise; /** - * An overload of the `pickFileAsync` method, which picks and returns a single `File`. - * This overload requires options to have `multipleFiles` flag be `undefined` or `false`. - * @param options options + * Opens the system file picker for selecting a single file. + * + * This overload requires `options.multipleFiles` to be `undefined` or `false`. + * + * @param options File picker options. */ static pickFileAsync(options?: PickSingleFileOptions): Promise; /** - * An overload of the `pickFileAsync` method, which picks and returns a list of `File`'s. - * This overload requires options to have `multipleFiles` flag be `true`. - * @param options options + * Opens the system file picker for selecting multiple files. + * + * This overload requires `options.multipleFiles` to be `true`. + * + * @param options File picker options. + * + * @example + * ```ts + * const result = await File.pickFileAsync({ + * multipleFiles: true, + * mimeTypes: ['image/*', 'application/pdf'], + * }); + * + * if (!result.canceled) { + * for (const file of result.result) { + * console.log(file.uri); + * } + * } + * ``` */ static pickFileAsync(options?: PickMultipleFilesOptions): Promise; /** @@ -622,6 +644,9 @@ export type DirectoryInfo = { */ files?: string[]; }; +/** + * Shared options accepted by file picker calls. + */ export type PickFileGeneralOptions = { /** * A URI pointing to an initial folder in which the file picker is opened. @@ -644,12 +669,19 @@ export type PickFileGeneralOptions = { * Options for picking a single file. */ export type PickSingleFileOptions = PickFileGeneralOptions & { + /** + * Keeps the picker in single-file mode. Omit this property or set it to `false` when selecting one file. + * @default false + */ multipleFiles?: false; }; /** * Options for picking multiple files. */ export type PickMultipleFilesOptions = PickFileGeneralOptions & { + /** + * Allows multiple files to be selected from the system UI. + */ multipleFiles: true; }; /** @@ -659,31 +691,61 @@ export type PickMultipleFilesOptions = PickFileGeneralOptions & { export type PickFileOptions = PickSingleFileOptions | PickMultipleFilesOptions; /** * Result type for picking a single file. + * + * Successful picks return `{ result: File, canceled: false }`. Canceled picks return + * `{ result: null, canceled: true }`. */ export type PickSingleFileResult = PickSingleFileSuccessResult | PickFileCanceledResult; /** * Result type for picking multiple files. + * + * Successful picks return `{ result: File[], canceled: false }`. Canceled picks return + * `{ result: null, canceled: true }`. */ export type PickMultipleFilesResult = PickMultipleFilesSuccessResult | PickFileCanceledResult; /** * Result type for successfully picking a single file. + * @inline + * @docsInline */ export type PickSingleFileSuccessResult = { + /** + * The selected file. + */ result: File; + /** + * Indicates that the picker completed with a selected file. + */ canceled: false; }; /** - * Result type for a successful picking multiple files. + * Result type for successfully picking multiple files. + * @inline + * @docsInline */ export type PickMultipleFilesSuccessResult = { + /** + * The selected files. + */ result: File[]; + /** + * Indicates that the picker completed with selected files. + */ canceled: false; }; /** * Result type for a canceled file pick. + * @inline + * @docsInline */ export type PickFileCanceledResult = { + /** + * Always `null` when the picker is canceled. + */ result: null; + /** + * Indicates that the user canceled the picker without selecting files. + */ canceled: true; }; /** @@ -861,10 +923,14 @@ export type UploadTaskState = Exclude; export type DownloadTaskState = TaskState; /** * Represents an upload task with progress tracking and cancellation support. + * + * Create instances with `new UploadTask(...)` or `file.createUploadTask(...)`, then call + * `uploadAsync()` to start the upload. */ export declare class UploadTask { /** - * The current state of the upload task. + * The current state of the upload task. Upload tasks move from `idle` to `active`, then to + * `completed`, `cancelled`, or `error`. */ readonly state: UploadTaskState; /** @@ -875,18 +941,21 @@ export declare class UploadTask { */ constructor(file: File, url: string, options?: UploadOptions); /** - * Starts the upload operation. - * @returns A promise that resolves with the upload result. - * If the task is cancelled via `cancel()` or `signal`, the promise rejects. + * Starts the upload operation. This method can only be called once, while the task is `idle`. + * + * @returns A promise fulfilled with the upload result. The promise is rejected when the upload + * cannot read the file, the request fails, or the task is cancelled. */ uploadAsync(): Promise; /** - * Cancels the upload operation. - * Any pending `uploadAsync()` promise rejects after cancellation. + * Cancels the upload operation. If `uploadAsync()` is pending, its promise is rejected after the + * native request is cancelled. */ cancel(): void; /** * Adds a listener for upload progress events. + * + * > **Note:** Prefer the `onProgress` option unless you need manual subscription control. */ addListener(eventName: 'progress', listener: (data: UploadProgress) => void): { remove: () => void; @@ -894,10 +963,14 @@ export declare class UploadTask { } /** * Represents a download task with pause/resume support and progress tracking. + * + * Create instances with `new DownloadTask(...)` or `File.createDownloadTask(...)`, then call + * `downloadAsync()` to start the download. */ export declare class DownloadTask { /** - * The current state of the download task. + * The current state of the download task. Download tasks move from `idle` to `active`, then to + * `paused`, `completed`, `cancelled`, or `error`. */ readonly state: DownloadTaskState; /** @@ -908,40 +981,53 @@ export declare class DownloadTask { */ constructor(url: string, destination: File | Directory, options?: DownloadTaskOptions); /** - * Starts the download operation. - * @returns A promise that resolves with the downloaded file, or null if paused. - * If the task is cancelled via `cancel()` or `signal`, the promise rejects. + * Starts the download operation. This method can only be called once, while the task is `idle`. + * + * @returns A promise fulfilled with the downloaded file, or `null` if the task is paused before + * completion. The promise is rejected when the request fails or the task is cancelled. */ downloadAsync(): Promise; /** - * Pauses the download operation. The pending downloadAsync() promise resolves with null. + * Requests pausing the active download operation. The pending `downloadAsync()` or `resumeAsync()` + * promise is fulfilled with `null` after native code produces resume data and the task enters the + * `paused` state. */ pause(): void; + /** + * Requests pausing the active download operation and waits until the task reaches the `paused` + * state. + */ + pauseAsync(): Promise; /** * Resumes a paused download operation. - * @returns A promise that resolves with the downloaded file, or null if paused again. - * If the task is cancelled via `cancel()` or `signal`, the promise rejects. + * + * @returns A promise fulfilled with the downloaded file, or `null` if the task is paused again. + * The promise is rejected when the request fails or the task is cancelled. */ resumeAsync(): Promise; /** - * Cancels the download operation. - * Any pending `downloadAsync()` or `resumeAsync()` promise rejects after cancellation. + * Cancels the download operation. If `downloadAsync()` or `resumeAsync()` is pending, its promise + * is rejected after the native request is cancelled. */ cancel(): void; /** - * Returns the current state that can be persisted and restored later. + * Returns the paused task state that can be persisted and restored later. + * * @returns The pause state. */ savable(): DownloadPauseState; /** * Creates a download task from a saved state. + * * @param state The saved pause state. - * @param options Optional new options to attach (e.g. onProgress, signal) since those are not persisted. + * @param options Optional new options to attach, such as `onProgress` or `signal`, since those are not persisted. * @returns A new download task. */ static fromSavable(state: DownloadPauseState, options?: DownloadTaskOptions): DownloadTask; /** * Adds a listener for download progress events. + * + * > **Note:** Prefer the `onProgress` option unless you need manual subscription control. */ addListener(eventName: 'progress', listener: (data: DownloadProgress) => void): { remove: () => void; diff --git a/packages/expo-file-system/build/ExpoFileSystem.types.d.ts.map b/packages/expo-file-system/build/ExpoFileSystem.types.d.ts.map index f574e6b39950f7..239a29c19db460 100644 --- a/packages/expo-file-system/build/ExpoFileSystem.types.d.ts.map +++ b/packages/expo-file-system/build/ExpoFileSystem.types.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"ExpoFileSystem.types.d.ts","sourceRoot":"","sources":["../src/ExpoFileSystem.types.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"ExpoFileSystem.types.d.ts","sourceRoot":"","sources":["../src/ExpoFileSystem.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,oBAAY,YAAY;IACtB;;OAEG;IACH,IAAI,SAAS;IACb;;OAEG;IACH,MAAM,WAAW;CAClB;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;OAGG;IACH,QAAQ,CAAC,EAAE,YAAY,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC5C;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;AAE5E;;GAEG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,IAAI,GAAG,SAAS,IAAI;IACnD;;OAEG;IACH,IAAI,EAAE,cAAc,CAAC;IACrB;;OAEG;IACH,MAAM,EAAE,CAAC,CAAC;IACV;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,CAAC;CACf,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,cAAc,EAAE,CAAC;CAC3B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;OAGG;IACH,MAAM,IAAI,IAAI,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF;;GAEG;AACH,oBAAY,QAAQ;IAClB;;;;;OAKG;IACH,SAAS,OAAO;IAEhB;;;OAGG;IACH,QAAQ,MAAM;IAEd;;;OAGG;IACH,SAAS,MAAM;IAEf;;;;;;OAMG;IACH,MAAM,OAAO;IAEb;;OAEG;IACH,QAAQ,OAAO;CAChB;AAED,MAAM,CAAC,OAAO,OAAO,SAAS;IAC5B;;;;;;;OAOG;gBACS,GAAG,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE;IAElD;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,YAAY,IAAI,IAAI;IAEpB;;;;OAIG;IACH,MAAM,IAAI,IAAI;IAEd;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAEhB;;;;OAIG;IACH,MAAM,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,IAAI;IAE9C,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAEvD,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS;IAExC;;;;;;;;;OASG;IACH,KAAK,CACH,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,IAAI,GAAG,SAAS,CAAC,KAAK,IAAI,EACvD,OAAO,CAAC,EAAE,YAAY,GACrB,iBAAiB;IAEpB;;OAEG;IACH,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAE/E;;OAEG;IACH,QAAQ,CAAC,WAAW,EAAE,SAAS,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,IAAI;IAE1E;;OAEG;IACH,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAE/E;;OAEG;IACH,QAAQ,CAAC,WAAW,EAAE,SAAS,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,IAAI;IAE1E;;OAEG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAE7B;;;;OAIG;IACH,aAAa,IAAI;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE;IAEvD;;OAEG;IACH,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,EAAE;IAE5B;;;;;;OAMG;IACH,IAAI,IAAI,aAAa;IAErB;;OAEG;IACH,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpB;;;;;;;OAOG;IACH,MAAM,CAAC,kBAAkB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;CACnE;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B;;OAEG;IACH,OAAO,CAAC,EAAE;QACR,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;KACvB,CAAC;IACF;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC9C;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,IAAI;IACvB;;;;OAIG;gBACS,GAAG,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE;IAElD;;OAEG;IACH,IAAI,GAAG,IAAI,MAAM,CAAC;IAElB;;;OAGG;IACH,YAAY,IAAI,IAAI;IAEpB;;;OAGG;IACH,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAEvB;;;OAGG;IACH,QAAQ,IAAI,MAAM;IAElB;;;OAGG;IACH,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAEzB;;;OAGG;IACH,UAAU,IAAI,MAAM;IAEpB;;;OAGG;IACH,KAAK,IAAI,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAEzC;;;OAGG;IACH,SAAS,IAAI,UAAU;IAEvB;;;OAGG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,IAAI;IAErE;;;;OAIG;IACH,MAAM,IAAI,IAAI;IAEd;;;;OAIG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,QAAQ;IAErC;;;OAGG;IACH,MAAM,EAAE,OAAO,CAAC;IAEhB;;;;OAIG;IACH,MAAM,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,IAAI;IAEzC;;OAEG;IACH,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAE/E;;OAEG;IACH,QAAQ,CAAC,WAAW,EAAE,SAAS,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,IAAI;IAE1E;;OAEG;IACH,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAE/E;;OAEG;IACH,QAAQ,CAAC,WAAW,EAAE,SAAS,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,IAAI;IAE1E;;OAEG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAE7B;;;;;;;;;;OAUG;IACH,IAAI,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,UAAU;IAEjC;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,iBAAiB,CACtB,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,SAAS,GAAG,IAAI,EAC7B,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,IAAI,CAAC;IAEhB;;;;;;;;;OASG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAEnE;;;;;;OAMG;IACH,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IACpF;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,wBAAwB,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAC1F;;;;;;;;;OASG;IACH,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,EAAE,CAAC;IAEpF;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,kBAAkB,CACvB,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,SAAS,GAAG,IAAI,EAC7B,OAAO,CAAC,EAAE,mBAAmB,GAC5B,YAAY;IAEf;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,UAAU;IAElE;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAEnB;;;OAGG;IACH,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhC;;OAEG;IACH,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAE5B;;OAEG;IACH,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAE5B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,KAAK,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,iBAAiB;CAC9F;AAED,MAAM,CAAC,OAAO,OAAO,UAAU;IAI7B,KAAK,IAAI,IAAI;IAKb,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC;IAKlD,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAMnC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAItB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB;;;;OAIG;IACH,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB;;OAEG;IACH,WAAW,EAAE,OAAO,GAAG,IAAI,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC9B;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,sBAAsB,GAAG;IAC3D;;;OAGG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC;CACvB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG,sBAAsB,GAAG;IAC9D;;OAEG;IACH,aAAa,EAAE,IAAI,CAAC;CACrB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,qBAAqB,GAAG,wBAAwB,CAAC;AAE/E;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG,2BAA2B,GAAG,sBAAsB,CAAC;AAExF;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,GAAG,8BAA8B,GAAG,sBAAsB,CAAC;AAE9F;;;;GAIG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC;;OAEG;IACH,MAAM,EAAE,IAAI,CAAC;IACb;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAC;CACjB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,8BAA8B,GAAG;IAC3C;;OAEG;IACH,MAAM,EAAE,IAAI,EAAE,CAAC;IACf;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAC;CACjB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC;;OAEG;IACH,MAAM,EAAE,IAAI,CAAC;IACb;;OAEG;IACH,QAAQ,EAAE,IAAI,CAAC;CAChB,CAAC;AAEF;;GAEG;AACH,oBAAY,UAAU;IACpB;;OAEG;IACH,cAAc,IAAI;IAClB;;OAEG;IACH,SAAS,IAAI;CACd;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;IACtC;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IAC5C;;;;;;;;;;;OAWG;IACH,WAAW,CAAC,EAAE,sBAAsB,CAAC;IACrC;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;;;;;;;;;;OAYG;IACH,WAAW,CAAC,EAAE,sBAAsB,CAAC;IACrC;;OAEG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC9C;;OAEG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,YAAY,GAAG,YAAY,CAAC;AAEjE;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;GAGG;AACH,KAAK,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,GAAG,OAAO,CAAC;AAEpF;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAE3D;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,SAAS,CAAC;AAE1C;;;;;GAKG;AACH,MAAM,CAAC,OAAO,OAAO,UAAU;IAC7B;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAEhC;;;;;OAKG;gBACS,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa;IAE5D;;;;;OAKG;IACH,WAAW,IAAI,OAAO,CAAC,YAAY,CAAC;IAEpC;;;OAGG;IACH,MAAM,IAAI,IAAI;IAEd;;;;OAIG;IACH,WAAW,CACT,SAAS,EAAE,UAAU,EACrB,QAAQ,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,GACvC;QAAE,MAAM,EAAE,MAAM,IAAI,CAAA;KAAE;CAC1B;AAED;;;;;GAKG;AACH,MAAM,CAAC,OAAO,OAAO,YAAY;IAC/B;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;IAElC;;;;;OAKG;gBACS,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,GAAG,SAAS,EAAE,OAAO,CAAC,EAAE,mBAAmB;IAErF;;;;;OAKG;IACH,aAAa,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAErC;;;;OAIG;IACH,KAAK,IAAI,IAAI;IAEb;;;OAGG;IACH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAE3B;;;;;OAKG;IACH,WAAW,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAEnC;;;OAGG;IACH,MAAM,IAAI,IAAI;IAEd;;;;OAIG;IACH,OAAO,IAAI,kBAAkB;IAE7B;;;;;;OAMG;IACH,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,kBAAkB,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,YAAY;IAE1F;;;;OAIG;IACH,WAAW,CACT,SAAS,EAAE,UAAU,EACrB,QAAQ,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,GACzC;QAAE,MAAM,EAAE,MAAM,IAAI,CAAA;KAAE;CAC1B"} \ No newline at end of file diff --git a/packages/expo-file-system/build/FileSystem.d.ts b/packages/expo-file-system/build/FileSystem.d.ts index 7d5701cc957951..efe83486fecbb5 100644 --- a/packages/expo-file-system/build/FileSystem.d.ts +++ b/packages/expo-file-system/build/FileSystem.d.ts @@ -1,5 +1,6 @@ +import { type EventSubscription } from 'expo-modules-core'; import ExpoFileSystem from './ExpoFileSystem'; -import { type DownloadOptions, type PathInfo, type UploadOptions, type UploadResult, type DownloadTaskOptions, type DownloadPauseState, type UploadTaskState, type DownloadTaskState, type WatchEvent, type WatchOptions, type WatchSubscription } from './ExpoFileSystem.types'; +import { type DownloadOptions, type PathInfo, type UploadOptions, type UploadProgress, type UploadResult, type DownloadProgress, type DownloadTaskOptions, type DownloadPauseState, type UploadTaskState, type DownloadTaskState, type WatchEvent, type WatchOptions, type WatchSubscription } from './ExpoFileSystem.types'; import { PathUtilities } from './pathUtilities'; export declare class Paths extends PathUtilities { /** @@ -67,8 +68,66 @@ export declare class File extends ExpoFileSystem.FileSystemFile implements Blob arrayBuffer(): Promise; stream(): ReadableStream>; slice(start?: number, end?: number, contentType?: string): Blob; + /** + * Uploads this file to a server and starts the request immediately. + * + * The promise is fulfilled with response metadata and body for completed HTTP responses, + * including non-2xx status codes. It is rejected only when the file cannot be read, the + * request fails, or the upload is cancelled. + * + * @param url The URL to upload the file to. + * @param options Upload options. + * @returns A promise fulfilled with the upload response. + */ upload(url: string, options?: UploadOptions): Promise; + /** + * Creates an upload task for this file without starting it. + * + * Call `uploadAsync()` on the returned task to start the upload. Use this when you need to + * inspect task state, cancel the upload, or subscribe to progress manually. + * + * @param url The URL to upload the file to. + * @param options Upload options. + * @returns An upload task that can be started with `uploadAsync()`. + * + * @example + * ```ts + * const file = new File(Paths.document, 'photo.jpg'); + * const task = file.createUploadTask('https://example.com/upload', { + * uploadType: UploadType.MULTIPART, + * onProgress: ({ bytesSent, totalBytes }) => { + * console.log(`${bytesSent} / ${totalBytes}`); + * }, + * }); + * + * const result = await task.uploadAsync(); + * ``` + */ createUploadTask(url: string, options?: UploadOptions): UploadTask; + /** + * Creates a download task without starting it. + * + * Call `downloadAsync()` on the returned task to start the download. Use this when you need + * pause/resume support, task state, cancellation, or manual progress subscriptions. + * + * @param url The URL of the file to download. + * @param destination The destination file or directory. If a directory is provided, the + * resulting filename is determined from the response headers or URL. + * @param options Download task options. + * @returns A download task that can be started with `downloadAsync()`. + * + * @example + * ```ts + * const destination = new File(Paths.document, 'video.mp4'); + * const task = File.createDownloadTask('https://example.com/video.mp4', destination, { + * onProgress: ({ bytesWritten, totalBytes }) => { + * console.log(`${bytesWritten} / ${totalBytes}`); + * }, + * }); + * + * const file = await task.downloadAsync(); + * ``` + */ static createDownloadTask(url: string, destination: File | Directory, options?: DownloadTaskOptions): DownloadTask; /** * Watches this file for changes on the filesystem. @@ -158,6 +217,9 @@ export declare class Directory extends ExpoFileSystem.FileSystemDirectory { } /** * Represents an upload task with progress tracking and cancellation support. + * + * Upload tasks start in the `idle` state. Calling `uploadAsync()` moves the task to `active`, + * then to `completed`, `cancelled`, or `error`. */ export declare class UploadTask extends ExpoFileSystem.FileSystemUploadTask { private _state; @@ -166,13 +228,56 @@ export declare class UploadTask extends ExpoFileSystem.FileSystemUploadTask { private _options?; private _subscription?; private _abortHandler?; + /** + * Creates an upload task. + * + * The task does not start automatically. Call `uploadAsync()` to begin uploading. + * + * @param file The file to upload. + * @param url The URL to upload the file to. + * @param options Upload options. + */ constructor(file: File, url: string, options?: UploadOptions); + /** + * The current state of the upload task. + */ get state(): UploadTaskState; + /** + * Starts the upload operation. + * + * This method can only be called once, while the task is `idle`. The promise is fulfilled + * with response metadata and body for completed HTTP responses, including non-2xx status codes. + * It is rejected when the file cannot be read, the request fails, or the task is cancelled. + * + * If `options.signal` is aborted, the promise is rejected with an `AbortError`. + * + * @returns A promise fulfilled with the upload response. + */ uploadAsync(): Promise; + /** + * Adds a listener for upload progress events. + * + * > **Note:** Prefer the `onProgress` option unless you need manual subscription control. + * + * @param eventName The event to listen to. Only `'progress'` is supported. + * @param listener Invoked with upload progress updates. + * @returns A subscription handle. Call `remove()` to stop listening. + */ + addListener(eventName: 'progress', listener: (data: UploadProgress) => void): EventSubscription; + /** + * Cancels the upload operation. + * + * If `uploadAsync()` is pending, its promise is rejected after the native request is cancelled. + * Calling this method after the task reaches `completed`, `cancelled`, or `error` has no effect. + */ cancel(): void; } /** * Represents a download task with pause/resume support and progress tracking. + * + * Download tasks start in the `idle` state. Calling `downloadAsync()` moves the task to `active`; + * pausing moves it to `paused`, and a completed, cancelled, or failed transfer moves it to the + * corresponding terminal state. */ export declare class DownloadTask extends ExpoFileSystem.FileSystemDownloadTask { private _state; @@ -184,14 +289,98 @@ export declare class DownloadTask extends ExpoFileSystem.FileSystemDownloadTask private _abortHandler?; private _inFlightOperation?; private _pauseRequest?; + /** + * Creates a download task. + * + * The task does not start automatically. Call `downloadAsync()` to begin downloading. + * + * @param url The URL of the file to download. + * @param destination The destination file or directory. If a directory is provided, the resulting + * filename is determined from the response headers or URL. + * @param options Download task options. + */ constructor(url: string, destination: File | Directory, options?: DownloadTaskOptions); + /** + * The current state of the download task. + */ get state(): DownloadTaskState; + /** + * Starts the download operation. + * + * This method can only be called once, while the task is `idle`. The promise is fulfilled with + * the downloaded file when the transfer completes, or with `null` if the task is paused before + * completion. It is rejected when the request fails or the task is cancelled. + * + * If `options.signal` is aborted, the promise is rejected with an `AbortError`. + * + * @returns A promise fulfilled with the downloaded file, or `null` when the task is paused. + */ downloadAsync(): Promise; + /** + * Requests pausing the active download operation. + * + * The pending `downloadAsync()` or `resumeAsync()` promise is fulfilled with `null` after native + * code produces resume data and the task enters the `paused` state. Use `pauseAsync()` if you + * need to wait until the task is ready to resume or save. + */ pause(): void; + /** + * Requests pausing the active download operation and waits until the task reaches the `paused` + * state. + * + * @returns A promise fulfilled after resume data is available. + */ pauseAsync(): Promise; + /** + * Resumes a paused download operation. + * + * The promise is fulfilled with the downloaded file when the transfer completes, or with `null` + * if the task is paused again before completion. It is rejected when the request fails or the task + * is cancelled. + * + * @returns A promise fulfilled with the downloaded file, or `null` when the task is paused. + */ resumeAsync(): Promise; + /** + * Adds a listener for download progress events. + * + * > **Note:** Prefer the `onProgress` option unless you need manual subscription control. + * + * @param eventName The event to listen to. Only `'progress'` is supported. + * @param listener Invoked with download progress updates. + * @returns A subscription handle. Call `remove()` to stop listening. + */ + addListener(eventName: 'progress', listener: (data: DownloadProgress) => void): EventSubscription; + /** + * Cancels the download operation. + * + * If `downloadAsync()` or `resumeAsync()` is pending, its promise is rejected after the native + * request is cancelled. Calling this method after the task reaches `completed`, `cancelled`, or + * `error` has no effect. + */ cancel(): void; + /** + * Returns the paused task state that can be persisted and restored later. + * + * This method can only be called while the task is `paused`. The returned state contains + * platform-specific resume data and request metadata, but does not include callbacks or abort + * signals. + * + * @returns A serializable paused download state. + */ savable(): DownloadPauseState; + /** + * Creates a paused download task from saved state. + * + * Use this to continue a download after persisting the value returned by `savable()`. New options + * can attach progress callbacks or an abort signal because functions and signals are not stored + * in `DownloadPauseState`. If both saved state and new options include headers, the new headers + * override saved headers with the same names. + * + * @param state The saved pause state. + * @param options Optional download task options to attach to the restored task. + * @returns A download task in the `paused` state. + */ static fromSavable(state: DownloadPauseState, options?: DownloadTaskOptions): DownloadTask; private _runDownloadOperation; private _emitFinalProgressEvent; diff --git a/packages/expo-file-system/build/FileSystem.d.ts.map b/packages/expo-file-system/build/FileSystem.d.ts.map index 2dd2ca6a59068d..5c5825d6e8a7e9 100644 --- a/packages/expo-file-system/build/FileSystem.d.ts.map +++ b/packages/expo-file-system/build/FileSystem.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"FileSystem.d.ts","sourceRoot":"","sources":["../src/FileSystem.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"FileSystem.d.ts","sourceRoot":"","sources":["../src/FileSystem.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/expo-file-system/build/index.d.ts b/packages/expo-file-system/build/index.d.ts index 561b9127607655..ff2bcab42bab52 100644 --- a/packages/expo-file-system/build/index.d.ts +++ b/packages/expo-file-system/build/index.d.ts @@ -1,4 +1,4 @@ export * from './FileSystem'; -export { DEFAULT_DEBOUNCE_MS, type FileCreateOptions, type DirectoryCreateOptions, type FileHandle, type FileInfo, type FileWriteOptions, type InfoOptions, type PathInfo, type DirectoryInfo, type DownloadOptions, type DownloadProgress, FileMode, EncodingType, UploadType, type PickFileOptions, type PickSingleFileOptions, type PickMultipleFilesOptions, type PickFileGeneralOptions, type PickSingleFileSuccessResult, type PickSingleFileResult, type PickMultipleFilesResult, type PickMultipleFilesSuccessResult, type PickFileCanceledResult, type UploadOptions, type UploadProgress, type UploadResult, type DownloadTaskOptions, type NetworkTaskSessionType, type DownloadPauseState, type UploadTaskState, type DownloadTaskState, type WatchEventType, type WatchEvent, type WatchOptions, type WatchSubscription, } from './ExpoFileSystem.types'; +export { DEFAULT_DEBOUNCE_MS, type FileCreateOptions, type DirectoryCreateOptions, type RelocationOptions, type FileHandle, type FileInfo, type FileWriteOptions, type InfoOptions, type PathInfo, type DirectoryInfo, type DownloadOptions, type DownloadProgress, FileMode, EncodingType, UploadType, type PickFileOptions, type PickSingleFileOptions, type PickMultipleFilesOptions, type PickFileGeneralOptions, type PickSingleFileSuccessResult, type PickSingleFileResult, type PickMultipleFilesResult, type PickMultipleFilesSuccessResult, type PickFileCanceledResult, type UploadOptions, type UploadProgress, type UploadResult, type DownloadTaskOptions, type NetworkTaskSessionType, type DownloadPauseState, type UploadTaskState, type DownloadTaskState, type WatchEventType, type WatchEvent, type WatchOptions, type WatchSubscription, } from './ExpoFileSystem.types'; export * from './legacyWarnings'; //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/packages/expo-file-system/build/index.d.ts.map b/packages/expo-file-system/build/index.d.ts.map index 999fcd2b109d5b..94bf5c9f6136eb 100644 --- a/packages/expo-file-system/build/index.d.ts.map +++ b/packages/expo-file-system/build/index.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAE7B,OAAO,EACL,mBAAmB,EACnB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,2BAA2B,EAChC,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,8BAA8B,EACnC,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,iBAAiB,GACvB,MAAM,wBAAwB,CAAC;AAEhC,cAAc,kBAAkB,CAAC"} \ No newline at end of file +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAE7B,OAAO,EACL,mBAAmB,EACnB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,2BAA2B,EAChC,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,8BAA8B,EACnC,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,iBAAiB,GACvB,MAAM,wBAAwB,CAAC;AAEhC,cAAc,kBAAkB,CAAC"} \ No newline at end of file diff --git a/packages/expo-file-system/src/ExpoFileSystem.ts b/packages/expo-file-system/src/ExpoFileSystem.ts index a04110352ac219..2c79b740394978 100644 --- a/packages/expo-file-system/src/ExpoFileSystem.ts +++ b/packages/expo-file-system/src/ExpoFileSystem.ts @@ -27,19 +27,37 @@ type DownloadTaskEvents = { }; declare class FileSystemUploadTask extends SharedObject { + /** + * @hidden + */ start(url: string, file: File, options: Record): Promise; + /** + * @hidden + */ cancel(): void; } declare class FileSystemDownloadTask extends SharedObject { + /** + * @hidden + */ start(url: string, to: File | Directory, options?: Record): Promise; + /** + * @hidden + */ pause(): any; + /** + * @hidden + */ resume( url: string, to: File | Directory, resumeData: string, options?: Record ): Promise; + /** + * @hidden + */ cancel(): void; } diff --git a/packages/expo-file-system/src/ExpoFileSystem.types.ts b/packages/expo-file-system/src/ExpoFileSystem.types.ts index b377c918a515e3..29a5022f91be72 100644 --- a/packages/expo-file-system/src/ExpoFileSystem.types.ts +++ b/packages/expo-file-system/src/ExpoFileSystem.types.ts @@ -11,6 +11,9 @@ export type FileCreateOptions = { overwrite?: boolean; }; +/** + * Options for moving or copying files and directories. + */ export type RelocationOptions = { /** * Whether to overwrite the destination if it exists. @@ -45,6 +48,7 @@ export type FileWriteOptions = { /** * The default debounce time for file system watcher events in milliseconds. + * @hidden */ export const DEFAULT_DEBOUNCE_MS = 100; @@ -89,7 +93,7 @@ export type WatchEvent = { export type WatchOptions = { /** * The debounce interval in milliseconds for coalescing rapid successive events into a single callback. - * @default DEFAULT_DEBOUNCE_MS + * @default 100 */ debounce?: number; /** @@ -362,7 +366,7 @@ export declare class File { /** * Retrieves text from the file. - * @returns A promise that resolves with the contents of the file as string. + * @returns A promise fulfilled with the contents of the file as string. */ text(): Promise; @@ -374,7 +378,7 @@ export declare class File { /** * Retrieves content of the file as base64. - * @returns A promise that resolves with the contents of the file as a base64 string. + * @returns A promise fulfilled with the contents of the file as a base64 string. */ base64(): Promise; @@ -386,7 +390,7 @@ export declare class File { /** * Retrieves byte content of the entire file. - * @returns A promise that resolves with the contents of the file as a `Uint8Array`. + * @returns A promise fulfilled with the contents of the file as a `Uint8Array`. */ bytes(): Promise>; @@ -479,7 +483,7 @@ export declare class File { * @param destination - The destination directory or file. If a directory is provided, the resulting filename will be determined based on the response headers. * @param options - Download options. When the destination already contains a file, the promise rejects with a `DestinationAlreadyExists` error unless `options.idempotent` is set to `true`. With `idempotent: true`, the download overwrites the existing file instead of failing. * - * @returns A promise that resolves to the downloaded file. When the server responds with + * @returns A promise fulfilled with the downloaded file. When the server responds with * a non-2xx HTTP status, the promise rejects with an `UnableToDownload` error whose * message includes the status code. No file is created in that scenario. * @@ -497,7 +501,7 @@ export declare class File { /** * Uploads this file to the network. * - * The promise resolves with the HTTP response metadata and body for any completed response, + * The promise is fulfilled with the HTTP response metadata and body for any completed response, * including non-2xx status codes. It rejects only for local file errors, transport failures, * or cancellation. * @@ -507,15 +511,33 @@ export declare class File { upload(url: string, options?: UploadOptions): Promise; /** - * An overload of the `pickFileAsync` method, which picks and returns a single `File`. - * This overload requires options to have `multipleFiles` flag be `undefined` or `false`. - * @param options options + * Opens the system file picker for selecting a single file. + * + * This overload requires `options.multipleFiles` to be `undefined` or `false`. + * + * @param options File picker options. */ static pickFileAsync(options?: PickSingleFileOptions): Promise; /** - * An overload of the `pickFileAsync` method, which picks and returns a list of `File`'s. - * This overload requires options to have `multipleFiles` flag be `true`. - * @param options options + * Opens the system file picker for selecting multiple files. + * + * This overload requires `options.multipleFiles` to be `true`. + * + * @param options File picker options. + * + * @example + * ```ts + * const result = await File.pickFileAsync({ + * multipleFiles: true, + * mimeTypes: ['image/*', 'application/pdf'], + * }); + * + * if (!result.canceled) { + * for (const file of result.result) { + * console.log(file.uri); + * } + * } + * ``` */ static pickFileAsync(options?: PickMultipleFilesOptions): Promise; /** @@ -723,6 +745,9 @@ export type DirectoryInfo = { files?: string[]; }; +/** + * Shared options accepted by file picker calls. + */ export type PickFileGeneralOptions = { /** * A URI pointing to an initial folder in which the file picker is opened. @@ -746,6 +771,10 @@ export type PickFileGeneralOptions = { * Options for picking a single file. */ export type PickSingleFileOptions = PickFileGeneralOptions & { + /** + * Keeps the picker in single-file mode. Omit this property or set it to `false` when selecting one file. + * @default false + */ multipleFiles?: false; }; @@ -753,6 +782,9 @@ export type PickSingleFileOptions = PickFileGeneralOptions & { * Options for picking multiple files. */ export type PickMultipleFilesOptions = PickFileGeneralOptions & { + /** + * Allows multiple files to be selected from the system UI. + */ multipleFiles: true; }; @@ -764,35 +796,65 @@ export type PickFileOptions = PickSingleFileOptions | PickMultipleFilesOptions; /** * Result type for picking a single file. + * + * Successful picks return `{ result: File, canceled: false }`. Canceled picks return + * `{ result: null, canceled: true }`. */ export type PickSingleFileResult = PickSingleFileSuccessResult | PickFileCanceledResult; /** * Result type for picking multiple files. + * + * Successful picks return `{ result: File[], canceled: false }`. Canceled picks return + * `{ result: null, canceled: true }`. */ export type PickMultipleFilesResult = PickMultipleFilesSuccessResult | PickFileCanceledResult; /** * Result type for successfully picking a single file. + * @inline + * @docsInline */ export type PickSingleFileSuccessResult = { + /** + * The selected file. + */ result: File; + /** + * Indicates that the picker completed with a selected file. + */ canceled: false; }; /** - * Result type for a successful picking multiple files. + * Result type for successfully picking multiple files. + * @inline + * @docsInline */ export type PickMultipleFilesSuccessResult = { + /** + * The selected files. + */ result: File[]; + /** + * Indicates that the picker completed with selected files. + */ canceled: false; }; /** * Result type for a canceled file pick. + * @inline + * @docsInline */ export type PickFileCanceledResult = { + /** + * Always `null` when the picker is canceled. + */ result: null; + /** + * Indicates that the user canceled the picker without selecting files. + */ canceled: true; }; @@ -981,10 +1043,14 @@ export type DownloadTaskState = TaskState; /** * Represents an upload task with progress tracking and cancellation support. + * + * Create instances with `new UploadTask(...)` or `file.createUploadTask(...)`, then call + * `uploadAsync()` to start the upload. */ export declare class UploadTask { /** - * The current state of the upload task. + * The current state of the upload task. Upload tasks move from `idle` to `active`, then to + * `completed`, `cancelled`, or `error`. */ readonly state: UploadTaskState; @@ -997,20 +1063,23 @@ export declare class UploadTask { constructor(file: File, url: string, options?: UploadOptions); /** - * Starts the upload operation. - * @returns A promise that resolves with the upload result. - * If the task is cancelled via `cancel()` or `signal`, the promise rejects. + * Starts the upload operation. This method can only be called once, while the task is `idle`. + * + * @returns A promise fulfilled with the upload result. The promise is rejected when the upload + * cannot read the file, the request fails, or the task is cancelled. */ uploadAsync(): Promise; /** - * Cancels the upload operation. - * Any pending `uploadAsync()` promise rejects after cancellation. + * Cancels the upload operation. If `uploadAsync()` is pending, its promise is rejected after the + * native request is cancelled. */ cancel(): void; /** * Adds a listener for upload progress events. + * + * > **Note:** Prefer the `onProgress` option unless you need manual subscription control. */ addListener( eventName: 'progress', @@ -1020,10 +1089,14 @@ export declare class UploadTask { /** * Represents a download task with pause/resume support and progress tracking. + * + * Create instances with `new DownloadTask(...)` or `File.createDownloadTask(...)`, then call + * `downloadAsync()` to start the download. */ export declare class DownloadTask { /** - * The current state of the download task. + * The current state of the download task. Download tasks move from `idle` to `active`, then to + * `paused`, `completed`, `cancelled`, or `error`. */ readonly state: DownloadTaskState; @@ -1036,46 +1109,60 @@ export declare class DownloadTask { constructor(url: string, destination: File | Directory, options?: DownloadTaskOptions); /** - * Starts the download operation. - * @returns A promise that resolves with the downloaded file, or null if paused. - * If the task is cancelled via `cancel()` or `signal`, the promise rejects. + * Starts the download operation. This method can only be called once, while the task is `idle`. + * + * @returns A promise fulfilled with the downloaded file, or `null` if the task is paused before + * completion. The promise is rejected when the request fails or the task is cancelled. */ downloadAsync(): Promise; /** - * Pauses the download operation. The pending downloadAsync() promise resolves with null. + * Requests pausing the active download operation. The pending `downloadAsync()` or `resumeAsync()` + * promise is fulfilled with `null` after native code produces resume data and the task enters the + * `paused` state. */ pause(): void; + /** + * Requests pausing the active download operation and waits until the task reaches the `paused` + * state. + */ + pauseAsync(): Promise; + /** * Resumes a paused download operation. - * @returns A promise that resolves with the downloaded file, or null if paused again. - * If the task is cancelled via `cancel()` or `signal`, the promise rejects. + * + * @returns A promise fulfilled with the downloaded file, or `null` if the task is paused again. + * The promise is rejected when the request fails or the task is cancelled. */ resumeAsync(): Promise; /** - * Cancels the download operation. - * Any pending `downloadAsync()` or `resumeAsync()` promise rejects after cancellation. + * Cancels the download operation. If `downloadAsync()` or `resumeAsync()` is pending, its promise + * is rejected after the native request is cancelled. */ cancel(): void; /** - * Returns the current state that can be persisted and restored later. + * Returns the paused task state that can be persisted and restored later. + * * @returns The pause state. */ savable(): DownloadPauseState; /** * Creates a download task from a saved state. + * * @param state The saved pause state. - * @param options Optional new options to attach (e.g. onProgress, signal) since those are not persisted. + * @param options Optional new options to attach, such as `onProgress` or `signal`, since those are not persisted. * @returns A new download task. */ static fromSavable(state: DownloadPauseState, options?: DownloadTaskOptions): DownloadTask; /** * Adds a listener for download progress events. + * + * > **Note:** Prefer the `onProgress` option unless you need manual subscription control. */ addListener( eventName: 'progress', diff --git a/packages/expo-file-system/src/FileSystem.ts b/packages/expo-file-system/src/FileSystem.ts index 2deec813098c23..28dadc2747031c 100644 --- a/packages/expo-file-system/src/FileSystem.ts +++ b/packages/expo-file-system/src/FileSystem.ts @@ -9,6 +9,7 @@ import { type PickSingleFileResult, FileMode, type UploadOptions, + type UploadProgress, type UploadResult, type DownloadProgress, type DownloadTaskOptions, @@ -155,14 +156,72 @@ export class File extends ExpoFileSystem.FileSystemFile implements Blob { return new Blob([this.bytesSync().slice(start, end)], { type: contentType }); } + /** + * Uploads this file to a server and starts the request immediately. + * + * The promise is fulfilled with response metadata and body for completed HTTP responses, + * including non-2xx status codes. It is rejected only when the file cannot be read, the + * request fails, or the upload is cancelled. + * + * @param url The URL to upload the file to. + * @param options Upload options. + * @returns A promise fulfilled with the upload response. + */ upload(url: string, options?: UploadOptions): Promise { return new UploadTask(this, url, options).uploadAsync(); } + /** + * Creates an upload task for this file without starting it. + * + * Call `uploadAsync()` on the returned task to start the upload. Use this when you need to + * inspect task state, cancel the upload, or subscribe to progress manually. + * + * @param url The URL to upload the file to. + * @param options Upload options. + * @returns An upload task that can be started with `uploadAsync()`. + * + * @example + * ```ts + * const file = new File(Paths.document, 'photo.jpg'); + * const task = file.createUploadTask('https://example.com/upload', { + * uploadType: UploadType.MULTIPART, + * onProgress: ({ bytesSent, totalBytes }) => { + * console.log(`${bytesSent} / ${totalBytes}`); + * }, + * }); + * + * const result = await task.uploadAsync(); + * ``` + */ createUploadTask(url: string, options?: UploadOptions): UploadTask { return new UploadTask(this, url, options); } + /** + * Creates a download task without starting it. + * + * Call `downloadAsync()` on the returned task to start the download. Use this when you need + * pause/resume support, task state, cancellation, or manual progress subscriptions. + * + * @param url The URL of the file to download. + * @param destination The destination file or directory. If a directory is provided, the + * resulting filename is determined from the response headers or URL. + * @param options Download task options. + * @returns A download task that can be started with `downloadAsync()`. + * + * @example + * ```ts + * const destination = new File(Paths.document, 'video.mp4'); + * const task = File.createDownloadTask('https://example.com/video.mp4', destination, { + * onProgress: ({ bytesWritten, totalBytes }) => { + * console.log(`${bytesWritten} / ${totalBytes}`); + * }, + * }); + * + * const file = await task.downloadAsync(); + * ``` + */ static createDownloadTask( url: string, destination: File | Directory, @@ -479,6 +538,9 @@ function cleanupNetworkTask( } /** * Represents an upload task with progress tracking and cancellation support. + * + * Upload tasks start in the `idle` state. Calling `uploadAsync()` moves the task to `active`, + * then to `completed`, `cancelled`, or `error`. */ export class UploadTask extends ExpoFileSystem.FileSystemUploadTask { private _state: UploadTaskState = 'idle'; @@ -488,6 +550,15 @@ export class UploadTask extends ExpoFileSystem.FileSystemUploadTask { private _subscription?: EventSubscription; private _abortHandler?: () => void; + /** + * Creates an upload task. + * + * The task does not start automatically. Call `uploadAsync()` to begin uploading. + * + * @param file The file to upload. + * @param url The URL to upload the file to. + * @param options Upload options. + */ constructor(file: File, url: string, options?: UploadOptions) { super(); this._file = file; @@ -495,10 +566,24 @@ export class UploadTask extends ExpoFileSystem.FileSystemUploadTask { this._options = options; } + /** + * The current state of the upload task. + */ get state(): UploadTaskState { return this._state; } + /** + * Starts the upload operation. + * + * This method can only be called once, while the task is `idle`. The promise is fulfilled + * with response metadata and body for completed HTTP responses, including non-2xx status codes. + * It is rejected when the file cannot be read, the request fails, or the task is cancelled. + * + * If `options.signal` is aborted, the promise is rejected with an `AbortError`. + * + * @returns A promise fulfilled with the upload response. + */ async uploadAsync(): Promise { assertNetworkTaskState(this._state, ['idle'], 'uploadAsync'); this._state = 'active'; @@ -549,6 +634,25 @@ export class UploadTask extends ExpoFileSystem.FileSystemUploadTask { } } + /** + * Adds a listener for upload progress events. + * + * > **Note:** Prefer the `onProgress` option unless you need manual subscription control. + * + * @param eventName The event to listen to. Only `'progress'` is supported. + * @param listener Invoked with upload progress updates. + * @returns A subscription handle. Call `remove()` to stop listening. + */ + addListener(eventName: 'progress', listener: (data: UploadProgress) => void): EventSubscription { + return super.addListener(eventName, listener); + } + + /** + * Cancels the upload operation. + * + * If `uploadAsync()` is pending, its promise is rejected after the native request is cancelled. + * Calling this method after the task reaches `completed`, `cancelled`, or `error` has no effect. + */ cancel(): void { if (['completed', 'cancelled', 'error'].includes(this._state)) return; this._state = 'cancelled'; @@ -561,6 +665,10 @@ export class UploadTask extends ExpoFileSystem.FileSystemUploadTask { /** * Represents a download task with pause/resume support and progress tracking. + * + * Download tasks start in the `idle` state. Calling `downloadAsync()` moves the task to `active`; + * pausing moves it to `paused`, and a completed, cancelled, or failed transfer moves it to the + * corresponding terminal state. */ export class DownloadTask extends ExpoFileSystem.FileSystemDownloadTask { private _state: DownloadTaskState = 'idle'; @@ -573,6 +681,16 @@ export class DownloadTask extends ExpoFileSystem.FileSystemDownloadTask { private _inFlightOperation?: Promise; private _pauseRequest?: Promise; + /** + * Creates a download task. + * + * The task does not start automatically. Call `downloadAsync()` to begin downloading. + * + * @param url The URL of the file to download. + * @param destination The destination file or directory. If a directory is provided, the resulting + * filename is determined from the response headers or URL. + * @param options Download task options. + */ constructor(url: string, destination: File | Directory, options?: DownloadTaskOptions) { super(); this._url = url; @@ -580,10 +698,24 @@ export class DownloadTask extends ExpoFileSystem.FileSystemDownloadTask { this._options = options; } + /** + * The current state of the download task. + */ get state(): DownloadTaskState { return this._state; } + /** + * Starts the download operation. + * + * This method can only be called once, while the task is `idle`. The promise is fulfilled with + * the downloaded file when the transfer completes, or with `null` if the task is paused before + * completion. It is rejected when the request fails or the task is cancelled. + * + * If `options.signal` is aborted, the promise is rejected with an `AbortError`. + * + * @returns A promise fulfilled with the downloaded file, or `null` when the task is paused. + */ async downloadAsync(): Promise { assertNetworkTaskState(this._state, ['idle'], 'downloadAsync'); this._state = 'active'; @@ -598,6 +730,13 @@ export class DownloadTask extends ExpoFileSystem.FileSystemDownloadTask { return operation; } + /** + * Requests pausing the active download operation. + * + * The pending `downloadAsync()` or `resumeAsync()` promise is fulfilled with `null` after native + * code produces resume data and the task enters the `paused` state. Use `pauseAsync()` if you + * need to wait until the task is ready to resume or save. + */ pause(): void { assertNetworkTaskState(this._state, ['active'], 'pause'); this._pauseRequest = Promise.resolve(super.pause()).then((result) => { @@ -607,11 +746,27 @@ export class DownloadTask extends ExpoFileSystem.FileSystemDownloadTask { // when the native promise resolves with null } + /** + * Requests pausing the active download operation and waits until the task reaches the `paused` + * state. + * + * @returns A promise fulfilled after resume data is available. + */ async pauseAsync(): Promise { this.pause(); await this._pauseRequest; await this._inFlightOperation; } + + /** + * Resumes a paused download operation. + * + * The promise is fulfilled with the downloaded file when the transfer completes, or with `null` + * if the task is paused again before completion. It is rejected when the request fails or the task + * is cancelled. + * + * @returns A promise fulfilled with the downloaded file, or `null` when the task is paused. + */ async resumeAsync(): Promise { assertNetworkTaskState(this._state, ['paused'], 'resumeAsync'); if (!this._resumeData) { @@ -631,6 +786,29 @@ export class DownloadTask extends ExpoFileSystem.FileSystemDownloadTask { return operation; } + /** + * Adds a listener for download progress events. + * + * > **Note:** Prefer the `onProgress` option unless you need manual subscription control. + * + * @param eventName The event to listen to. Only `'progress'` is supported. + * @param listener Invoked with download progress updates. + * @returns A subscription handle. Call `remove()` to stop listening. + */ + addListener( + eventName: 'progress', + listener: (data: DownloadProgress) => void + ): EventSubscription { + return super.addListener(eventName, listener); + } + + /** + * Cancels the download operation. + * + * If `downloadAsync()` or `resumeAsync()` is pending, its promise is rejected after the native + * request is cancelled. Calling this method after the task reaches `completed`, `cancelled`, or + * `error` has no effect. + */ cancel(): void { if (['completed', 'cancelled', 'error'].includes(this._state)) return; this._state = 'cancelled'; @@ -641,6 +819,15 @@ export class DownloadTask extends ExpoFileSystem.FileSystemDownloadTask { this._abortHandler = undefined; } + /** + * Returns the paused task state that can be persisted and restored later. + * + * This method can only be called while the task is `paused`. The returned state contains + * platform-specific resume data and request metadata, but does not include callbacks or abort + * signals. + * + * @returns A serializable paused download state. + */ savable(): DownloadPauseState { assertNetworkTaskState(this._state, ['paused'], 'savable'); return { @@ -652,6 +839,18 @@ export class DownloadTask extends ExpoFileSystem.FileSystemDownloadTask { }; } + /** + * Creates a paused download task from saved state. + * + * Use this to continue a download after persisting the value returned by `savable()`. New options + * can attach progress callbacks or an abort signal because functions and signals are not stored + * in `DownloadPauseState`. If both saved state and new options include headers, the new headers + * override saved headers with the same names. + * + * @param state The saved pause state. + * @param options Optional download task options to attach to the restored task. + * @returns A download task in the `paused` state. + */ static fromSavable(state: DownloadPauseState, options?: DownloadTaskOptions): DownloadTask { if (!state.resumeData) { throw new Error('Cannot restore task: DownloadPauseState has no resumeData'); diff --git a/packages/expo-file-system/src/index.ts b/packages/expo-file-system/src/index.ts index 0ed923dd8fb10b..234135cfcb2abf 100644 --- a/packages/expo-file-system/src/index.ts +++ b/packages/expo-file-system/src/index.ts @@ -4,6 +4,7 @@ export { DEFAULT_DEBOUNCE_MS, type FileCreateOptions, type DirectoryCreateOptions, + type RelocationOptions, type FileHandle, type FileInfo, type FileWriteOptions, diff --git a/packages/expo-modules-autolinking/CHANGELOG.md b/packages/expo-modules-autolinking/CHANGELOG.md index 519b967dc10efe..d561259b8e2a94 100644 --- a/packages/expo-modules-autolinking/CHANGELOG.md +++ b/packages/expo-modules-autolinking/CHANGELOG.md @@ -8,6 +8,8 @@ ### 🐛 Bug fixes +- [iOS] Re-stamp `ExpoModulesJSI.xcframework` stub slices on every `pod install` so cached pods can't ship with missing slices. ([#45542](https://github.com/expo/expo/pull/45542) by [@tsapeta](https://github.com/tsapeta)) + ### 💡 Others ## 56.0.2 — 2026-05-06 diff --git a/packages/expo-modules-autolinking/scripts/ios/cocoapods/installer.rb b/packages/expo-modules-autolinking/scripts/ios/cocoapods/installer.rb index 19b96edd011fc0..689979c329eabc 100644 --- a/packages/expo-modules-autolinking/scripts/ios/cocoapods/installer.rb +++ b/packages/expo-modules-autolinking/scripts/ios/cocoapods/installer.rb @@ -84,10 +84,19 @@ def t.build_type private - # Creates the stub xcframework for ExpoModulesJSI if it doesn't exist. - # CocoaPods only runs prepare_command when a pod is freshly downloaded or - # its podspec changes, so CI cache hits skip it. This method runs on every - # pod install to guarantee the stub is always present. + # Ensures every slice declared by ExpoModulesJSI's podspec exists in + # `Products/ExpoModulesJSI.xcframework`. CocoaPods only runs + # prepare_command when a pod is freshly downloaded or its podspec + # changes, so CI cache hits skip it. This method runs on every pod + # install to guarantee every declared slice is present — an xcframework + # with only some slices (e.g. simulator-only after a prior Debug build) + # breaks the per-slice copy script CocoaPods generates from Info.plist, + # which then leaves XCFrameworkIntermediates empty for the missing slice + # and surfaces as `No such module 'ExpoModulesJSI'`. + # + # The script itself is idempotent and only stamps slices that are + # missing, so always invoking it is cheaper than maintaining a separate + # completeness check that would have to mirror the script's slice list. def ensure_expo_modules_jsi_stub_xcframework jsi_target = self.pod_targets.find { |t| t.name == 'ExpoModulesJSI' } return if jsi_target.nil? @@ -95,9 +104,6 @@ def ensure_expo_modules_jsi_stub_xcframework pod_dir = jsi_target.sandbox.pod_dir('ExpoModulesJSI') return unless File.directory?(pod_dir) - xcframework_path = File.join(pod_dir, 'Products', 'ExpoModulesJSI.xcframework') - return if File.directory?(xcframework_path) - system('./scripts/create-stub-xcframework.sh', chdir: pod_dir.to_s) end diff --git a/packages/expo-modules-core/CHANGELOG.md b/packages/expo-modules-core/CHANGELOG.md index aa9577a4d699dc..dfe557268056a2 100644 --- a/packages/expo-modules-core/CHANGELOG.md +++ b/packages/expo-modules-core/CHANGELOG.md @@ -8,6 +8,8 @@ ### 🐛 Bug fixes +- [Android] Fix unsetting border width on views with border radius causing views to disappear ([#45467](https://github.com/expo/expo/pull/45467) by [@fractalbeauty](https://github.com/fractalbeauty)) + ### 💡 Others ## 56.0.4 — 2026-05-07 diff --git a/packages/expo-modules-core/android/src/main/java/expo/modules/kotlin/views/decorators/CSSProps.kt b/packages/expo-modules-core/android/src/main/java/expo/modules/kotlin/views/decorators/CSSProps.kt index 5aea5b31e449d6..0bcd136e826adc 100644 --- a/packages/expo-modules-core/android/src/main/java/expo/modules/kotlin/views/decorators/CSSProps.kt +++ b/packages/expo-modules-core/android/src/main/java/expo/modules/kotlin/views/decorators/CSSProps.kt @@ -64,7 +64,7 @@ private fun ViewDefinitionBuilder.UseBorderWidthProps() { BackgroundStyleApplicator.setBorderWidth( view, edge, - width ?: Float.NaN + width ) } } diff --git a/packages/expo-modules-jsi/CHANGELOG.md b/packages/expo-modules-jsi/CHANGELOG.md index d257b229d0638a..2c71baea289dd7 100644 --- a/packages/expo-modules-jsi/CHANGELOG.md +++ b/packages/expo-modules-jsi/CHANGELOG.md @@ -9,6 +9,7 @@ ### 🐛 Bug fixes - [iOS] Fixed `ExpoModulesJSI.xcframework` build failing under `useFrameworks: "static"` + `buildReactNativeFromSource: true` due to missing header search paths. ([#45508](https://github.com/expo/expo/pull/45508) by [@chrfalch](https://github.com/chrfalch)) +- [iOS] Fixed missing slices in `ExpoModulesJSI.xcframework` causing `No such module 'ExpoModulesJSI'` build errors. ([#45542](https://github.com/expo/expo/pull/45542) by [@tsapeta](https://github.com/tsapeta)) ### 💡 Others diff --git a/packages/expo-modules-jsi/apple/scripts/build-xcframework.sh b/packages/expo-modules-jsi/apple/scripts/build-xcframework.sh index f4808e0de2ca94..ac53129cd8d0d7 100755 --- a/packages/expo-modules-jsi/apple/scripts/build-xcframework.sh +++ b/packages/expo-modules-jsi/apple/scripts/build-xcframework.sh @@ -6,8 +6,10 @@ # but can also be invoked manually with PODS_ROOT set. # # Features: -# - Hash-based caching: skips rebuild if source files haven't changed -# - Additive slices: builds only the requested platform, preserves others +# - Per-slice hash-based caching: a slice is rebuilt only when its own +# recorded source hash differs from the current one. Other slices — +# including those built for other platforms in earlier runs — are left +# untouched. # - Reads React/JSI/Hermes headers directly from Pods/Headers/Public, so the # same configuration works for both prebuilt and source-built React Native # - Cleans .swiftinterface files for cross-compiler compatibility @@ -20,13 +22,11 @@ # PLATFORM_NAME (optional) Build for a specific platform (e.g. iphoneos, iphonesimulator). # When unset, builds for both iphoneos and iphonesimulator. -set -eo pipefail +set -euo pipefail PACKAGE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" PACKAGE_NAME="ExpoModulesJSI" XCFRAMEWORK_PATH="${PACKAGE_DIR}/Products/${PACKAGE_NAME}.xcframework" -SLICES_DIR="${PACKAGE_DIR}/.xcframework-slices" -HASH_FILE="${SLICES_DIR}/.build-hash" CONFIGURATION="Release" DERIVED_DATA_PATH="${PACKAGE_DIR}/.DerivedData" @@ -34,6 +34,8 @@ SPM_BUILD_PATH="${PACKAGE_DIR}/.build" SPM_WORKSPACE_PATH="${PACKAGE_DIR}/.swiftpm" BUILD_PRODUCTS_PATH="${DERIVED_DATA_PATH}/Build/Products" +source "${PACKAGE_DIR}/scripts/xcframework-helpers.sh" + CLEAN=false while [[ $# -gt 0 ]]; do @@ -49,7 +51,6 @@ while [[ $# -gt 0 ]]; do esac done -# Use colors only when stdout is a terminal. if [[ -t 1 ]]; then BLUE="\033[34m" RESET="\033[0m" @@ -71,9 +72,10 @@ SOURCE_DIRS=( SOURCE_FILES=( "${PACKAGE_DIR}/Package.swift" "${PACKAGE_DIR}/scripts/build-xcframework.sh" + "${PACKAGE_DIR}/scripts/create-stub-xcframework.sh" + "${PACKAGE_DIR}/scripts/xcframework-helpers.sh" ) -# Computes a SHA256 hash of all source files. compute_hash() { local all_files all_files=$( @@ -111,11 +113,30 @@ platform_destination() { esac } -# Builds a single framework slice for a given platform and stages it. +# Resolves the xcframework slice ID that a built platform should land in. +# Mirrors the slice IDs xcodebuild -create-xcframework would have assigned for +# a single-arch device build / dual-arch simulator build. +platform_slice_id() { + case "$1" in + iphoneos) echo "ios-arm64" ;; + iphonesimulator) echo "ios-arm64_x86_64-simulator" ;; + appletvos) echo "tvos-arm64" ;; + appletvsimulator) echo "tvos-arm64_x86_64-simulator" ;; + *) + log "error: No slice mapping for platform: $1" + exit 1 + ;; + esac +} + +# Builds a single framework slice for the given platform and replaces the +# matching slice inside XCFRAMEWORK_PATH. Other slices on disk are untouched. build_slice() { local platform="$1" local destination destination=$(platform_destination "$platform") + local slice_id + slice_id=$(platform_slice_id "$platform") local build_dir_name="${CONFIGURATION}-${platform}" log "Building framework slice for ${platform}..." @@ -148,22 +169,29 @@ build_slice() { ) local product_path="${BUILD_PRODUCTS_PATH}/${build_dir_name}" - local framework_path="${product_path}/PackageFrameworks/${PACKAGE_NAME}.framework" + local framework_src="${product_path}/PackageFrameworks/${PACKAGE_NAME}.framework" local swiftmodule_src="${product_path}/${PACKAGE_NAME}.swiftmodule" local generated_maps="${DERIVED_DATA_PATH}/Build/Intermediates.noindex/GeneratedModuleMaps-${platform}" - # Stage the built slice for this platform. - local slice_staging="${SLICES_DIR}/${platform}" - rm -rf "$slice_staging" - mkdir -p "$slice_staging" + if [[ ! -d "$framework_src" ]]; then + log "error: xcodebuild did not produce ${framework_src}" + exit 1 + fi + + # Replace the slice in place. Stage to a temp location first so a partial + # write can't leave the xcframework in a broken state. + local slice_dir="${XCFRAMEWORK_PATH}/${slice_id}" + local staging_dir="${XCFRAMEWORK_PATH}/.${slice_id}.new" + rm -rf "$staging_dir" + mkdir -p "$staging_dir" - cp -r "$framework_path" "$slice_staging/" + cp -r "$framework_src" "$staging_dir/" if [[ -d "${product_path}/${PACKAGE_NAME}.framework.dSYM" ]]; then - cp -r "${product_path}/${PACKAGE_NAME}.framework.dSYM" "$slice_staging/" + cp -r "${product_path}/${PACKAGE_NAME}.framework.dSYM" "$staging_dir/" fi # Copy Swift module interfaces and generated headers into the staged framework. - local modules_dir="${slice_staging}/${PACKAGE_NAME}.framework/Modules" + local modules_dir="${staging_dir}/${PACKAGE_NAME}.framework/Modules" mkdir -p "$modules_dir" cp -r "$swiftmodule_src/" "${modules_dir}/${PACKAGE_NAME}.swiftmodule" rm -rf "${modules_dir}/${PACKAGE_NAME}.swiftmodule/Project" @@ -185,33 +213,15 @@ build_slice() { find "${modules_dir}/${PACKAGE_NAME}.swiftmodule" -name '*.swiftinterface' \ -exec sed -i '' '/^extension __ObjC\./,/^}/d;/^@usableFromInline$/{N;/_ConstraintThatIsNotPartOfTheAPIOfThisLibrary/d;};/_ConstraintThatIsNotPartOfTheAPIOfThisLibrary/d' {} + - local headers_dir="${slice_staging}/${PACKAGE_NAME}.framework/Headers" + local headers_dir="${staging_dir}/${PACKAGE_NAME}.framework/Headers" mkdir -p "$headers_dir" cp "${generated_maps}/${PACKAGE_NAME}-Swift.h" "$headers_dir/" cp "${generated_maps}/${PACKAGE_NAME}.modulemap" "$headers_dir/module.modulemap" -} -# Assembles the xcframework from all staged slices. -assemble_xcframework() { - rm -rf "$XCFRAMEWORK_PATH" - - local xcframework_args=() - for slice_dir in "${SLICES_DIR}"/*/; do - local framework="${slice_dir}${PACKAGE_NAME}.framework" - local dsym="${slice_dir}${PACKAGE_NAME}.framework.dSYM" - if [[ -d "$framework" ]]; then - xcframework_args+=(-framework "$framework") - if [[ -d "$dsym" ]]; then - xcframework_args+=(-debug-symbols "$(cd "$dsym" && pwd)") - fi - fi - done - - xcodebuild -create-xcframework "${xcframework_args[@]}" -output "$XCFRAMEWORK_PATH" - - # Write the hash so subsequent builds can skip if nothing changed. - mkdir -p "$SLICES_DIR" - echo "$current_hash" > "$HASH_FILE" + echo "$current_hash" > "${staging_dir}/.build-hash" + + rm -rf "$slice_dir" + mv "$staging_dir" "$slice_dir" } # --- Main --- @@ -240,7 +250,6 @@ PODS_ROOT="$(cd "$PODS_ROOT" && pwd)" RN_ROOT="$(node -p 'require("path").dirname(require.resolve("react-native/package.json"))' 2>/dev/null \ || echo "${PODS_ROOT}/../../node_modules/react-native")" -# log detected configuration to verify the fallback path triggers. mode="$( [[ -d "${PODS_ROOT}/React-Core-prebuilt/React.xcframework" ]] && echo "prebuilt RN" || echo "source-built RN")" [[ -f "${PODS_ROOT}/Target Support Files/React-jsi/React-jsi-umbrella.h" ]] && mode="${mode}, static frameworks" log "Detected: ${mode} (RN_ROOT=${RN_ROOT})" @@ -258,12 +267,16 @@ GENERATED_MODULE_MAP="${PACKAGE_DIR}/.generated/module.modulemap" SOURCE_FILES+=("$GENERATED_MODULE_MAP") if [[ "$CLEAN" == true ]]; then - rm -rf "$XCFRAMEWORK_PATH" "$SLICES_DIR" "$DERIVED_DATA_PATH" "$SPM_BUILD_PATH" "$SPM_WORKSPACE_PATH" - log "Cleaned existing xcframework, staged slices, DerivedData, and SwiftPM state" + rm -rf "$XCFRAMEWORK_PATH" "$DERIVED_DATA_PATH" "$SPM_BUILD_PATH" "$SPM_WORKSPACE_PATH" + log "Cleaned existing xcframework, DerivedData, and SwiftPM state" + # Re-stamp stub slices so the post-clean state matches a fresh `pod install`: + # CocoaPods reads Info.plist before this script runs, and would fail to + # resolve any slice not declared there. + "${PACKAGE_DIR}/scripts/create-stub-xcframework.sh" fi # Determine which platforms to build. -if [[ -n "$PLATFORM_NAME" ]]; then +if [[ -n "${PLATFORM_NAME:-}" ]]; then PLATFORMS=("$PLATFORM_NAME") else PLATFORMS=("iphoneos" "iphonesimulator") @@ -271,42 +284,31 @@ fi current_hash=$(compute_hash) -# Check if sources have changed since the last build. -if [[ -f "$HASH_FILE" ]]; then - previous_hash=$(cat "$HASH_FILE") - if [[ "$current_hash" == "$previous_hash" ]]; then - # Sources haven't changed — filter out platforms that already have a staged slice. - platforms_to_build=() - for platform in "${PLATFORMS[@]}"; do - if [[ ! -d "${SLICES_DIR}/${platform}/${PACKAGE_NAME}.framework" ]]; then - platforms_to_build+=("$platform") - fi - done - - if [[ ${#platforms_to_build[@]} -eq 0 ]]; then - log "xcframework is up to date, skipping build" - exit 0 - fi - - PLATFORMS=("${platforms_to_build[@]}") - else - # Sources changed — remove all staged slices so they get rebuilt. - # Also wipe DerivedData and .build because Swift Package Manager caches - # the resolved package graph there and Package.swift reads PODS_ROOT at - # resolve time; without this, switching PODS_ROOT (e.g. between apps) - # leaks paths from the previous resolution into the new build. - log "Source files changed, rebuilding all slices" - rm -rf "$SLICES_DIR" "$XCFRAMEWORK_PATH" "$DERIVED_DATA_PATH" "$SPM_BUILD_PATH" "$SPM_WORKSPACE_PATH" +# Filter out platforms whose slice is already up to date. +platforms_to_build=() +for platform in "${PLATFORMS[@]}"; do + slice_id=$(platform_slice_id "$platform") + slice_hash_file="${XCFRAMEWORK_PATH}/${slice_id}/.build-hash" + if [[ -f "$slice_hash_file" ]] && [[ "$(cat "$slice_hash_file")" == "$current_hash" ]]; then + continue fi + platforms_to_build+=("$platform") +done + +if [[ ${#platforms_to_build[@]} -eq 0 ]]; then + log "xcframework slices up to date, skipping build" + exit 0 fi +PLATFORMS=("${platforms_to_build[@]}") + SECONDS=0 for platform in "${PLATFORMS[@]}"; do build_slice "$platform" done -assemble_xcframework +write_xcframework_plist "$XCFRAMEWORK_PATH" "$PACKAGE_NAME" -SLICE_NAMES=$(for d in "${XCFRAMEWORK_PATH}"/*/; do basename "$d"; done | paste -sd', ' - | sed 's/,/, /g') +SLICE_NAMES=$(for d in "${XCFRAMEWORK_PATH}"/*/; do basename "$d"; done | LC_ALL=C sort | tr '\n' ',' | sed 's/,$//;s/,/, /g') log "Built xcframework successfully in ${SECONDS}s (${SLICE_NAMES})" diff --git a/packages/expo-modules-jsi/apple/scripts/create-stub-xcframework.sh b/packages/expo-modules-jsi/apple/scripts/create-stub-xcframework.sh index 758add9e52883e..7b31b5daec727d 100755 --- a/packages/expo-modules-jsi/apple/scripts/create-stub-xcframework.sh +++ b/packages/expo-modules-jsi/apple/scripts/create-stub-xcframework.sh @@ -1,102 +1,57 @@ #!/bin/bash -# Creates a stub xcframework with a minimal dynamic library so that -# CocoaPods detects it as a dynamic framework and generates the -# "[CP] Copy XCFrameworks" and "[CP] Embed Pods Frameworks" build phases. -# The real xcframework is built by the build-xcframework.sh script at build time. +# Ensures every required slice in ExpoModulesJSI.xcframework exists with at +# least a stub binary so CocoaPods detects the package as a dynamic framework +# and generates the "[CP] Copy XCFrameworks" and "[CP] Embed Pods Frameworks" +# build phases for every supported platform. The real xcframework is built by +# build-xcframework.sh at build time. +# +# Non-destructive: existing slice binaries (real or stub) are kept; only +# missing required slices are stamped. Info.plist is rewritten from whatever +# slices are on disk so additional slices built via Xcode survive. -set -eo pipefail +set -euo pipefail PACKAGE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" PACKAGE_NAME="ExpoModulesJSI" XCFRAMEWORK_PATH="${PACKAGE_DIR}/Products/${PACKAGE_NAME}.xcframework" -# Use colors only when run in the terminal +source "$(dirname "${BASH_SOURCE[0]}")/xcframework-helpers.sh" + BLUE=""; RESET="" if [ -t 1 ]; then BLUE="\033[34m" RESET="\033[0m" fi -echo -e "${BLUE}[Expo]${RESET} Creating stub xcframework for ${PACKAGE_NAME}" - -# Platform slices the podspec supports. CocoaPods reads Info.plist at -# `pod install` time to generate per-slice cases in its xcframework copy -# script, so every SDK we want to build for must appear here. -# -# Format: slice_id|platform|variant|archs -SLICES=( - "ios-arm64|ios||arm64" - "ios-arm64_x86_64-simulator|ios|simulator|arm64 x86_64" - "tvos-arm64|tvos||arm64" - "tvos-arm64_x86_64-simulator|tvos|simulator|arm64 x86_64" -) - -# Always regenerate the Info.plist so it declares every slice. A previous -# build may have produced an xcframework with only the target platform's -# slice (e.g. device-only or simulator-only), which would cause CocoaPods -# to generate a copy script that is missing the other variant. +echo -e "${BLUE}[Expo]${RESET} Ensuring required slices in ${PACKAGE_NAME}.xcframework" # The stub binary is only inspected by CocoaPods at install time to detect # that this is a dynamic framework — it is never linked against (the real # xcframework replaces it before the sources compile). Compile it once and -# reuse the same binary for every slice. -STUB_SOURCE="${XCFRAMEWORK_PATH}/.stub-binary" +# reuse the same binary for every slice that needs stamping. mkdir -p "$XCFRAMEWORK_PATH" +STUB_SOURCE="${XCFRAMEWORK_PATH}/.stub-binary" echo "" | clang -x c - -dynamiclib \ -o "$STUB_SOURCE" \ -install_name "@rpath/${PACKAGE_NAME}.framework/${PACKAGE_NAME}" -available_libraries="" -for slice in "${SLICES[@]}"; do - IFS='|' read -r slice_id platform variant archs <<<"$slice" - slice_dir="${XCFRAMEWORK_PATH}/${slice_id}/${PACKAGE_NAME}.framework" - mkdir -p "$slice_dir" - if [[ ! -f "${slice_dir}/${PACKAGE_NAME}" ]]; then - cp "$STUB_SOURCE" "${slice_dir}/${PACKAGE_NAME}" - fi - - arch_entries="" - for arch in $archs; do - arch_entries+=" ${arch} -" - done +for slice_id in "${EXPO_MODULES_JSI_REQUIRED_SLICE_IDS[@]}"; do + slice_dir="${XCFRAMEWORK_PATH}/${slice_id}" + framework_dir="${slice_dir}/${PACKAGE_NAME}.framework" + binary_path="${framework_dir}/${PACKAGE_NAME}" + hash_file="${slice_dir}/.build-hash" - variant_entry="" - if [[ -n "$variant" ]]; then - variant_entry=" SupportedPlatformVariant - ${variant} -" + mkdir -p "$framework_dir" + if [[ ! -f "$binary_path" ]]; then + cp "$STUB_SOURCE" "$binary_path" + fi + # Empty hash marks the slice as a stub. build-xcframework.sh treats any + # mismatch (including stub vs. real source hash) as needing a rebuild. + if [[ ! -f "$hash_file" ]]; then + : > "$hash_file" fi - - available_libraries+=" - BinaryPath - ${PACKAGE_NAME}.framework/${PACKAGE_NAME} - LibraryIdentifier - ${slice_id} - LibraryPath - ${PACKAGE_NAME}.framework - SupportedArchitectures - -${arch_entries} - SupportedPlatform - ${platform} -${variant_entry} -" done + rm -f "$STUB_SOURCE" -cat > "${XCFRAMEWORK_PATH}/Info.plist" < - - - - AvailableLibraries - -${available_libraries} - CFBundlePackageType - XFWK - XCFrameworkFormatVersion - 1.0 - - -PLIST +write_xcframework_plist "$XCFRAMEWORK_PATH" "$PACKAGE_NAME" diff --git a/packages/expo-modules-jsi/apple/scripts/xcframework-helpers.sh b/packages/expo-modules-jsi/apple/scripts/xcframework-helpers.sh new file mode 100644 index 00000000000000..66b7d2ccf94cbf --- /dev/null +++ b/packages/expo-modules-jsi/apple/scripts/xcframework-helpers.sh @@ -0,0 +1,124 @@ +# Shared helpers for managing ExpoModulesJSI.xcframework. +# +# Sourced by create-stub-xcframework.sh and build-xcframework.sh. Defines the +# canonical slice metadata and the Info.plist writer used by both scripts so +# the manifest is produced from a single place. + +# All slice IDs known to the xcframework, mapped to their plist metadata. +# CocoaPods reads Info.plist at `pod install` time and generates a per-slice +# copy script; any slice missing from this table will be skipped by +# write_xcframework_plist with a warning. +# +# Format: slice_id|platform|variant|archs +EXPO_MODULES_JSI_KNOWN_SLICES=( + "ios-arm64|ios||arm64" + "ios-arm64_x86_64-simulator|ios|simulator|arm64 x86_64" + "tvos-arm64|tvos||arm64" + "tvos-arm64_x86_64-simulator|tvos|simulator|arm64 x86_64" +) + +# Slice IDs the xcframework must always declare, even when only a subset has +# been built. The stub script materializes empty placeholders for any of these +# missing on disk so CocoaPods can wire up copy/embed phases for every target +# the podspec supports. +EXPO_MODULES_JSI_REQUIRED_SLICE_IDS=( + "ios-arm64" + "ios-arm64_x86_64-simulator" + "tvos-arm64" + "tvos-arm64_x86_64-simulator" +) + +# xcframework_slice_descriptor SLICE_ID +# Echoes the descriptor row for SLICE_ID, or returns 1 if SLICE_ID is unknown. +xcframework_slice_descriptor() { + local slice_id="$1" + local entry + for entry in "${EXPO_MODULES_JSI_KNOWN_SLICES[@]}"; do + if [[ "${entry%%|*}" == "$slice_id" ]]; then + echo "$entry" + return 0 + fi + done + return 1 +} + +# write_xcframework_plist XCFRAMEWORK_PATH PACKAGE_NAME +# Writes Info.plist describing every slice directory currently inside +# XCFRAMEWORK_PATH. Slices are sorted by ID for deterministic output. Slice +# directories not listed in EXPO_MODULES_JSI_KNOWN_SLICES are skipped with a +# warning so callers can spot missing metadata instead of silently shipping a +# slice CocoaPods can't describe. +write_xcframework_plist() { + local xcframework_path="$1" + local package_name="$2" + + local slice_dirs=() + local entry + for entry in "${xcframework_path}"/*/; do + [[ -d "$entry" ]] || continue + slice_dirs+=("$(basename "$entry")") + done + + local sorted_slices=() + while IFS= read -r line; do + sorted_slices+=("$line") + done < <(printf '%s\n' "${slice_dirs[@]}" | LC_ALL=C sort) + + local available_libraries="" + local slice_id + for slice_id in "${sorted_slices[@]}"; do + local descriptor + if ! descriptor=$(xcframework_slice_descriptor "$slice_id"); then + echo "warning: skipping slice '${slice_id}' — not in EXPO_MODULES_JSI_KNOWN_SLICES" >&2 + continue + fi + + local platform variant archs + IFS='|' read -r _ platform variant archs <<<"$descriptor" + + local arch_entries="" + local arch + for arch in $archs; do + arch_entries+=" ${arch} +" + done + + local variant_entry="" + if [[ -n "$variant" ]]; then + variant_entry=" SupportedPlatformVariant + ${variant} +" + fi + + available_libraries+=" + BinaryPath + ${package_name}.framework/${package_name} + LibraryIdentifier + ${slice_id} + LibraryPath + ${package_name}.framework + SupportedArchitectures + +${arch_entries} + SupportedPlatform + ${platform} +${variant_entry} +" + done + + cat > "${xcframework_path}/Info.plist" < + + + + AvailableLibraries + +${available_libraries} + CFBundlePackageType + XFWK + XCFrameworkFormatVersion + 1.0 + + +PLIST +} diff --git a/packages/expo-observe/android/src/main/java/expo/modules/observe/ObservabilityManager.kt b/packages/expo-observe/android/src/main/java/expo/modules/observe/ObservabilityManager.kt index 0825681bdcf3e6..b9c051971cfb6a 100644 --- a/packages/expo-observe/android/src/main/java/expo/modules/observe/ObservabilityManager.kt +++ b/packages/expo-observe/android/src/main/java/expo/modules/observe/ObservabilityManager.kt @@ -136,7 +136,7 @@ class BaseObservabilityManager( suspend fun cleanup() { pendingMetricsManager.cleanupOldPendingMetrics() - // TODO(@ubax): Move sessionManager.cleanupOldMetrics() out of eas observe - sessionManager.cleanupOldMetrics() + // TODO(@ubax): Move sessionManager.cleanupOldSessions out of eas observe + sessionManager.cleanupOldSessions() } } diff --git a/packages/expo-observe/android/src/test/java/expo/modules/observe/BaseObservabilityManagerTest.kt b/packages/expo-observe/android/src/test/java/expo/modules/observe/BaseObservabilityManagerTest.kt index 9d8c87a59a81c3..cd8f2b03b2c3ae 100644 --- a/packages/expo-observe/android/src/test/java/expo/modules/observe/BaseObservabilityManagerTest.kt +++ b/packages/expo-observe/android/src/test/java/expo/modules/observe/BaseObservabilityManagerTest.kt @@ -753,7 +753,7 @@ class BaseObservabilityManagerTest { // region Cleanup tests @Test - fun `cleanup calls both cleanupOldPendingMetrics and cleanupOldMetrics`() = + fun `cleanup prunes pending metrics and stale sessions`() = runTest { // Arrange val manager = createManager() @@ -763,7 +763,7 @@ class BaseObservabilityManagerTest { // Assert coVerify(exactly = 1) { mockPendingMetricsManager.cleanupOldPendingMetrics() } - coVerify(exactly = 1) { mockSessionManager.cleanupOldMetrics() } + coVerify(exactly = 1) { mockSessionManager.cleanupOldSessions() } } // endregion diff --git a/packages/expo/CHANGELOG.md b/packages/expo/CHANGELOG.md index 73dd7f491f2392..e9d48d301b3626 100644 --- a/packages/expo/CHANGELOG.md +++ b/packages/expo/CHANGELOG.md @@ -15,6 +15,7 @@ - Remove pinned dependencies ([#45520](https://github.com/expo/expo/pull/45520) by [@kitten](https://githun.com/kitten)) - Send platform as HMR log mode for terminal log prefixing. ([#45516](https://github.com/expo/expo/pull/45516) by [@EvanBacon](https://github.com/EvanBacon)) - Remove redundant log messages from web HMR setup. ([#45516](https://github.com/expo/expo/pull/45516) by [@EvanBacon](https://github.com/EvanBacon)) + ## 56.0.0-preview.6 — 2026-05-07 _This version does not introduce any user-facing changes._ diff --git a/tools/src/CocoaPods.ts b/tools/src/CocoaPods.ts index 2ae8881c700395..9e69c8cf3ca649 100644 --- a/tools/src/CocoaPods.ts +++ b/tools/src/CocoaPods.ts @@ -46,13 +46,16 @@ type PodInstallOptions = Partial<{ }>; /** - * Installs pods under given project path. + * Re-resolves the given pods under the project path, + * respecting the existing lockfile for all other pods. Equivalent to + * `pod update --no-repo-update`. */ -export async function podInstallAsync( +export async function podUpdateAsync( projectPath: string, + podNames: string[], options: PodInstallOptions = { noRepoUpdate: false, stdio: 'pipe' } ): Promise { - const args = ['install']; + const args = ['update', ...podNames]; if (options.noRepoUpdate) { args.push('--no-repo-update'); diff --git a/tools/src/generate-docs-api-data/docsInline.ts b/tools/src/generate-docs-api-data/docsInline.ts index cddedc8c23e409..a9c02c283483cc 100644 --- a/tools/src/generate-docs-api-data/docsInline.ts +++ b/tools/src/generate-docs-api-data/docsInline.ts @@ -223,7 +223,17 @@ async function collectTaggedDeclarations( disableSources: true, hideGenerator: true, excludeExternals: true, - blockTags: [...Configuration.OptionDefaults.blockTags, DOCS_INLINE_TAG], + blockTags: [ + ...Configuration.OptionDefaults.blockTags, + DOCS_INLINE_TAG, + '@alias', + '@deprecated', + '@docsMissing', + '@header', + '@hideType', + '@needsAudit', + '@platform', + ], } as unknown as TypeDocOptions, [new TSConfigReader(), new TypeDocReader()] ); diff --git a/tools/src/publish-packages/tasks/updateIosProjects.ts b/tools/src/publish-packages/tasks/updateIosProjects.ts index 7cd782c9b0c674..fc93366dd08c45 100644 --- a/tools/src/publish-packages/tasks/updateIosProjects.ts +++ b/tools/src/publish-packages/tasks/updateIosProjects.ts @@ -2,7 +2,7 @@ import chalk from 'chalk'; import path from 'path'; import { selectPackagesToPublish } from './selectPackagesToPublish'; -import { podInstallAsync } from '../../CocoaPods'; +import { podUpdateAsync } from '../../CocoaPods'; import logger from '../../Logger'; import { Task } from '../../TasksRunner'; import { filterAsync } from '../../Utils'; @@ -46,10 +46,14 @@ export const updateIosProjects = new Task( logger.log(' ', `${green(nativeApp.packageName)}: Reinstalling pods...`); - // `pod install` sometimes fails, but it's not needed to properly - // publish packages, so let's just continue if that happens. + // Use `pod update`: we just bumped these pods' versions, and precompiled modules + // register them as `:podspec =>` sources, which trip CocoaPods' strict version-drift check on + // `pod install`. `pod update ` re-resolves only the bumped + // pods and is correct in source mode too. Failures are non-fatal. try { - await podInstallAsync(path.join(nativeApp.path, 'ios'), { noRepoUpdate: true }); + await podUpdateAsync(path.join(nativeApp.path, 'ios'), podspecNames, { + noRepoUpdate: true, + }); } catch (e) { logger.debug(e.stderr || e.stdout); logger.error('🍎 Failed to install pods in', green(nativeApp.packageName));