@forthtilliath/react-native-kit 0.14.8 → 0.15.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 (103) hide show
  1. package/README.md +37 -17
  2. package/dist/components/index.d.ts +4 -4
  3. package/dist/components/index.d.ts.map +1 -1
  4. package/dist/components/index.js +4 -4
  5. package/dist/components/list/SwipeableRow.d.ts +14 -1
  6. package/dist/components/list/SwipeableRow.d.ts.map +1 -1
  7. package/dist/components/list/SwipeableRow.js +18 -16
  8. package/dist/components/list/Thumbnail.d.ts.map +1 -1
  9. package/dist/components/list/Thumbnail.js +2 -6
  10. package/dist/components/list/UndoToast.d.ts +10 -4
  11. package/dist/components/list/UndoToast.d.ts.map +1 -1
  12. package/dist/components/list/UndoToast.js +11 -8
  13. package/dist/components/list/index.d.ts +4 -4
  14. package/dist/components/list/index.d.ts.map +1 -1
  15. package/dist/components/list/index.js +4 -4
  16. package/dist/components/picker/PhotoPicker.d.ts +7 -1
  17. package/dist/components/picker/PhotoPicker.d.ts.map +1 -1
  18. package/dist/components/picker/PhotoPicker.js +33 -28
  19. package/dist/components/picker/PickerModal.d.ts +7 -1
  20. package/dist/components/picker/PickerModal.d.ts.map +1 -1
  21. package/dist/components/picker/PickerModal.js +8 -28
  22. package/dist/components/picker/PickerModal.styles.d.ts +18 -1
  23. package/dist/components/picker/PickerModal.styles.d.ts.map +1 -1
  24. package/dist/components/picker/PickerModal.styles.js +16 -6
  25. package/dist/components/picker/VoiceSearchButton.d.ts +13 -2
  26. package/dist/components/picker/VoiceSearchButton.d.ts.map +1 -1
  27. package/dist/components/picker/VoiceSearchButton.js +18 -1
  28. package/dist/components/picker/index.d.ts +3 -3
  29. package/dist/components/picker/index.d.ts.map +1 -1
  30. package/dist/components/picker/index.js +3 -3
  31. package/dist/components/settings/AboutSettingsScreen.d.ts +7 -1
  32. package/dist/components/settings/AboutSettingsScreen.d.ts.map +1 -1
  33. package/dist/components/settings/AboutSettingsScreen.js +13 -13
  34. package/dist/components/settings/BackupSettingsScreen.d.ts +9 -59
  35. package/dist/components/settings/BackupSettingsScreen.d.ts.map +1 -1
  36. package/dist/components/settings/BackupSettingsScreen.js +32 -141
  37. package/dist/components/settings/BackupSettingsScreen.styles.d.ts +173 -0
  38. package/dist/components/settings/BackupSettingsScreen.styles.d.ts.map +1 -0
  39. package/dist/components/settings/BackupSettingsScreen.styles.js +98 -0
  40. package/dist/components/settings/ContactSettingsScreen.d.ts +7 -1
  41. package/dist/components/settings/ContactSettingsScreen.d.ts.map +1 -1
  42. package/dist/components/settings/ContactSettingsScreen.js +15 -14
  43. package/dist/components/settings/PrivacySettingsScreen.d.ts +7 -1
  44. package/dist/components/settings/PrivacySettingsScreen.d.ts.map +1 -1
  45. package/dist/components/settings/PrivacySettingsScreen.js +50 -28
  46. package/dist/components/settings/SettingsMenu.d.ts.map +1 -1
  47. package/dist/components/settings/SettingsMenu.js +2 -9
  48. package/dist/components/settings/ThemeSettingsScreen.d.ts +7 -1
  49. package/dist/components/settings/ThemeSettingsScreen.d.ts.map +1 -1
  50. package/dist/components/settings/ThemeSettingsScreen.js +17 -19
  51. package/dist/components/settings/UpdateSettingsScreen.d.ts +11 -2
  52. package/dist/components/settings/UpdateSettingsScreen.d.ts.map +1 -1
  53. package/dist/components/settings/UpdateSettingsScreen.js +7 -31
  54. package/dist/components/settings/UpdateSettingsScreen.styles.d.ts +28 -1
  55. package/dist/components/settings/UpdateSettingsScreen.styles.d.ts.map +1 -1
  56. package/dist/components/settings/UpdateSettingsScreen.styles.js +26 -11
  57. package/dist/components/settings/index.d.ts +7 -7
  58. package/dist/components/settings/index.d.ts.map +1 -1
  59. package/dist/components/settings/index.js +7 -7
  60. package/dist/components/theme/ThemeOptionList.d.ts +7 -1
  61. package/dist/components/theme/ThemeOptionList.d.ts.map +1 -1
  62. package/dist/components/theme/ThemeOptionList.js +6 -17
  63. package/dist/components/theme/ThemeToggle.d.ts +7 -1
  64. package/dist/components/theme/ThemeToggle.d.ts.map +1 -1
  65. package/dist/components/theme/ThemeToggle.js +6 -20
  66. package/dist/components/theme/index.d.ts +2 -2
  67. package/dist/components/theme/index.d.ts.map +1 -1
  68. package/dist/components/theme/index.js +2 -2
  69. package/dist/components/theme/themeLabels.d.ts +14 -0
  70. package/dist/components/theme/themeLabels.d.ts.map +1 -0
  71. package/dist/components/theme/themeLabels.js +5 -0
  72. package/dist/hooks/index.d.ts +3 -3
  73. package/dist/hooks/index.d.ts.map +1 -1
  74. package/dist/hooks/index.js +3 -3
  75. package/dist/hooks/useDebouncedChange.d.ts.map +1 -1
  76. package/dist/hooks/useDebouncedChange.js +6 -7
  77. package/dist/hooks/useSubmitGuard.d.ts.map +1 -1
  78. package/dist/hooks/useSubmitGuard.js +9 -5
  79. package/dist/i18n/KitLocaleProvider.d.ts +19 -0
  80. package/dist/i18n/KitLocaleProvider.d.ts.map +1 -0
  81. package/dist/i18n/KitLocaleProvider.js +16 -0
  82. package/dist/i18n/index.d.ts +3 -0
  83. package/dist/i18n/index.d.ts.map +1 -0
  84. package/dist/i18n/index.js +2 -0
  85. package/dist/i18n/locale.d.ts +14 -0
  86. package/dist/i18n/locale.d.ts.map +1 -0
  87. package/dist/i18n/locale.js +18 -0
  88. package/dist/index.d.ts +5 -2
  89. package/dist/index.d.ts.map +1 -1
  90. package/dist/index.js +5 -2
  91. package/dist/utils/helpers/confirmDestructive.d.ts +6 -0
  92. package/dist/utils/helpers/confirmDestructive.d.ts.map +1 -1
  93. package/dist/utils/helpers/confirmDestructive.js +20 -6
  94. package/dist/utils/helpers/index.d.ts +1 -0
  95. package/dist/utils/helpers/index.d.ts.map +1 -1
  96. package/dist/utils/helpers/index.js +1 -0
  97. package/dist/utils/helpers/mergeSlotStyles.d.ts +20 -0
  98. package/dist/utils/helpers/mergeSlotStyles.d.ts.map +1 -0
  99. package/dist/utils/helpers/mergeSlotStyles.js +26 -0
  100. package/dist/utils/index.d.ts +1 -1
  101. package/dist/utils/index.d.ts.map +1 -1
  102. package/dist/utils/index.js +1 -1
  103. package/package.json +14 -10
@@ -28,5 +28,22 @@ export interface PickerModalLabels {
28
28
  otherGroupLabel?: string;
29
29
  }
30
30
  export declare const defaultStyles: Required<PickerModalStyles>;
31
- export declare const defaultLabels: Required<PickerModalLabels>;
31
+ export declare const defaultLabels: {
32
+ fr: {
33
+ close: string;
34
+ searchPlaceholder: string;
35
+ searchAccessibilityLabel: string;
36
+ voiceSearchAccessibilityLabel: string;
37
+ defaultEmptyMessage: string;
38
+ otherGroupLabel: string;
39
+ };
40
+ en: {
41
+ close: string;
42
+ searchPlaceholder: string;
43
+ searchAccessibilityLabel: string;
44
+ voiceSearchAccessibilityLabel: string;
45
+ defaultEmptyMessage: string;
46
+ otherGroupLabel: string;
47
+ };
48
+ };
32
49
  //# sourceMappingURL=PickerModal.styles.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PickerModal.styles.d.ts","sourceRoot":"","sources":["../../../src/components/picker/PickerModal.styles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEhF,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC9B,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC9B,GAAG,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC3B,YAAY,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IACrC,uBAAuB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC/C,QAAQ,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAChC,WAAW,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACnC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,aAAa,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACrC,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC,gBAAgB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACxC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,6BAA6B,CAAC,EAAE,MAAM,CAAC;IACvC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,iBAAiB,CAyErD,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,iBAAiB,CAOrD,CAAC"}
1
+ {"version":3,"file":"PickerModal.styles.d.ts","sourceRoot":"","sources":["../../../src/components/picker/PickerModal.styles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAIhF,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC9B,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC9B,GAAG,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC3B,YAAY,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IACrC,uBAAuB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC/C,QAAQ,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAChC,WAAW,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACnC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,aAAa,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACrC,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC,gBAAgB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACxC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,6BAA6B,CAAC,EAAE,MAAM,CAAC;IACvC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,iBAAiB,CAyErD,CAAC;AAEF,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;CAiBgC,CAAC"}
@@ -73,10 +73,20 @@ export const defaultStyles = {
73
73
  placeholderTextColor: "#6b7280",
74
74
  };
75
75
  export const defaultLabels = {
76
- close: "Fermer",
77
- searchPlaceholder: "Rechercher…",
78
- searchAccessibilityLabel: "Rechercher",
79
- voiceSearchAccessibilityLabel: "Dicter la recherche",
80
- defaultEmptyMessage: "Aucun résultat.",
81
- otherGroupLabel: "Autres",
76
+ fr: {
77
+ close: "Fermer",
78
+ searchPlaceholder: "Rechercher…",
79
+ searchAccessibilityLabel: "Rechercher",
80
+ voiceSearchAccessibilityLabel: "Dicter la recherche",
81
+ defaultEmptyMessage: "Aucun résultat.",
82
+ otherGroupLabel: "Autres",
83
+ },
84
+ en: {
85
+ close: "Close",
86
+ searchPlaceholder: "Search…",
87
+ searchAccessibilityLabel: "Search",
88
+ voiceSearchAccessibilityLabel: "Dictate the search",
89
+ defaultEmptyMessage: "No results.",
90
+ otherGroupLabel: "Other",
91
+ },
82
92
  };
@@ -1,14 +1,25 @@
1
+ import { type KitLocale } from "../../i18n/locale.js";
1
2
  export interface VoiceSearchButtonStyles {
2
3
  iconColor?: string;
3
4
  iconColorActive?: string;
4
5
  }
5
6
  export interface VoiceSearchButtonProps {
6
7
  onResult: (transcript: string) => void;
8
+ /** Defaults to "Recherche vocale" (`"Voice search"` with `locale="en"`). */
7
9
  accessibilityLabel?: string;
10
+ /** Defaults to "Arrêter la recherche vocale" (`"Stop voice search"` with `locale="en"`). */
8
11
  stopAccessibilityLabel?: string;
9
- /** BCP 47 locale passed to the speech recognizer. */
12
+ /**
13
+ * BCP 47 language passed to the speech recognizer. Defaults to the
14
+ * locale's (`"fr-FR"`, or `"en-US"` with `locale="en"`).
15
+ */
10
16
  lang?: string;
17
+ /**
18
+ * Language of the default labels and speech recognition — French by
19
+ * default, or the nearest `KitLocaleProvider`'s.
20
+ */
21
+ locale?: KitLocale;
11
22
  styles?: VoiceSearchButtonStyles;
12
23
  }
13
- export declare function VoiceSearchButton({ onResult, accessibilityLabel, stopAccessibilityLabel, lang, styles, }: VoiceSearchButtonProps): import("react").JSX.Element;
24
+ export declare function VoiceSearchButton({ onResult, accessibilityLabel: customAccessibilityLabel, stopAccessibilityLabel: customStopAccessibilityLabel, lang: customLang, locale, styles, }: VoiceSearchButtonProps): import("react").JSX.Element;
14
25
  //# sourceMappingURL=VoiceSearchButton.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"VoiceSearchButton.d.ts","sourceRoot":"","sources":["../../../src/components/picker/VoiceSearchButton.tsx"],"names":[],"mappings":"AAQA,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,uBAAuB,CAAC;CAClC;AAaD,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,kBAAmC,EACnC,sBAA4C,EAC5C,IAAc,EACd,MAAM,GACP,EAAE,sBAAsB,+BAwDxB"}
1
+ {"version":3,"file":"VoiceSearchButton.d.ts","sourceRoot":"","sources":["../../../src/components/picker/VoiceSearchButton.tsx"],"names":[],"mappings":"AAQA,OAAO,EAEL,KAAK,SAAS,EAEf,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,4FAA4F;IAC5F,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,MAAM,CAAC,EAAE,uBAAuB,CAAC;CAClC;AAwBD,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,kBAAkB,EAAE,wBAAwB,EAC5C,sBAAsB,EAAE,4BAA4B,EACpD,IAAI,EAAE,UAAU,EAChB,MAAM,EACN,MAAM,GACP,EAAE,sBAAsB,+BAgExB"}
@@ -3,6 +3,17 @@ import { useRef, useState } from "react";
3
3
  import { Pressable } from "react-native";
4
4
  import { Ionicons } from "@expo/vector-icons";
5
5
  import { ExpoSpeechRecognitionModule, useSpeechRecognitionEvent, } from "expo-speech-recognition";
6
+ import { KIT_LOCALE_TAGS, useKitLocale, } from "../../i18n/locale.js";
7
+ const defaultLabels = {
8
+ fr: {
9
+ accessibilityLabel: "Recherche vocale",
10
+ stopAccessibilityLabel: "Arrêter la recherche vocale",
11
+ },
12
+ en: {
13
+ accessibilityLabel: "Voice search",
14
+ stopAccessibilityLabel: "Stop voice search",
15
+ },
16
+ };
6
17
  const defaultStyles = {
7
18
  iconColor: "#2563eb",
8
19
  iconColorActive: "#dc2626",
@@ -13,7 +24,13 @@ const defaultStyles = {
13
24
  // search picker on the same screen). `requestedRef` distinguishes the button
14
25
  // that started THIS session from other mounted instances, so only it reacts
15
26
  // to the result instead of all of them.
16
- export function VoiceSearchButton({ onResult, accessibilityLabel = "Voice search", stopAccessibilityLabel = "Stop voice search", lang = "en-US", styles, }) {
27
+ export function VoiceSearchButton({ onResult, accessibilityLabel: customAccessibilityLabel, stopAccessibilityLabel: customStopAccessibilityLabel, lang: customLang, locale, styles, }) {
28
+ const resolvedLocale = useKitLocale(locale);
29
+ const accessibilityLabel = customAccessibilityLabel ??
30
+ defaultLabels[resolvedLocale].accessibilityLabel;
31
+ const stopAccessibilityLabel = customStopAccessibilityLabel ??
32
+ defaultLabels[resolvedLocale].stopAccessibilityLabel;
33
+ const lang = customLang ?? KIT_LOCALE_TAGS[resolvedLocale];
17
34
  const merged = { ...defaultStyles, ...styles };
18
35
  const [isListening, setIsListening] = useState(false);
19
36
  const requestedRef = useRef(false);
@@ -1,4 +1,4 @@
1
- export * from "./PhotoPicker";
2
- export * from "./PickerModal";
3
- export * from "./VoiceSearchButton";
1
+ export * from "./PhotoPicker.js";
2
+ export * from "./PickerModal.js";
3
+ export * from "./VoiceSearchButton.js";
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/picker/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/picker/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC"}
@@ -1,3 +1,3 @@
1
- export * from "./PhotoPicker";
2
- export * from "./PickerModal";
3
- export * from "./VoiceSearchButton";
1
+ export * from "./PhotoPicker.js";
2
+ export * from "./PickerModal.js";
3
+ export * from "./VoiceSearchButton.js";
@@ -1,4 +1,5 @@
1
1
  import type { StyleProp, TextStyle, ViewStyle } from "react-native";
2
+ import { type KitLocale } from "../../i18n/locale.js";
2
3
  export interface AboutSettingsScreenSection {
3
4
  title: string;
4
5
  paragraphs: string[];
@@ -26,7 +27,12 @@ export interface AboutSettingsScreenProps {
26
27
  /** Omit to not show a "developed by" credit line at all. */
27
28
  developerName?: string;
28
29
  labels?: AboutSettingsScreenLabels;
30
+ /**
31
+ * Language of the built-in labels — French by default, or the nearest
32
+ * `KitLocaleProvider`'s. `labels` still overrides individual strings.
33
+ */
34
+ locale?: KitLocale;
29
35
  styles?: AboutSettingsScreenStyles;
30
36
  }
31
- export declare function AboutSettingsScreen({ appName, version, description, sections, developerName, labels, styles, }: AboutSettingsScreenProps): import("react").JSX.Element;
37
+ export declare function AboutSettingsScreen({ appName, version, description, sections, developerName, labels, locale, styles, }: AboutSettingsScreenProps): import("react").JSX.Element;
32
38
  //# sourceMappingURL=AboutSettingsScreen.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AboutSettingsScreen.d.ts","sourceRoot":"","sources":["../../../src/components/settings/AboutSettingsScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGpE,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,yBAAyB;IACxC,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC/B,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC,IAAI,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACxC;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC/B,oFAAoF;IACpF,QAAQ,CAAC,EAAE,0BAA0B,EAAE,CAAC;IACxC,4DAA4D;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,yBAAyB,CAAC;IACnC,MAAM,CAAC,EAAE,yBAAyB,CAAC;CACpC;AAqCD,wBAAgB,mBAAmB,CAAC,EAClC,OAAO,EACP,OAAO,EACP,WAAW,EACX,QAAQ,EACR,aAAa,EACb,MAAM,EACN,MAAM,GACP,EAAE,wBAAwB,+BA8C1B"}
1
+ {"version":3,"file":"AboutSettingsScreen.d.ts","sourceRoot":"","sources":["../../../src/components/settings/AboutSettingsScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGpE,OAAO,EAAE,KAAK,SAAS,EAAgB,MAAM,sBAAsB,CAAC;AAGpE,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,yBAAyB;IACxC,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC/B,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC,IAAI,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACxC;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC/B,oFAAoF;IACpF,QAAQ,CAAC,EAAE,0BAA0B,EAAE,CAAC;IACxC,4DAA4D;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,yBAAyB,CAAC;IACnC;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,MAAM,CAAC,EAAE,yBAAyB,CAAC;CACpC;AA2CD,wBAAgB,mBAAmB,CAAC,EAClC,OAAO,EACP,OAAO,EACP,WAAW,EACX,QAAQ,EACR,aAAa,EACb,MAAM,EACN,MAAM,EACN,MAAM,GACP,EAAE,wBAAwB,+BAsC1B"}
@@ -1,8 +1,16 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { Text, View } from "react-native";
3
+ import { useKitLocale } from "../../i18n/locale.js";
4
+ import { mergeSlotStyles } from "../../utils/helpers/mergeSlotStyles.js";
3
5
  const defaultLabels = {
4
- version: (version) => `Version ${version}`,
5
- developedBy: (name) => `Développée par ${name}.`,
6
+ fr: {
7
+ version: (version) => `Version ${version}`,
8
+ developedBy: (name) => `Développée par ${name}.`,
9
+ },
10
+ en: {
11
+ version: (version) => `Version ${version}`,
12
+ developedBy: (name) => `Developed by ${name}.`,
13
+ },
6
14
  };
7
15
  const defaultStyles = {
8
16
  container: {},
@@ -33,17 +41,9 @@ const defaultStyles = {
33
41
  // required rather than defaulted from `expo-constants` so this stays
34
42
  // framework-agnostic; pass `Constants.expoConfig?.name`/`.version` from the
35
43
  // caller.
36
- export function AboutSettingsScreen({ appName, version, description, sections, developerName, labels, styles, }) {
37
- const merged = {
38
- container: [defaultStyles.container, styles?.container],
39
- appName: [defaultStyles.appName, styles?.appName],
40
- version: [defaultStyles.version, styles?.version],
41
- separator: [defaultStyles.separator, styles?.separator],
42
- paragraph: [defaultStyles.paragraph, styles?.paragraph],
43
- sectionTitle: [defaultStyles.sectionTitle, styles?.sectionTitle],
44
- hint: [defaultStyles.hint, styles?.hint],
45
- };
46
- const t = { ...defaultLabels, ...labels };
44
+ export function AboutSettingsScreen({ appName, version, description, sections, developerName, labels, locale, styles, }) {
45
+ const merged = mergeSlotStyles(defaultStyles, styles);
46
+ const t = { ...defaultLabels[useKitLocale(locale)], ...labels };
47
47
  const paragraphs = Array.isArray(description) ? description : [description];
48
48
  return (_jsxs(View, { style: merged.container, children: [_jsx(Text, { style: merged.appName, children: appName }), _jsx(Text, { style: merged.version, children: t.version(version) }), _jsx(View, { style: merged.separator }), paragraphs.map((paragraph) => (_jsx(Text, { style: merged.paragraph, children: paragraph }, paragraph))), sections?.map((section) => (_jsxs(View, { children: [_jsx(View, { style: merged.separator }), _jsx(Text, { style: merged.sectionTitle, children: section.title }), section.paragraphs.map((paragraph) => (_jsx(Text, { style: merged.paragraph, children: paragraph }, paragraph)))] }, section.title))), developerName && (_jsxs(_Fragment, { children: [_jsx(View, { style: merged.separator }), _jsx(Text, { style: merged.hint, children: t.developedBy(developerName) })] }))] }));
49
49
  }
@@ -1,61 +1,6 @@
1
- import type { StyleProp, TextStyle, ViewStyle } from "react-native";
2
- import { Ionicons } from "@expo/vector-icons";
3
- export interface BackupSettingsScreenReminder {
4
- enabled: boolean;
5
- /** Set while a permission request or the toggle's own persistence is in flight. */
6
- busy?: boolean;
7
- onToggle: (value: boolean) => void;
8
- /** How often the reminder fires, only used to word the hint (e.g. "every 7 days"). */
9
- intervalDays: number;
10
- }
11
- export interface BackupSettingsScreenInfo {
12
- label: string;
13
- value: string;
14
- }
15
- export interface BackupSettingsScreenIcons {
16
- export?: keyof typeof Ionicons.glyphMap;
17
- import?: keyof typeof Ionicons.glyphMap;
18
- }
19
- export interface BackupSettingsScreenStyles {
20
- container?: StyleProp<ViewStyle>;
21
- infoBox?: StyleProp<ViewStyle>;
22
- infoLabel?: StyleProp<TextStyle>;
23
- infoValue?: StyleProp<TextStyle>;
24
- sectionTitle?: StyleProp<TextStyle>;
25
- hint?: StyleProp<TextStyle>;
26
- row?: StyleProp<ViewStyle>;
27
- button?: StyleProp<ViewStyle>;
28
- buttonDisabled?: StyleProp<ViewStyle>;
29
- buttonText?: StyleProp<TextStyle>;
30
- iconColor?: string;
31
- /** Merged on top of `button`/`buttonText` — defaults to the same look as the export button. */
32
- importButton?: StyleProp<ViewStyle>;
33
- importButtonText?: StyleProp<TextStyle>;
34
- reminderRow?: StyleProp<ViewStyle>;
35
- reminderTextColumn?: StyleProp<ViewStyle>;
36
- reminderLabel?: StyleProp<TextStyle>;
37
- reminderHint?: StyleProp<TextStyle>;
38
- activityIndicatorColor?: string;
39
- }
40
- export interface BackupSettingsScreenLabels {
41
- hint?: string;
42
- exportButton?: string;
43
- importButton?: string;
44
- /** Only shown in `layout="sections"`. */
45
- exportSectionTitle?: string;
46
- exportHelpText?: string;
47
- importSectionTitle?: string;
48
- importHelpText?: string;
49
- importConfirmTitle?: string;
50
- importConfirmMessage?: string;
51
- importConfirmLabel?: string;
52
- importConfirmCancelLabel?: string;
53
- reminderLabel?: string;
54
- reminderHint?: (intervalDays: number) => string;
55
- exportErrorTitle?: string;
56
- importErrorTitle?: string;
57
- genericErrorMessage?: string;
58
- }
1
+ import { type KitLocale } from "../../i18n/locale.js";
2
+ import { type BackupSettingsScreenIcons, type BackupSettingsScreenInfo, type BackupSettingsScreenLabels, type BackupSettingsScreenReminder, type BackupSettingsScreenStyles } from "./BackupSettingsScreen.styles.js";
3
+ export type { BackupSettingsScreenIcons, BackupSettingsScreenInfo, BackupSettingsScreenLabels, BackupSettingsScreenReminder, BackupSettingsScreenStyles, } from "./BackupSettingsScreen.styles.js";
59
4
  export interface BackupSettingsScreenProps {
60
5
  /** Exports/shares the app's data however it sees fit (e.g. a JSON file via the native share sheet). */
61
6
  onExport: () => Promise<void>;
@@ -78,7 +23,12 @@ export interface BackupSettingsScreenProps {
78
23
  /** Leading icon for each button. Omit either (or both) for a text-only button (default). */
79
24
  icons?: BackupSettingsScreenIcons;
80
25
  labels?: BackupSettingsScreenLabels;
26
+ /**
27
+ * Language of the built-in labels — French by default, or the nearest
28
+ * `KitLocaleProvider`'s. `labels` still overrides individual strings.
29
+ */
30
+ locale?: KitLocale;
81
31
  styles?: BackupSettingsScreenStyles;
82
32
  }
83
- export declare function BackupSettingsScreen({ onExport, onImport, reminder, info, layout, icons, labels, styles, }: BackupSettingsScreenProps): import("react").JSX.Element;
33
+ export declare function BackupSettingsScreen({ onExport, onImport, reminder, info, layout, icons, labels, locale, styles, }: BackupSettingsScreenProps): import("react").JSX.Element;
84
34
  //# sourceMappingURL=BackupSettingsScreen.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"BackupSettingsScreen.d.ts","sourceRoot":"","sources":["../../../src/components/settings/BackupSettingsScreen.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AASpE,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAI9C,MAAM,WAAW,4BAA4B;IAC3C,OAAO,EAAE,OAAO,CAAC;IACjB,mFAAmF;IACnF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,sFAAsF;IACtF,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,yBAAyB;IACxC,MAAM,CAAC,EAAE,MAAM,OAAO,QAAQ,CAAC,QAAQ,CAAC;IACxC,MAAM,CAAC,EAAE,MAAM,OAAO,QAAQ,CAAC,QAAQ,CAAC;CACzC;AAED,MAAM,WAAW,0BAA0B;IACzC,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC/B,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC,IAAI,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC5B,GAAG,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC3B,MAAM,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC9B,cAAc,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACtC,UAAU,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+FAA+F;IAC/F,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC,gBAAgB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACxC,WAAW,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACnC,kBAAkB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC1C,aAAa,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACrC,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,0BAA0B;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC;IAChD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,yBAAyB;IACxC,uGAAuG;IACvG,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,4BAA4B,CAAC;IACxC,6FAA6F;IAC7F,IAAI,CAAC,EAAE,wBAAwB,CAAC;IAChC;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IAChC,4FAA4F;IAC5F,KAAK,CAAC,EAAE,yBAAyB,CAAC;IAClC,MAAM,CAAC,EAAE,0BAA0B,CAAC;IACpC,MAAM,CAAC,EAAE,0BAA0B,CAAC;CACrC;AAyGD,wBAAgB,oBAAoB,CAAC,EACnC,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,MAAkB,EAClB,KAAK,EACL,MAAM,EACN,MAAM,GACP,EAAE,yBAAyB,+BAqL3B"}
1
+ {"version":3,"file":"BackupSettingsScreen.d.ts","sourceRoot":"","sources":["../../../src/components/settings/BackupSettingsScreen.tsx"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,SAAS,EAAgB,MAAM,sBAAsB,CAAC;AAIpE,OAAO,EACL,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,EACjC,KAAK,0BAA0B,EAIhC,MAAM,kCAAkC,CAAC;AAE1C,YAAY,EACV,yBAAyB,EACzB,wBAAwB,EACxB,0BAA0B,EAC1B,4BAA4B,EAC5B,0BAA0B,GAC3B,MAAM,kCAAkC,CAAC;AAE1C,MAAM,WAAW,yBAAyB;IACxC,uGAAuG;IACvG,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,4BAA4B,CAAC;IACxC,6FAA6F;IAC7F,IAAI,CAAC,EAAE,wBAAwB,CAAC;IAChC;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IAChC,4FAA4F;IAC5F,KAAK,CAAC,EAAE,yBAAyB,CAAC;IAClC,MAAM,CAAC,EAAE,0BAA0B,CAAC;IACpC;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,MAAM,CAAC,EAAE,0BAA0B,CAAC;CACrC;AAWD,wBAAgB,oBAAoB,CAAC,EACnC,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,MAAkB,EAClB,KAAK,EACL,MAAM,EACN,MAAM,EACN,MAAM,GACP,EAAE,yBAAyB,+BAwJ3B"}
@@ -1,85 +1,11 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState } from "react";
3
2
  import { ActivityIndicator, Alert, Pressable, Switch, Text, View, } from "react-native";
4
3
  import { Ionicons } from "@expo/vector-icons";
4
+ import { useSubmitGuard } from "../../hooks/useSubmitGuard.js";
5
+ import { useKitLocale } from "../../i18n/locale.js";
5
6
  import { confirmDestructive } from "../../utils/helpers/confirmDestructive.js";
6
- const defaultLabels = {
7
- hint: "Les données sont stockées uniquement sur cet appareil et sont perdues en cas de réinstallation ou de mise à jour incompatible. Exporte-les régulièrement pour pouvoir les restaurer.",
8
- exportButton: "⬆️ Exporter",
9
- importButton: "⬇️ Importer",
10
- exportSectionTitle: "Exporter",
11
- exportHelpText: "Exporte toutes tes données dans un fichier que tu peux garder précieusement ou transférer vers un autre appareil.",
12
- importSectionTitle: "Importer",
13
- importHelpText: "Restaure une sauvegarde exportée précédemment. Remplace entièrement les données actuelles — il n'y a pas de fusion.",
14
- importConfirmTitle: "Importer une sauvegarde ?",
15
- importConfirmMessage: "Toutes les données actuelles seront remplacées par celles du fichier choisi.",
16
- importConfirmLabel: "Choisir un fichier",
17
- importConfirmCancelLabel: "Annuler",
18
- reminderLabel: "🔔 Rappel de sauvegarde",
19
- reminderHint: undefined,
20
- exportErrorTitle: "Échec de l'export",
21
- importErrorTitle: "Échec de l'import",
22
- genericErrorMessage: "Une erreur inconnue s'est produite.",
23
- };
24
- const defaultStyles = {
25
- container: {},
26
- infoBox: {
27
- backgroundColor: "#f9fafb",
28
- borderWidth: 1,
29
- borderColor: "#e5e7eb",
30
- borderRadius: 10,
31
- padding: 12,
32
- marginBottom: 20,
33
- gap: 2,
34
- },
35
- infoLabel: { fontSize: 12, color: "#6b7280" },
36
- infoValue: { fontSize: 12, color: "#111827", fontWeight: "600" },
37
- sectionTitle: {
38
- fontSize: 15,
39
- fontWeight: "700",
40
- color: "#111827",
41
- marginTop: 20,
42
- },
43
- hint: {
44
- fontSize: 13,
45
- color: "#6b7280",
46
- marginTop: 6,
47
- marginBottom: 14,
48
- lineHeight: 18,
49
- },
50
- row: { flexDirection: "row", gap: 10 },
51
- button: {
52
- flexDirection: "row",
53
- flex: 1,
54
- paddingVertical: 12,
55
- borderRadius: 8,
56
- borderWidth: 1,
57
- borderColor: "#2563eb",
58
- alignItems: "center",
59
- justifyContent: "center",
60
- gap: 8,
61
- },
62
- buttonDisabled: { opacity: 0.5 },
63
- buttonText: { color: "#2563eb", fontWeight: "700" },
64
- iconColor: "#2563eb",
65
- importButton: undefined,
66
- importButtonText: undefined,
67
- reminderRow: {
68
- flexDirection: "row",
69
- alignItems: "center",
70
- gap: 12,
71
- marginTop: 24,
72
- },
73
- reminderTextColumn: { flex: 1 },
74
- reminderLabel: {
75
- fontSize: 15,
76
- fontWeight: "600",
77
- color: "#111827",
78
- marginBottom: 4,
79
- },
80
- reminderHint: { fontSize: 13, color: "#6b7280" },
81
- activityIndicatorColor: undefined,
82
- };
7
+ import { mergeSlotStyles } from "../../utils/helpers/mergeSlotStyles.js";
8
+ import { defaultIconColor, defaultLabels, defaultStyles, } from "./BackupSettingsScreen.styles.js";
83
9
  function errorMessage(err, fallback) {
84
10
  return err instanceof Error ? err.message : fallback;
85
11
  }
@@ -88,85 +14,50 @@ function errorMessage(err, fallback) {
88
14
  // what gets exported/imported is entirely app-specific (its own database
89
15
  // tables), so `onExport`/`onImport` are required props, not something this
90
16
  // package could have a sensible default for.
91
- export function BackupSettingsScreen({ onExport, onImport, reminder, info, layout = "compact", icons, labels, styles, }) {
92
- const [exporting, setExporting] = useState(false);
93
- const [importing, setImporting] = useState(false);
94
- const merged = {
95
- container: [defaultStyles.container, styles?.container],
96
- infoBox: [defaultStyles.infoBox, styles?.infoBox],
97
- infoLabel: [defaultStyles.infoLabel, styles?.infoLabel],
98
- infoValue: [defaultStyles.infoValue, styles?.infoValue],
99
- sectionTitle: [defaultStyles.sectionTitle, styles?.sectionTitle],
100
- hint: [defaultStyles.hint, styles?.hint],
101
- row: [defaultStyles.row, styles?.row],
102
- button: [defaultStyles.button, styles?.button],
103
- buttonDisabled: [defaultStyles.buttonDisabled, styles?.buttonDisabled],
104
- buttonText: [defaultStyles.buttonText, styles?.buttonText],
105
- importButton: [
106
- defaultStyles.button,
107
- styles?.button,
108
- defaultStyles.importButton,
109
- styles?.importButton,
110
- ],
111
- importButtonText: [
112
- defaultStyles.buttonText,
113
- styles?.buttonText,
114
- defaultStyles.importButtonText,
115
- styles?.importButtonText,
116
- ],
117
- reminderRow: [defaultStyles.reminderRow, styles?.reminderRow],
118
- reminderTextColumn: [
119
- defaultStyles.reminderTextColumn,
120
- styles?.reminderTextColumn,
121
- ],
122
- reminderLabel: [defaultStyles.reminderLabel, styles?.reminderLabel],
123
- reminderHint: [defaultStyles.reminderHint, styles?.reminderHint],
124
- };
125
- const t = { ...defaultLabels, ...labels };
126
- const activityIndicatorColor = styles?.activityIndicatorColor ?? defaultStyles.activityIndicatorColor;
127
- const iconColor = styles?.iconColor ?? defaultStyles.iconColor;
128
- async function handleExport() {
129
- if (exporting)
130
- return;
131
- setExporting(true);
132
- try {
133
- await onExport();
134
- }
135
- catch (err) {
136
- Alert.alert(t.exportErrorTitle, errorMessage(err, t.genericErrorMessage));
137
- }
138
- finally {
139
- setExporting(false);
140
- }
17
+ export function BackupSettingsScreen({ onExport, onImport, reminder, info, layout = "compact", icons, labels, locale, styles, }) {
18
+ // Guards rather than a plain `if (busy) return`: two taps before the
19
+ // re-render would both see the stale "not busy" state and run twice.
20
+ const exportGuard = useSubmitGuard();
21
+ const importGuard = useSubmitGuard();
22
+ const merged = mergeSlotStyles(defaultStyles, styles);
23
+ const importButtonStyle = [merged.button, styles?.importButton];
24
+ const importButtonTextStyle = [merged.buttonText, styles?.importButtonText];
25
+ const t = { ...defaultLabels[useKitLocale(locale)], ...labels };
26
+ const activityIndicatorColor = styles?.activityIndicatorColor;
27
+ const iconColor = styles?.iconColor ?? defaultIconColor;
28
+ function handleExport() {
29
+ void exportGuard.guard(async () => {
30
+ try {
31
+ await onExport();
32
+ }
33
+ catch (err) {
34
+ Alert.alert(t.exportErrorTitle, errorMessage(err, t.genericErrorMessage));
35
+ }
36
+ });
141
37
  }
142
38
  function handleImportPress() {
143
- if (importing)
39
+ if (importGuard.isSaving)
144
40
  return;
145
41
  confirmDestructive(t.importConfirmTitle, () => {
146
- void (async () => {
147
- setImporting(true);
42
+ void importGuard.guard(async () => {
148
43
  try {
149
44
  await onImport();
150
45
  }
151
46
  catch (err) {
152
47
  Alert.alert(t.importErrorTitle, errorMessage(err, t.genericErrorMessage));
153
48
  }
154
- finally {
155
- setImporting(false);
156
- }
157
- })();
49
+ });
158
50
  }, {
159
51
  message: t.importConfirmMessage,
160
52
  cancelLabel: t.importConfirmCancelLabel,
161
53
  confirmLabel: t.importConfirmLabel,
162
54
  });
163
55
  }
164
- const exportButton = (_jsx(Pressable, { style: [merged.button, exporting && merged.buttonDisabled], disabled: exporting, onPress: () => {
165
- void handleExport();
166
- }, accessibilityRole: "button", accessibilityLabel: t.exportButton, children: exporting ? (_jsx(ActivityIndicator, { color: activityIndicatorColor })) : (_jsxs(_Fragment, { children: [icons?.export && (_jsx(Ionicons, { name: icons.export, size: 18, color: iconColor })), _jsx(Text, { style: merged.buttonText, children: t.exportButton })] })) }));
167
- const importButton = (_jsx(Pressable, { style: [merged.importButton, importing && merged.buttonDisabled], disabled: importing, onPress: handleImportPress, accessibilityRole: "button", accessibilityLabel: t.importButton, children: importing ? (_jsx(ActivityIndicator, { color: activityIndicatorColor })) : (_jsxs(_Fragment, { children: [icons?.import && (_jsx(Ionicons, { name: icons.import, size: 18, color: iconColor })), _jsx(Text, { style: merged.importButtonText, children: t.importButton })] })) }));
56
+ const exporting = exportGuard.isSaving;
57
+ const importing = importGuard.isSaving;
58
+ const exportButton = (_jsx(Pressable, { style: [merged.button, exporting && merged.buttonDisabled], disabled: exporting, onPress: handleExport, accessibilityRole: "button", accessibilityLabel: t.exportButton, children: exporting ? (_jsx(ActivityIndicator, { color: activityIndicatorColor })) : (_jsxs(_Fragment, { children: [icons?.export && (_jsx(Ionicons, { name: icons.export, size: 18, color: iconColor })), _jsx(Text, { style: merged.buttonText, children: t.exportButton })] })) }));
59
+ const importButton = (_jsx(Pressable, { style: [importButtonStyle, importing && merged.buttonDisabled], disabled: importing, onPress: handleImportPress, accessibilityRole: "button", accessibilityLabel: t.importButton, children: importing ? (_jsx(ActivityIndicator, { color: activityIndicatorColor })) : (_jsxs(_Fragment, { children: [icons?.import && (_jsx(Ionicons, { name: icons.import, size: 18, color: iconColor })), _jsx(Text, { style: importButtonTextStyle, children: t.importButton })] })) }));
168
60
  return (_jsxs(View, { style: merged.container, children: [info && (_jsxs(View, { style: merged.infoBox, children: [_jsx(Text, { style: merged.infoLabel, children: info.label }), _jsx(Text, { style: merged.infoValue, children: info.value })] })), layout === "sections" ? (_jsxs(_Fragment, { children: [_jsx(Text, { style: merged.sectionTitle, children: t.exportSectionTitle }), _jsx(Text, { style: merged.hint, children: t.exportHelpText }), exportButton, _jsx(Text, { style: merged.sectionTitle, children: t.importSectionTitle }), _jsx(Text, { style: merged.hint, children: t.importHelpText }), importButton] })) : (_jsxs(_Fragment, { children: [_jsx(Text, { style: merged.hint, children: t.hint }), _jsxs(View, { style: merged.row, children: [exportButton, importButton] })] })), reminder && (_jsxs(Pressable, { style: merged.reminderRow, disabled: reminder.busy, onPress: () => {
169
61
  reminder.onToggle(!reminder.enabled);
170
- }, accessibilityRole: "switch", accessibilityState: { checked: reminder.enabled }, accessibilityLabel: t.reminderLabel, children: [_jsxs(View, { style: merged.reminderTextColumn, children: [_jsx(Text, { style: merged.reminderLabel, children: t.reminderLabel }), _jsx(Text, { style: merged.reminderHint, children: t.reminderHint?.(reminder.intervalDays) ??
171
- `Une notification tous les ${String(reminder.intervalDays)} jours pour penser à exporter.` })] }), reminder.busy ? (_jsx(ActivityIndicator, { color: activityIndicatorColor })) : (_jsx(Switch, { value: reminder.enabled, onValueChange: reminder.onToggle }))] }))] }));
62
+ }, accessibilityRole: "switch", accessibilityState: { checked: reminder.enabled }, accessibilityLabel: t.reminderLabel, children: [_jsxs(View, { style: merged.reminderTextColumn, children: [_jsx(Text, { style: merged.reminderLabel, children: t.reminderLabel }), _jsx(Text, { style: merged.reminderHint, children: t.reminderHint(reminder.intervalDays) })] }), reminder.busy ? (_jsx(ActivityIndicator, { color: activityIndicatorColor })) : (_jsx(Switch, { value: reminder.enabled, onValueChange: reminder.onToggle }))] }))] }));
172
63
  }