@forthtilliath/react-native-kit 0.15.1 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +100 -0
  2. package/dist/components/feedback/ErrorFallback.d.ts +63 -0
  3. package/dist/components/feedback/ErrorFallback.d.ts.map +1 -0
  4. package/dist/components/feedback/ErrorFallback.js +86 -0
  5. package/dist/components/feedback/index.d.ts +2 -0
  6. package/dist/components/feedback/index.d.ts.map +1 -0
  7. package/dist/components/feedback/index.js +1 -0
  8. package/dist/components/index.d.ts +2 -0
  9. package/dist/components/index.d.ts.map +1 -1
  10. package/dist/components/index.js +2 -0
  11. package/dist/components/list/AddButton.d.ts +27 -0
  12. package/dist/components/list/AddButton.d.ts.map +1 -0
  13. package/dist/components/list/AddButton.js +29 -0
  14. package/dist/components/list/DragHandle.d.ts +35 -0
  15. package/dist/components/list/DragHandle.d.ts.map +1 -0
  16. package/dist/components/list/DragHandle.js +31 -0
  17. package/dist/components/list/SwipeableRow.d.ts +18 -4
  18. package/dist/components/list/SwipeableRow.d.ts.map +1 -1
  19. package/dist/components/list/SwipeableRow.js +40 -13
  20. package/dist/components/list/index.d.ts +2 -0
  21. package/dist/components/list/index.d.ts.map +1 -1
  22. package/dist/components/list/index.js +2 -0
  23. package/dist/components/overlay/BottomSheet.d.ts +45 -0
  24. package/dist/components/overlay/BottomSheet.d.ts.map +1 -0
  25. package/dist/components/overlay/BottomSheet.js +48 -0
  26. package/dist/components/overlay/index.d.ts +2 -0
  27. package/dist/components/overlay/index.d.ts.map +1 -0
  28. package/dist/components/overlay/index.js +1 -0
  29. package/dist/components/picker/CheckboxGroup.d.ts +47 -0
  30. package/dist/components/picker/CheckboxGroup.d.ts.map +1 -0
  31. package/dist/components/picker/CheckboxGroup.js +50 -0
  32. package/dist/components/picker/MonthDayGrid.d.ts +58 -0
  33. package/dist/components/picker/MonthDayGrid.d.ts.map +1 -0
  34. package/dist/components/picker/MonthDayGrid.js +73 -0
  35. package/dist/components/picker/OptionsModal.d.ts +45 -0
  36. package/dist/components/picker/OptionsModal.d.ts.map +1 -0
  37. package/dist/components/picker/OptionsModal.js +45 -0
  38. package/dist/components/picker/QuantityStepper.d.ts +63 -0
  39. package/dist/components/picker/QuantityStepper.d.ts.map +1 -0
  40. package/dist/components/picker/QuantityStepper.js +101 -0
  41. package/dist/components/picker/SegmentedToggle.d.ts +52 -0
  42. package/dist/components/picker/SegmentedToggle.d.ts.map +1 -0
  43. package/dist/components/picker/SegmentedToggle.js +48 -0
  44. package/dist/components/picker/SelectField.d.ts +45 -0
  45. package/dist/components/picker/SelectField.d.ts.map +1 -0
  46. package/dist/components/picker/SelectField.js +54 -0
  47. package/dist/components/picker/index.d.ts +6 -0
  48. package/dist/components/picker/index.d.ts.map +1 -1
  49. package/dist/components/picker/index.js +6 -0
  50. package/dist/components/settings/SettingsCard.d.ts +63 -0
  51. package/dist/components/settings/SettingsCard.d.ts.map +1 -0
  52. package/dist/components/settings/SettingsCard.js +68 -0
  53. package/dist/components/settings/SwitchRow.d.ts +48 -0
  54. package/dist/components/settings/SwitchRow.d.ts.map +1 -0
  55. package/dist/components/settings/SwitchRow.js +44 -0
  56. package/dist/components/settings/index.d.ts +2 -0
  57. package/dist/components/settings/index.d.ts.map +1 -1
  58. package/dist/components/settings/index.js +2 -0
  59. package/dist/components/theme/ThemePreferenceProvider.d.ts +39 -0
  60. package/dist/components/theme/ThemePreferenceProvider.d.ts.map +1 -0
  61. package/dist/components/theme/ThemePreferenceProvider.js +53 -0
  62. package/dist/components/theme/index.d.ts +2 -0
  63. package/dist/components/theme/index.d.ts.map +1 -1
  64. package/dist/components/theme/index.js +2 -0
  65. package/dist/components/theme/themePreferenceContext.d.ts +20 -0
  66. package/dist/components/theme/themePreferenceContext.d.ts.map +1 -0
  67. package/dist/components/theme/themePreferenceContext.js +21 -0
  68. package/dist/index.d.ts +20 -0
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +20 -0
  71. package/dist/utils/calendar/index.d.ts +3 -0
  72. package/dist/utils/calendar/index.d.ts.map +1 -0
  73. package/dist/utils/calendar/index.js +2 -0
  74. package/dist/utils/calendar/syncDedicatedCalendar.d.ts +37 -0
  75. package/dist/utils/calendar/syncDedicatedCalendar.d.ts.map +1 -0
  76. package/dist/utils/calendar/syncDedicatedCalendar.js +42 -0
  77. package/dist/utils/calendar/toCalendarEventDetails.d.ts +32 -0
  78. package/dist/utils/calendar/toCalendarEventDetails.d.ts.map +1 -0
  79. package/dist/utils/calendar/toCalendarEventDetails.js +47 -0
  80. package/dist/utils/files/appFiles.d.ts +61 -0
  81. package/dist/utils/files/appFiles.d.ts.map +1 -0
  82. package/dist/utils/files/appFiles.js +126 -0
  83. package/dist/utils/files/imageThumbnail.d.ts +22 -0
  84. package/dist/utils/files/imageThumbnail.d.ts.map +1 -0
  85. package/dist/utils/files/imageThumbnail.js +28 -0
  86. package/dist/utils/files/index.d.ts +3 -0
  87. package/dist/utils/files/index.d.ts.map +1 -0
  88. package/dist/utils/files/index.js +2 -0
  89. package/dist/utils/helpers/haptics.d.ts +9 -0
  90. package/dist/utils/helpers/haptics.d.ts.map +1 -0
  91. package/dist/utils/helpers/haptics.js +28 -0
  92. package/dist/utils/helpers/index.d.ts +5 -0
  93. package/dist/utils/helpers/index.d.ts.map +1 -1
  94. package/dist/utils/helpers/index.js +5 -0
  95. package/dist/utils/helpers/isNativeModuleAvailable.d.ts +12 -0
  96. package/dist/utils/helpers/isNativeModuleAvailable.d.ts.map +1 -0
  97. package/dist/utils/helpers/isNativeModuleAvailable.js +15 -0
  98. package/dist/utils/helpers/shareFile.d.ts +23 -0
  99. package/dist/utils/helpers/shareFile.d.ts.map +1 -0
  100. package/dist/utils/helpers/shareFile.js +26 -0
  101. package/dist/utils/helpers/shareTextFile.d.ts +16 -0
  102. package/dist/utils/helpers/shareTextFile.d.ts.map +1 -0
  103. package/dist/utils/helpers/shareTextFile.js +23 -0
  104. package/dist/utils/helpers/shareViewAsImage.d.ts +21 -0
  105. package/dist/utils/helpers/shareViewAsImage.d.ts.map +1 -0
  106. package/dist/utils/helpers/shareViewAsImage.js +32 -0
  107. package/dist/utils/index.d.ts +2 -0
  108. package/dist/utils/index.d.ts.map +1 -1
  109. package/dist/utils/index.js +2 -0
  110. package/package.json +38 -6
package/dist/index.d.ts CHANGED
@@ -1,26 +1,46 @@
1
+ export * from "./components/feedback/ErrorFallback.js";
2
+ export * from "./components/list/AddButton.js";
1
3
  export * from "./components/list/ColorDot.js";
4
+ export * from "./components/list/DragHandle.js";
2
5
  export * from "./components/list/SwipeableRow.js";
3
6
  export * from "./components/list/Thumbnail.js";
4
7
  export * from "./components/list/UndoToast.js";
8
+ export * from "./components/overlay/BottomSheet.js";
9
+ export * from "./components/picker/CheckboxGroup.js";
10
+ export * from "./components/picker/MonthDayGrid.js";
11
+ export * from "./components/picker/OptionsModal.js";
5
12
  export * from "./components/picker/PhotoPicker.js";
6
13
  export * from "./components/picker/PickerModal.js";
14
+ export * from "./components/picker/QuantityStepper.js";
15
+ export * from "./components/picker/SegmentedToggle.js";
16
+ export * from "./components/picker/SelectField.js";
7
17
  export * from "./components/picker/VoiceSearchButton.js";
8
18
  export * from "./components/settings/AboutSettingsScreen.js";
9
19
  export * from "./components/settings/BackupSettingsScreen.js";
10
20
  export * from "./components/settings/ContactSettingsScreen.js";
11
21
  export * from "./components/settings/PrivacySettingsScreen.js";
22
+ export * from "./components/settings/SettingsCard.js";
12
23
  export * from "./components/settings/SettingsMenu.js";
24
+ export * from "./components/settings/SwitchRow.js";
13
25
  export * from "./components/settings/ThemeSettingsScreen.js";
14
26
  export * from "./components/settings/UpdateSettingsScreen.js";
15
27
  export * from "./components/theme/ThemeOptionList.js";
28
+ export * from "./components/theme/themePreferenceContext.js";
29
+ export * from "./components/theme/ThemePreferenceProvider.js";
16
30
  export * from "./components/theme/ThemeToggle.js";
17
31
  export * from "./hooks/useDebouncedChange.js";
18
32
  export * from "./hooks/useEffectiveColorScheme.js";
19
33
  export * from "./hooks/useSubmitGuard.js";
20
34
  export * from "./i18n/KitLocaleProvider.js";
21
35
  export * from "./i18n/locale.js";
36
+ export * from "./utils/calendar/syncDedicatedCalendar.js";
37
+ export * from "./utils/calendar/toCalendarEventDetails.js";
22
38
  export * from "./utils/helpers/confirmDestructive.js";
39
+ export * from "./utils/helpers/haptics.js";
40
+ export * from "./utils/helpers/isNativeModuleAvailable.js";
23
41
  export * from "./utils/helpers/mergeSlotStyles.js";
42
+ export * from "./utils/helpers/shareFile.js";
43
+ export * from "./utils/helpers/shareTextFile.js";
24
44
  export { getMostRecentIds, type RecentIdRow, } from "@forthtilliath/ts-kit/array/getMostRecentIds";
25
45
  export { nextInCycle } from "@forthtilliath/ts-kit/array/nextInCycle";
26
46
  export { rankByNameMatch } from "@forthtilliath/ts-kit/array/rankByNameMatch";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,oCAAoC,CAAC;AACnD,cAAc,oCAAoC,CAAC;AACnD,cAAc,0CAA0C,CAAC;AACzD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,+CAA+C,CAAC;AAC9D,cAAc,gDAAgD,CAAC;AAC/D,cAAc,gDAAgD,CAAC;AAC/D,cAAc,uCAAuC,CAAC;AACtD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,+CAA+C,CAAC;AAC9D,cAAc,uCAAuC,CAAC;AACtD,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,oCAAoC,CAAC;AACnD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kBAAkB,CAAC;AACjC,cAAc,uCAAuC,CAAC;AACtD,cAAc,oCAAoC,CAAC;AAGnD,OAAO,EACL,gBAAgB,EAChB,KAAK,WAAW,GACjB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAC5E,OAAO,EACL,gBAAgB,EAChB,KAAK,YAAY,GAClB,MAAM,6CAA6C,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,wCAAwC,CAAC;AACvD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,qCAAqC,CAAC;AACpD,cAAc,sCAAsC,CAAC;AACrD,cAAc,qCAAqC,CAAC;AACpD,cAAc,qCAAqC,CAAC;AACpD,cAAc,oCAAoC,CAAC;AACnD,cAAc,oCAAoC,CAAC;AACnD,cAAc,wCAAwC,CAAC;AACvD,cAAc,wCAAwC,CAAC;AACvD,cAAc,oCAAoC,CAAC;AACnD,cAAc,0CAA0C,CAAC;AACzD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,+CAA+C,CAAC;AAC9D,cAAc,gDAAgD,CAAC;AAC/D,cAAc,gDAAgD,CAAC;AAC/D,cAAc,uCAAuC,CAAC;AACtD,cAAc,uCAAuC,CAAC;AACtD,cAAc,oCAAoC,CAAC;AACnD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,+CAA+C,CAAC;AAC9D,cAAc,uCAAuC,CAAC;AACtD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,+CAA+C,CAAC;AAC9D,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,oCAAoC,CAAC;AACnD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kBAAkB,CAAC;AACjC,cAAc,2CAA2C,CAAC;AAC1D,cAAc,4CAA4C,CAAC;AAC3D,cAAc,uCAAuC,CAAC;AACtD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4CAA4C,CAAC;AAC3D,cAAc,oCAAoC,CAAC;AACnD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AAGjD,OAAO,EACL,gBAAgB,EAChB,KAAK,WAAW,GACjB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAC5E,OAAO,EACL,gBAAgB,EAChB,KAAK,YAAY,GAClB,MAAM,6CAA6C,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAC"}
package/dist/index.js CHANGED
@@ -3,29 +3,49 @@
3
3
  // etc.) remain the recommended default for apps that want to avoid pulling in
4
4
  // peer deps they don't have installed (Metro doesn't reliably tree-shake) —
5
5
  // see the README.
6
+ export * from "./components/feedback/ErrorFallback.js";
7
+ export * from "./components/list/AddButton.js";
6
8
  export * from "./components/list/ColorDot.js";
9
+ export * from "./components/list/DragHandle.js";
7
10
  export * from "./components/list/SwipeableRow.js";
8
11
  export * from "./components/list/Thumbnail.js";
9
12
  export * from "./components/list/UndoToast.js";
13
+ export * from "./components/overlay/BottomSheet.js";
14
+ export * from "./components/picker/CheckboxGroup.js";
15
+ export * from "./components/picker/MonthDayGrid.js";
16
+ export * from "./components/picker/OptionsModal.js";
10
17
  export * from "./components/picker/PhotoPicker.js";
11
18
  export * from "./components/picker/PickerModal.js";
19
+ export * from "./components/picker/QuantityStepper.js";
20
+ export * from "./components/picker/SegmentedToggle.js";
21
+ export * from "./components/picker/SelectField.js";
12
22
  export * from "./components/picker/VoiceSearchButton.js";
13
23
  export * from "./components/settings/AboutSettingsScreen.js";
14
24
  export * from "./components/settings/BackupSettingsScreen.js";
15
25
  export * from "./components/settings/ContactSettingsScreen.js";
16
26
  export * from "./components/settings/PrivacySettingsScreen.js";
27
+ export * from "./components/settings/SettingsCard.js";
17
28
  export * from "./components/settings/SettingsMenu.js";
29
+ export * from "./components/settings/SwitchRow.js";
18
30
  export * from "./components/settings/ThemeSettingsScreen.js";
19
31
  export * from "./components/settings/UpdateSettingsScreen.js";
20
32
  export * from "./components/theme/ThemeOptionList.js";
33
+ export * from "./components/theme/themePreferenceContext.js";
34
+ export * from "./components/theme/ThemePreferenceProvider.js";
21
35
  export * from "./components/theme/ThemeToggle.js";
22
36
  export * from "./hooks/useDebouncedChange.js";
23
37
  export * from "./hooks/useEffectiveColorScheme.js";
24
38
  export * from "./hooks/useSubmitGuard.js";
25
39
  export * from "./i18n/KitLocaleProvider.js";
26
40
  export * from "./i18n/locale.js";
41
+ export * from "./utils/calendar/syncDedicatedCalendar.js";
42
+ export * from "./utils/calendar/toCalendarEventDetails.js";
27
43
  export * from "./utils/helpers/confirmDestructive.js";
44
+ export * from "./utils/helpers/haptics.js";
45
+ export * from "./utils/helpers/isNativeModuleAvailable.js";
28
46
  export * from "./utils/helpers/mergeSlotStyles.js";
47
+ export * from "./utils/helpers/shareFile.js";
48
+ export * from "./utils/helpers/shareTextFile.js";
29
49
  // Framework-agnostic — actually implemented (and tested/documented) in
30
50
  // ts-kit, re-exported here so existing imports of these names keep working.
31
51
  export { getMostRecentIds, } from "@forthtilliath/ts-kit/array/getMostRecentIds";
@@ -0,0 +1,3 @@
1
+ export * from "./syncDedicatedCalendar.js";
2
+ export * from "./toCalendarEventDetails.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/calendar/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from "./syncDedicatedCalendar.js";
2
+ export * from "./toCalendarEventDetails.js";
@@ -0,0 +1,37 @@
1
+ import type { CalendarEventDetails } from "./toCalendarEventDetails.js";
2
+ /** The app's own calendar on the phone. */
3
+ export interface DedicatedCalendar {
4
+ /** Internal name (Android), stable: finds the calendar again on the next sync. */
5
+ name: string;
6
+ /** Shown in the user's calendar app. */
7
+ title: string;
8
+ color: string;
9
+ }
10
+ export interface SyncDedicatedCalendarOptions {
11
+ calendar: DedicatedCalendar;
12
+ /** Start of the period to replace (included). */
13
+ from: Date;
14
+ /** End of the period to replace (excluded). */
15
+ to: Date;
16
+ /** The period's new events — see `toCalendarEventDetails`. */
17
+ events: readonly CalendarEventDetails[];
18
+ }
19
+ export type CalendarSyncResult = {
20
+ status: "denied";
21
+ } | {
22
+ status: "done";
23
+ count: number;
24
+ };
25
+ /**
26
+ * Writes a period's events to the app's dedicated calendar on the phone
27
+ * (created on first use, as a local account), replacing whatever that
28
+ * calendar held over the period: a new sync replaces the previous one with no
29
+ * duplicates, and an event removed from the app disappears from the calendar
30
+ * too. Other calendars are never touched. Asks for the calendar permission
31
+ * first. Needs `expo-calendar` (an optional peer dependency).
32
+ *
33
+ * @param options - See {@link SyncDedicatedCalendarOptions}.
34
+ * @returns `{ status: "denied" }` without the permission, else the number of events written.
35
+ */
36
+ export declare function syncDedicatedCalendar({ calendar, from, to, events, }: SyncDedicatedCalendarOptions): Promise<CalendarSyncResult>;
37
+ //# sourceMappingURL=syncDedicatedCalendar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"syncDedicatedCalendar.d.ts","sourceRoot":"","sources":["../../../src/utils/calendar/syncDedicatedCalendar.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAExE,2CAA2C;AAC3C,MAAM,WAAW,iBAAiB;IAChC,kFAAkF;IAClF,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,iDAAiD;IACjD,IAAI,EAAE,IAAI,CAAC;IACX,+CAA+C;IAC/C,EAAE,EAAE,IAAI,CAAC;IACT,8DAA8D;IAC9D,MAAM,EAAE,SAAS,oBAAoB,EAAE,CAAC;CACzC;AAED,MAAM,MAAM,kBAAkB,GAC5B;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAwB3D;;;;;;;;;;GAUG;AACH,wBAAsB,qBAAqB,CAAC,EAC1C,QAAQ,EACR,IAAI,EACJ,EAAE,EACF,MAAM,GACP,EAAE,4BAA4B,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAY5D"}
@@ -0,0 +1,42 @@
1
+ import * as Calendar from "expo-calendar";
2
+ async function getOrCreateLocalCalendar({ name, title, color, }) {
3
+ const calendars = await Calendar.getCalendars(Calendar.EntityTypes.EVENT);
4
+ const existing = calendars.find((c) => c.name === name);
5
+ if (existing)
6
+ return existing;
7
+ return Calendar.createCalendar({
8
+ title,
9
+ name,
10
+ color,
11
+ entityType: Calendar.EntityTypes.EVENT,
12
+ // A local account: nothing syncs to a Google account, and the user can
13
+ // hide this calendar in one tap from their calendar app.
14
+ source: { isLocalAccount: true, name: title, type: "LOCAL" },
15
+ ownerAccount: title,
16
+ accessLevel: Calendar.CalendarAccessLevel.OWNER,
17
+ });
18
+ }
19
+ /**
20
+ * Writes a period's events to the app's dedicated calendar on the phone
21
+ * (created on first use, as a local account), replacing whatever that
22
+ * calendar held over the period: a new sync replaces the previous one with no
23
+ * duplicates, and an event removed from the app disappears from the calendar
24
+ * too. Other calendars are never touched. Asks for the calendar permission
25
+ * first. Needs `expo-calendar` (an optional peer dependency).
26
+ *
27
+ * @param options - See {@link SyncDedicatedCalendarOptions}.
28
+ * @returns `{ status: "denied" }` without the permission, else the number of events written.
29
+ */
30
+ export async function syncDedicatedCalendar({ calendar, from, to, events, }) {
31
+ const { granted } = await Calendar.requestCalendarPermissions();
32
+ if (!granted)
33
+ return { status: "denied" };
34
+ const target = await getOrCreateLocalCalendar(calendar);
35
+ for (const event of await target.listEvents(from, to)) {
36
+ await event.delete();
37
+ }
38
+ for (const event of events) {
39
+ await target.createEvent(event);
40
+ }
41
+ return { status: "done", count: events.length };
42
+ }
@@ -0,0 +1,32 @@
1
+ /** A calendar event as an app describes it: a day, and optional wall-clock hours. */
2
+ export interface CalendarEventInput {
3
+ title: string;
4
+ notes?: string;
5
+ /** The day, `YYYY-MM-DD`. */
6
+ date: string;
7
+ /** `HH:MM`; without `start` and `end` the event lasts all day. */
8
+ start?: string;
9
+ /** `HH:MM`; at or before `start`, the event ends the next day (night shift). */
10
+ end?: string;
11
+ }
12
+ /** What `expo-calendar`'s `createEvent` expects. */
13
+ export interface CalendarEventDetails {
14
+ title: string;
15
+ notes: string;
16
+ startDate: Date;
17
+ endDate: Date;
18
+ allDay: boolean;
19
+ timeZone: string;
20
+ }
21
+ /**
22
+ * Converts an app event to `expo-calendar`'s format. Timed events are in
23
+ * local time and may end the next day; an all-day event is set at UTC
24
+ * midnight with the `"UTC"` time zone — what Android requires, otherwise it
25
+ * shows up a day off depending on the device's time zone.
26
+ *
27
+ * @param event - See {@link CalendarEventInput}.
28
+ * @param timeZone - Time zone of timed events. @defaultValue the device's
29
+ * @returns The details to pass to `calendar.createEvent()`.
30
+ */
31
+ export declare function toCalendarEventDetails(event: CalendarEventInput, timeZone?: string): CalendarEventDetails;
32
+ //# sourceMappingURL=toCalendarEventDetails.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toCalendarEventDetails.d.ts","sourceRoot":"","sources":["../../../src/utils/calendar/toCalendarEventDetails.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gFAAgF;IAChF,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,oDAAoD;AACpD,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,EAAE,IAAI,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAsBD;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,kBAAkB,EACzB,QAAQ,GAAE,MAAyB,GAClC,oBAAoB,CAoBtB"}
@@ -0,0 +1,47 @@
1
+ function deviceTimeZone() {
2
+ return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
3
+ }
4
+ function nextDay(isoDate) {
5
+ const day = new Date(`${isoDate}T00:00:00Z`);
6
+ day.setUTCDate(day.getUTCDate() + 1);
7
+ return day.toISOString().slice(0, 10);
8
+ }
9
+ function localDateTime(isoDate, time) {
10
+ const [year = 0, month = 1, day = 1] = isoDate.split("-").map(Number);
11
+ const [hours = 0, minutes = 0] = time.split(":").map(Number);
12
+ return new Date(year, month - 1, day, hours, minutes);
13
+ }
14
+ function utcMidnight(isoDate) {
15
+ return new Date(`${isoDate}T00:00:00Z`);
16
+ }
17
+ /**
18
+ * Converts an app event to `expo-calendar`'s format. Timed events are in
19
+ * local time and may end the next day; an all-day event is set at UTC
20
+ * midnight with the `"UTC"` time zone — what Android requires, otherwise it
21
+ * shows up a day off depending on the device's time zone.
22
+ *
23
+ * @param event - See {@link CalendarEventInput}.
24
+ * @param timeZone - Time zone of timed events. @defaultValue the device's
25
+ * @returns The details to pass to `calendar.createEvent()`.
26
+ */
27
+ export function toCalendarEventDetails(event, timeZone = deviceTimeZone()) {
28
+ if (event.start && event.end) {
29
+ const endDay = event.end <= event.start ? nextDay(event.date) : event.date;
30
+ return {
31
+ title: event.title,
32
+ notes: event.notes ?? "",
33
+ startDate: localDateTime(event.date, event.start),
34
+ endDate: localDateTime(endDay, event.end),
35
+ allDay: false,
36
+ timeZone,
37
+ };
38
+ }
39
+ return {
40
+ title: event.title,
41
+ notes: event.notes ?? "",
42
+ startDate: utcMidnight(event.date),
43
+ endDate: utcMidnight(nextDay(event.date)),
44
+ allDay: true,
45
+ timeZone: "UTC",
46
+ };
47
+ }
@@ -0,0 +1,61 @@
1
+ import { Directory } from "expo-file-system";
2
+ /**
3
+ * The app's persistent sub-folder `name` (in documents), created on first use.
4
+ * `name` is made of letters, digits, `_`, `-`, and `/` between nested folders.
5
+ *
6
+ * @throws if `name` holds any other character (`..`, a leading `/`…).
7
+ */
8
+ export declare function getAppDirectory(name: string): Directory;
9
+ /**
10
+ * Extension of a file URI, query string ignored — `fallback` when it has none
11
+ * (picker URIs don't always carry one).
12
+ */
13
+ export declare function getFileExtension(uri: string, fallback?: string): string;
14
+ export interface PersistFileOptions {
15
+ /** Persistent sub-folder, see `getAppDirectory`. */
16
+ directory: string;
17
+ /** Start of the new file name (letters, digits, `_`, `-`), followed by a timestamp. */
18
+ prefix: string;
19
+ }
20
+ /**
21
+ * Copies a temporary file (picker result, download) into the persistent
22
+ * sub-folder and returns the copy's URI, to store instead of the original.
23
+ */
24
+ export declare function persistFile(sourceUri: string, { directory, prefix }: PersistFileOptions): Promise<string>;
25
+ export interface WriteBase64FileOptions extends PersistFileOptions {
26
+ /** @defaultValue "jpg" */
27
+ extension?: string;
28
+ }
29
+ /**
30
+ * Writes base64 content (a photo embedded in a JSON backup…) as a new file of
31
+ * the persistent sub-folder and returns its URI. Names are random rather than
32
+ * timestamped: a restore writes many files within the same millisecond.
33
+ *
34
+ * @throws if `directory`, `prefix` or `extension` isn't a plain name (see
35
+ * {@link getAppDirectory}).
36
+ */
37
+ export declare function writeBase64File(base64: string, { directory, prefix, extension }: WriteBase64FileOptions): string;
38
+ /**
39
+ * Content of a file as base64 (to embed it in a JSON backup), `null` when it
40
+ * can't be read — a photo the OS already cleared from its cache, a bad URI.
41
+ */
42
+ export declare function readFileBase64(uri: string): string | null;
43
+ /** Whether a file exists at `uri`; `false` for a malformed URI instead of throwing. */
44
+ export declare function fileExists(uri: string): boolean;
45
+ /**
46
+ * Deletes a file if it is still there, best effort: an absent file or a failed
47
+ * deletion never makes the caller fail.
48
+ */
49
+ export declare function deleteFileQuietly(uri: string | null | undefined): void;
50
+ /**
51
+ * Deletes every file of the persistent sub-folder that isn't in `keep`
52
+ * (replaced photo, deleted entity, data replaced by an import). Returns how
53
+ * many files were deleted.
54
+ *
55
+ * Files are matched by **name**, not by full URI: Android reaches the same
56
+ * file as `/data/user/0/<package>/…` or `/data/data/<package>/…` depending on
57
+ * the API that built the URI — compared as a whole, a stored URI in the other
58
+ * form would get its photo deleted.
59
+ */
60
+ export declare function pruneAppDirectory(name: string, keep: Iterable<string>): number;
61
+ //# sourceMappingURL=appFiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appFiles.d.ts","sourceRoot":"","sources":["../../../src/utils/files/appFiles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAe,MAAM,kBAAkB,CAAC;AA0B1D;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAQvD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,SAAQ,GAAG,MAAM,CAGtE;AAED,MAAM,WAAW,kBAAkB;IACjC,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,uFAAuF;IACvF,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,EACjB,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,kBAAkB,GACxC,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED,MAAM,WAAW,sBAAuB,SAAQ,kBAAkB;IAChE,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,EAAE,SAAS,EAAE,MAAM,EAAE,SAAiB,EAAE,EAAE,sBAAsB,GAC/D,MAAM,CAQR;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMzD;AAED,uFAAuF;AACvF,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAM/C;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAQtE;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,GACrB,MAAM,CAcR"}
@@ -0,0 +1,126 @@
1
+ import { Directory, File, Paths } from "expo-file-system";
2
+ import { randomId } from "@forthtilliath/ts-kit/id/randomId";
3
+ // Files the app keeps for good (photos, avatars...): pickers and exports hand
4
+ // back URIs in a cache folder the OS may empty at any time, so anything worth
5
+ // keeping is copied into a sub-folder of the app's documents.
6
+ // Folder names, prefixes and extensions end up in a path, and callers may
7
+ // build them from imported data (a restored backup): only plain name
8
+ // characters get through — no "..", no way out of the documents folder.
9
+ const SAFE_NAME = /^[\w-]+$/;
10
+ const SAFE_FOLDER = /^[\w-]+(\/[\w-]+)*$/;
11
+ function assertSafe(value, pattern, what) {
12
+ if (!pattern.test(value)) {
13
+ throw new Error(`Invalid ${what}: ${JSON.stringify(value)}`);
14
+ }
15
+ return value;
16
+ }
17
+ /** Last segment of a URI, i.e. the file name. */
18
+ function fileNameOf(uri) {
19
+ return uri.slice(uri.lastIndexOf("/") + 1);
20
+ }
21
+ /**
22
+ * The app's persistent sub-folder `name` (in documents), created on first use.
23
+ * `name` is made of letters, digits, `_`, `-`, and `/` between nested folders.
24
+ *
25
+ * @throws if `name` holds any other character (`..`, a leading `/`…).
26
+ */
27
+ export function getAppDirectory(name) {
28
+ const directory = new Directory(Paths.document, assertSafe(name, SAFE_FOLDER, "folder name"));
29
+ if (!directory.exists)
30
+ directory.create({ intermediates: true, idempotent: true });
31
+ return directory;
32
+ }
33
+ /**
34
+ * Extension of a file URI, query string ignored — `fallback` when it has none
35
+ * (picker URIs don't always carry one).
36
+ */
37
+ export function getFileExtension(uri, fallback = "jpg") {
38
+ const match = uri.split("?")[0]?.match(/\.(\w+)$/);
39
+ return match?.[1] ?? fallback;
40
+ }
41
+ /**
42
+ * Copies a temporary file (picker result, download) into the persistent
43
+ * sub-folder and returns the copy's URI, to store instead of the original.
44
+ */
45
+ export async function persistFile(sourceUri, { directory, prefix }) {
46
+ const destination = new File(getAppDirectory(directory), `${assertSafe(prefix, SAFE_NAME, "prefix")}-${Date.now()}.${getFileExtension(sourceUri)}`);
47
+ await new File(sourceUri).copy(destination);
48
+ return destination.uri;
49
+ }
50
+ /**
51
+ * Writes base64 content (a photo embedded in a JSON backup…) as a new file of
52
+ * the persistent sub-folder and returns its URI. Names are random rather than
53
+ * timestamped: a restore writes many files within the same millisecond.
54
+ *
55
+ * @throws if `directory`, `prefix` or `extension` isn't a plain name (see
56
+ * {@link getAppDirectory}).
57
+ */
58
+ export function writeBase64File(base64, { directory, prefix, extension = "jpg" }) {
59
+ const file = new File(getAppDirectory(directory), `${assertSafe(prefix, SAFE_NAME, "prefix")}-${randomId()}.${assertSafe(extension, SAFE_NAME, "extension")}`);
60
+ file.create();
61
+ file.write(base64, { encoding: "base64" });
62
+ return file.uri;
63
+ }
64
+ /**
65
+ * Content of a file as base64 (to embed it in a JSON backup), `null` when it
66
+ * can't be read — a photo the OS already cleared from its cache, a bad URI.
67
+ */
68
+ export function readFileBase64(uri) {
69
+ try {
70
+ return new File(uri).base64Sync();
71
+ }
72
+ catch {
73
+ return null;
74
+ }
75
+ }
76
+ /** Whether a file exists at `uri`; `false` for a malformed URI instead of throwing. */
77
+ export function fileExists(uri) {
78
+ try {
79
+ return new File(uri).exists;
80
+ }
81
+ catch {
82
+ return false;
83
+ }
84
+ }
85
+ /**
86
+ * Deletes a file if it is still there, best effort: an absent file or a failed
87
+ * deletion never makes the caller fail.
88
+ */
89
+ export function deleteFileQuietly(uri) {
90
+ if (!uri)
91
+ return;
92
+ try {
93
+ const file = new File(uri);
94
+ if (file.exists)
95
+ file.delete();
96
+ }
97
+ catch {
98
+ // Nothing to do: a leftover file is harmless.
99
+ }
100
+ }
101
+ /**
102
+ * Deletes every file of the persistent sub-folder that isn't in `keep`
103
+ * (replaced photo, deleted entity, data replaced by an import). Returns how
104
+ * many files were deleted.
105
+ *
106
+ * Files are matched by **name**, not by full URI: Android reaches the same
107
+ * file as `/data/user/0/<package>/…` or `/data/data/<package>/…` depending on
108
+ * the API that built the URI — compared as a whole, a stored URI in the other
109
+ * form would get its photo deleted.
110
+ */
111
+ export function pruneAppDirectory(name, keep) {
112
+ const kept = new Set(Array.from(keep, fileNameOf));
113
+ let deleted = 0;
114
+ for (const entry of getAppDirectory(name).list()) {
115
+ if (entry instanceof File && !kept.has(fileNameOf(entry.uri))) {
116
+ try {
117
+ entry.delete();
118
+ deleted += 1;
119
+ }
120
+ catch {
121
+ // Retried on the next prune.
122
+ }
123
+ }
124
+ }
125
+ return deleted;
126
+ }
@@ -0,0 +1,22 @@
1
+ import { type PersistFileOptions } from "./appFiles.js";
2
+ export interface SaveImageThumbnailOptions extends PersistFileOptions {
3
+ /** Width in pixels, height keeps the ratio. @defaultValue 256 */
4
+ width?: number;
5
+ /** JPEG quality, 0 to 1. @defaultValue 0.8 */
6
+ quality?: number;
7
+ }
8
+ /**
9
+ * Shrinks a picked photo to a JPEG thumbnail and keeps it in the app's
10
+ * persistent sub-folder (see `getAppDirectory`); returns its URI. Small
11
+ * enough to embed as base64 in a JSON backup (`readFileBase64`) and recreate
12
+ * on restore (`writeBase64File`). Needs `expo-image-manipulator` and
13
+ * `expo-file-system`.
14
+ *
15
+ * @example
16
+ * const avatarUri = await saveImageThumbnail(pickedUri, {
17
+ * directory: "avatars",
18
+ * prefix: "avatar",
19
+ * });
20
+ */
21
+ export declare function saveImageThumbnail(sourceUri: string, { width, quality, ...target }: SaveImageThumbnailOptions): Promise<string>;
22
+ //# sourceMappingURL=imageThumbnail.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imageThumbnail.d.ts","sourceRoot":"","sources":["../../../src/utils/files/imageThumbnail.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,kBAAkB,EAAmB,MAAM,eAAe,CAAC;AAEzE,MAAM,WAAW,yBAA0B,SAAQ,kBAAkB;IACnE,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,EAAE,KAAW,EAAE,OAAa,EAAE,GAAG,MAAM,EAAE,EAAE,yBAAyB,GACnE,OAAO,CAAC,MAAM,CAAC,CAWjB"}
@@ -0,0 +1,28 @@
1
+ import { ImageManipulator, SaveFormat } from "expo-image-manipulator";
2
+ import { writeBase64File } from "./appFiles.js";
3
+ /**
4
+ * Shrinks a picked photo to a JPEG thumbnail and keeps it in the app's
5
+ * persistent sub-folder (see `getAppDirectory`); returns its URI. Small
6
+ * enough to embed as base64 in a JSON backup (`readFileBase64`) and recreate
7
+ * on restore (`writeBase64File`). Needs `expo-image-manipulator` and
8
+ * `expo-file-system`.
9
+ *
10
+ * @example
11
+ * const avatarUri = await saveImageThumbnail(pickedUri, {
12
+ * directory: "avatars",
13
+ * prefix: "avatar",
14
+ * });
15
+ */
16
+ export async function saveImageThumbnail(sourceUri, { width = 256, quality = 0.8, ...target }) {
17
+ const image = await ImageManipulator.manipulate(sourceUri)
18
+ .resize({ width })
19
+ .renderAsync();
20
+ const result = await image.saveAsync({
21
+ base64: true,
22
+ compress: quality,
23
+ format: SaveFormat.JPEG,
24
+ });
25
+ if (!result.base64)
26
+ throw new Error("Empty image");
27
+ return writeBase64File(result.base64, { ...target, extension: "jpg" });
28
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./appFiles.js";
2
+ export * from "./imageThumbnail.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/files/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from "./appFiles.js";
2
+ export * from "./imageThumbnail.js";
@@ -0,0 +1,9 @@
1
+ /** Light tap — a button press or a stepper step. */
2
+ export declare function tapFeedback(): void;
3
+ /** Selection tick — picking an option or flipping a switch. */
4
+ export declare function selectFeedback(): void;
5
+ /** An action that succeeded (saved, drawn, sent…). */
6
+ export declare function successFeedback(): void;
7
+ /** An action that failed. */
8
+ export declare function errorFeedback(): void;
9
+ //# sourceMappingURL=haptics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"haptics.d.ts","sourceRoot":"","sources":["../../../src/utils/helpers/haptics.ts"],"names":[],"mappings":"AAMA,oDAAoD;AACpD,wBAAgB,WAAW,IAAI,IAAI,CAIlC;AAED,+DAA+D;AAC/D,wBAAgB,cAAc,IAAI,IAAI,CAIrC;AAED,sDAAsD;AACtD,wBAAgB,eAAe,IAAI,IAAI,CAMtC;AAED,6BAA6B;AAC7B,wBAAgB,aAAa,IAAI,IAAI,CAMpC"}
@@ -0,0 +1,28 @@
1
+ import * as Haptics from "expo-haptics";
2
+ // Semantic aliases around expo-haptics. Every call is fire-and-forget: a
3
+ // failed vibration (web, no motor, haptics off) must never fail the action it
4
+ // accompanies.
5
+ /** Light tap — a button press or a stepper step. */
6
+ export function tapFeedback() {
7
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light).catch(() => {
8
+ /* best effort */
9
+ });
10
+ }
11
+ /** Selection tick — picking an option or flipping a switch. */
12
+ export function selectFeedback() {
13
+ Haptics.selectionAsync().catch(() => {
14
+ /* best effort */
15
+ });
16
+ }
17
+ /** An action that succeeded (saved, drawn, sent…). */
18
+ export function successFeedback() {
19
+ Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success).catch(() => {
20
+ /* best effort */
21
+ });
22
+ }
23
+ /** An action that failed. */
24
+ export function errorFeedback() {
25
+ Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error).catch(() => {
26
+ /* best effort */
27
+ });
28
+ }
@@ -1,3 +1,8 @@
1
1
  export * from "./confirmDestructive.js";
2
+ export * from "./haptics.js";
3
+ export * from "./isNativeModuleAvailable.js";
2
4
  export * from "./mergeSlotStyles.js";
5
+ export * from "./shareFile.js";
6
+ export * from "./shareTextFile.js";
7
+ export * from "./shareViewAsImage.js";
3
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/helpers/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/helpers/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,cAAc,CAAC;AAC7B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC"}
@@ -1,2 +1,7 @@
1
1
  export * from "./confirmDestructive.js";
2
+ export * from "./haptics.js";
3
+ export * from "./isNativeModuleAvailable.js";
2
4
  export * from "./mergeSlotStyles.js";
5
+ export * from "./shareFile.js";
6
+ export * from "./shareTextFile.js";
7
+ export * from "./shareViewAsImage.js";
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Whether the native module `name` is compiled into this binary (new or old
3
+ * architecture). Check it before loading a library that requires its native
4
+ * module on import: on a binary built without it (an older dev build),
5
+ * importing it anyway crashes the whole screen instead of disabling the one
6
+ * feature that needs it.
7
+ *
8
+ * @example
9
+ * if (isNativeModuleAvailable("RNViewShot")) showShareAsImageButton();
10
+ */
11
+ export declare function isNativeModuleAvailable(name: string): boolean;
12
+ //# sourceMappingURL=isNativeModuleAvailable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isNativeModuleAvailable.d.ts","sourceRoot":"","sources":["../../../src/utils/helpers/isNativeModuleAvailable.ts"],"names":[],"mappings":"AAMA;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAK7D"}