@forthtilliath/react-native-kit 0.11.0 → 0.13.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.
@@ -0,0 +1,57 @@
1
+ import type { StyleProp, ViewStyle } from "react-native";
2
+ export interface ColorDotProps {
3
+ /**
4
+ * Dot color, as any React Native color string (`"#ef4444"`, `"tomato"`,
5
+ * `"rgba(0,0,0,0.5)"`…). When `undefined`, the component renders `null` —
6
+ * so an optional field can be passed straight through:
7
+ * `<ColorDot color={category.color} />`.
8
+ */
9
+ color?: string;
10
+ /**
11
+ * Diameter in px. The dot is always a perfect circle
12
+ * (`borderRadius = size / 2`).
13
+ *
14
+ * @defaultValue 10
15
+ */
16
+ size?: number;
17
+ /**
18
+ * Extra style merged after the computed `{ width, height, borderRadius,
19
+ * backgroundColor }`. Use it for spacing (`marginRight`), a border, or to
20
+ * override the shape.
21
+ */
22
+ style?: StyleProp<ViewStyle>;
23
+ }
24
+ /**
25
+ * A small round color swatch — the coloured bullet next to a category, a
26
+ * team, a tag, or a status.
27
+ *
28
+ * It renders **nothing** when `color` is `undefined`, which is the whole
29
+ * point: list rows can bind an optional color field without wrapping the dot
30
+ * in `{category.color && ...}` at every call site.
31
+ *
32
+ * @example Basic usage
33
+ * ```tsx
34
+ * import { ColorDot } from "@forthtilliath/react-native-kit/components/list/ColorDot";
35
+ *
36
+ * <View style={{ flexDirection: "row", alignItems: "center", gap: 8 }}>
37
+ * <ColorDot color="#ef4444" />
38
+ * <Text>Urgent</Text>
39
+ * </View>;
40
+ * ```
41
+ *
42
+ * @example Optional color (renders nothing when the category has none)
43
+ * ```tsx
44
+ * <ColorDot color={category.color} size={12} />
45
+ * ```
46
+ *
47
+ * @example Custom size and a subtle ring
48
+ * ```tsx
49
+ * <ColorDot
50
+ * color={team.color}
51
+ * size={16}
52
+ * style={{ borderWidth: 1, borderColor: "rgba(0,0,0,0.15)" }}
53
+ * />
54
+ * ```
55
+ */
56
+ export declare function ColorDot({ color, size, style }: ColorDotProps): import("react").JSX.Element | null;
57
+ //# sourceMappingURL=ColorDot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ColorDot.d.ts","sourceRoot":"","sources":["../../../src/components/list/ColorDot.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzD,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,IAAmB,EAAE,KAAK,EAAE,EAAE,aAAa,sCAe5E"}
@@ -0,0 +1,48 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { View } from "react-native";
3
+ const DEFAULT_SIZE = 10;
4
+ /**
5
+ * A small round color swatch — the coloured bullet next to a category, a
6
+ * team, a tag, or a status.
7
+ *
8
+ * It renders **nothing** when `color` is `undefined`, which is the whole
9
+ * point: list rows can bind an optional color field without wrapping the dot
10
+ * in `{category.color && ...}` at every call site.
11
+ *
12
+ * @example Basic usage
13
+ * ```tsx
14
+ * import { ColorDot } from "@forthtilliath/react-native-kit/components/list/ColorDot";
15
+ *
16
+ * <View style={{ flexDirection: "row", alignItems: "center", gap: 8 }}>
17
+ * <ColorDot color="#ef4444" />
18
+ * <Text>Urgent</Text>
19
+ * </View>;
20
+ * ```
21
+ *
22
+ * @example Optional color (renders nothing when the category has none)
23
+ * ```tsx
24
+ * <ColorDot color={category.color} size={12} />
25
+ * ```
26
+ *
27
+ * @example Custom size and a subtle ring
28
+ * ```tsx
29
+ * <ColorDot
30
+ * color={team.color}
31
+ * size={16}
32
+ * style={{ borderWidth: 1, borderColor: "rgba(0,0,0,0.15)" }}
33
+ * />
34
+ * ```
35
+ */
36
+ export function ColorDot({ color, size = DEFAULT_SIZE, style }) {
37
+ if (!color)
38
+ return null;
39
+ return (_jsx(View, { style: [
40
+ {
41
+ width: size,
42
+ height: size,
43
+ borderRadius: size / 2,
44
+ backgroundColor: color,
45
+ },
46
+ style,
47
+ ] }));
48
+ }
@@ -0,0 +1,100 @@
1
+ import type { StyleProp, TextStyle, ViewStyle } from "react-native";
2
+ /**
3
+ * Per-slot style overrides for {@link UndoToast}. Every field is optional and
4
+ * is **merged after** the matching default (as a style array), so overriding
5
+ * one property (say `toast.backgroundColor`) keeps the rest of the default
6
+ * for that slot — the positioning, padding, and shadow don't disappear.
7
+ */
8
+ export interface UndoToastStyles {
9
+ /** The floating bar container (absolute-positioned, near the bottom). */
10
+ toast?: StyleProp<ViewStyle>;
11
+ /** The message text on the left. Truncated to a single line. */
12
+ message?: StyleProp<TextStyle>;
13
+ /** The action label on the right (the tappable "Undo"). */
14
+ action?: StyleProp<TextStyle>;
15
+ }
16
+ export interface UndoToastProps {
17
+ /**
18
+ * What just happened, phrased in the past tense — e.g.
19
+ * `"« Marie » supprimée"` or `"1 item deleted"`. Rendered on a
20
+ * single line and truncated with an ellipsis if too long.
21
+ */
22
+ message: string;
23
+ /**
24
+ * Label of the action button.
25
+ *
26
+ * @defaultValue "Undo"
27
+ */
28
+ actionLabel?: string;
29
+ /**
30
+ * Called when the action button is tapped. Wire this to your reverse-the-
31
+ * change logic (restore the row, re-insert the item…). The host is
32
+ * responsible for hiding the toast afterwards.
33
+ */
34
+ onAction: () => void;
35
+ /** Per-slot style overrides — see {@link UndoToastStyles}. */
36
+ styles?: UndoToastStyles;
37
+ }
38
+ /**
39
+ * A bottom-of-screen snackbar for **undoing an action that already
40
+ * happened** — the counterpart to a delete that runs immediately with no
41
+ * confirmation dialog (for instance a {@link SwipeToDeleteRow} swipe).
42
+ *
43
+ * `UndoToast` is presentational only: it does not time itself out, animate
44
+ * in/out, or stack. The host owns that — typically a piece of state holding
45
+ * the "pending undo" payload, a `setTimeout` that commits the change for
46
+ * good, and an exit animation. This keeps the component free of any
47
+ * animation-library or timer opinions.
48
+ *
49
+ * The default look is a dark floating bar, readable on both light and dark
50
+ * backgrounds. Re-theme it through {@link UndoToastProps.styles}.
51
+ *
52
+ * @example Minimal
53
+ * ```tsx
54
+ * import { UndoToast } from "@forthtilliath/react-native-kit/components/list/UndoToast";
55
+ *
56
+ * {recentlyDeleted && (
57
+ * <UndoToast
58
+ * message={`"${recentlyDeleted.name}" deleted`}
59
+ * onAction={restoreLast}
60
+ * />
61
+ * )}
62
+ * ```
63
+ *
64
+ * @example Full pattern — auto-commit after 5s, localized label, themed
65
+ * ```tsx
66
+ * const [pending, setPending] = useState<Employee | null>(null);
67
+ *
68
+ * function remove(employee: Employee) {
69
+ * setEmployees((list) => list.filter((e) => e.id !== employee.id));
70
+ * setPending(employee);
71
+ * }
72
+ *
73
+ * useEffect(() => {
74
+ * if (!pending) return;
75
+ * const id = setTimeout(() => {
76
+ * db.deleteEmployee(pending.id); // point of no return
77
+ * setPending(null);
78
+ * }, 5000);
79
+ * return () => clearTimeout(id);
80
+ * }, [pending]);
81
+ *
82
+ * {pending && (
83
+ * <UndoToast
84
+ * message={`« ${pending.name} » supprimé`}
85
+ * actionLabel="Annuler"
86
+ * onAction={() => {
87
+ * setEmployees((list) => [...list, pending]);
88
+ * setPending(null);
89
+ * }}
90
+ * styles={{
91
+ * toast: { backgroundColor: colors.inverseSurface },
92
+ * message: { color: colors.inverseOnSurface },
93
+ * action: { color: colors.inversePrimary },
94
+ * }}
95
+ * />
96
+ * )}
97
+ * ```
98
+ */
99
+ export declare function UndoToast({ message, actionLabel, onAction, styles, }: UndoToastProps): import("react").JSX.Element;
100
+ //# sourceMappingURL=UndoToast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UndoToast.d.ts","sourceRoot":"","sources":["../../../src/components/list/UndoToast.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGpE;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,gEAAgE;IAChE,OAAO,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC/B,2DAA2D;IAC3D,MAAM,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B;AAkCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,wBAAgB,SAAS,CAAC,EACxB,OAAO,EACP,WAAoB,EACpB,QAAQ,EACR,MAAM,GACP,EAAE,cAAc,+BAmBhB"}
@@ -0,0 +1,104 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Pressable, Text, View } from "react-native";
3
+ const defaultStyles = {
4
+ toast: {
5
+ position: "absolute",
6
+ left: 16,
7
+ right: 16,
8
+ bottom: 24,
9
+ flexDirection: "row",
10
+ alignItems: "center",
11
+ justifyContent: "space-between",
12
+ gap: 12,
13
+ paddingVertical: 14,
14
+ paddingHorizontal: 16,
15
+ borderRadius: 8,
16
+ backgroundColor: "#1f1f1f",
17
+ elevation: 4,
18
+ shadowColor: "#000000",
19
+ shadowOpacity: 0.3,
20
+ shadowRadius: 6,
21
+ shadowOffset: { width: 0, height: 2 },
22
+ },
23
+ message: {
24
+ flex: 1,
25
+ color: "#ffffff",
26
+ fontSize: 14,
27
+ },
28
+ action: {
29
+ color: "#7cc0ff",
30
+ fontWeight: "700",
31
+ fontSize: 14,
32
+ },
33
+ };
34
+ /**
35
+ * A bottom-of-screen snackbar for **undoing an action that already
36
+ * happened** — the counterpart to a delete that runs immediately with no
37
+ * confirmation dialog (for instance a {@link SwipeToDeleteRow} swipe).
38
+ *
39
+ * `UndoToast` is presentational only: it does not time itself out, animate
40
+ * in/out, or stack. The host owns that — typically a piece of state holding
41
+ * the "pending undo" payload, a `setTimeout` that commits the change for
42
+ * good, and an exit animation. This keeps the component free of any
43
+ * animation-library or timer opinions.
44
+ *
45
+ * The default look is a dark floating bar, readable on both light and dark
46
+ * backgrounds. Re-theme it through {@link UndoToastProps.styles}.
47
+ *
48
+ * @example Minimal
49
+ * ```tsx
50
+ * import { UndoToast } from "@forthtilliath/react-native-kit/components/list/UndoToast";
51
+ *
52
+ * {recentlyDeleted && (
53
+ * <UndoToast
54
+ * message={`"${recentlyDeleted.name}" deleted`}
55
+ * onAction={restoreLast}
56
+ * />
57
+ * )}
58
+ * ```
59
+ *
60
+ * @example Full pattern — auto-commit after 5s, localized label, themed
61
+ * ```tsx
62
+ * const [pending, setPending] = useState<Employee | null>(null);
63
+ *
64
+ * function remove(employee: Employee) {
65
+ * setEmployees((list) => list.filter((e) => e.id !== employee.id));
66
+ * setPending(employee);
67
+ * }
68
+ *
69
+ * useEffect(() => {
70
+ * if (!pending) return;
71
+ * const id = setTimeout(() => {
72
+ * db.deleteEmployee(pending.id); // point of no return
73
+ * setPending(null);
74
+ * }, 5000);
75
+ * return () => clearTimeout(id);
76
+ * }, [pending]);
77
+ *
78
+ * {pending && (
79
+ * <UndoToast
80
+ * message={`« ${pending.name} » supprimé`}
81
+ * actionLabel="Annuler"
82
+ * onAction={() => {
83
+ * setEmployees((list) => [...list, pending]);
84
+ * setPending(null);
85
+ * }}
86
+ * styles={{
87
+ * toast: { backgroundColor: colors.inverseSurface },
88
+ * message: { color: colors.inverseOnSurface },
89
+ * action: { color: colors.inversePrimary },
90
+ * }}
91
+ * />
92
+ * )}
93
+ * ```
94
+ */
95
+ export function UndoToast({ message, actionLabel = "Undo", onAction, styles, }) {
96
+ // Merge each slot as [default, override] so a partial override doesn't drop
97
+ // the rest of that slot's default (positioning, shadow, flex…).
98
+ const merged = {
99
+ toast: [defaultStyles.toast, styles?.toast],
100
+ message: [defaultStyles.message, styles?.message],
101
+ action: [defaultStyles.action, styles?.action],
102
+ };
103
+ return (_jsxs(View, { style: merged.toast, children: [_jsx(Text, { style: merged.message, numberOfLines: 1, children: message }), _jsx(Pressable, { onPress: onAction, hitSlop: 8, accessibilityRole: "button", children: _jsx(Text, { style: merged.action, children: actionLabel }) })] }));
104
+ }
@@ -1,3 +1,5 @@
1
+ export * from "./ColorDot";
1
2
  export * from "./SwipeableRow";
2
3
  export * from "./Thumbnail";
4
+ export * from "./UndoToast";
3
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/list/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/list/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC"}
@@ -1,2 +1,4 @@
1
+ export * from "./ColorDot";
1
2
  export * from "./SwipeableRow";
2
3
  export * from "./Thumbnail";
4
+ export * from "./UndoToast";
@@ -1,10 +1,15 @@
1
1
  import type { StyleProp, TextStyle, ViewStyle } from "react-native";
2
+ export interface AboutSettingsScreenSection {
3
+ title: string;
4
+ paragraphs: string[];
5
+ }
2
6
  export interface AboutSettingsScreenStyles {
3
7
  container?: StyleProp<ViewStyle>;
4
8
  appName?: StyleProp<TextStyle>;
5
9
  version?: StyleProp<TextStyle>;
6
10
  separator?: StyleProp<ViewStyle>;
7
11
  paragraph?: StyleProp<TextStyle>;
12
+ sectionTitle?: StyleProp<TextStyle>;
8
13
  hint?: StyleProp<TextStyle>;
9
14
  }
10
15
  export interface AboutSettingsScreenLabels {
@@ -16,9 +21,12 @@ export interface AboutSettingsScreenProps {
16
21
  version: string;
17
22
  /** One or more paragraphs describing the app, rendered in order. */
18
23
  description: string | string[];
19
- developerName: string;
24
+ /** Extra titled sections after the description, e.g. a medical/legal disclaimer. */
25
+ sections?: AboutSettingsScreenSection[];
26
+ /** Omit to not show a "developed by" credit line at all. */
27
+ developerName?: string;
20
28
  labels?: AboutSettingsScreenLabels;
21
29
  styles?: AboutSettingsScreenStyles;
22
30
  }
23
- export declare function AboutSettingsScreen({ appName, version, description, developerName, labels, styles, }: AboutSettingsScreenProps): import("react").JSX.Element;
31
+ export declare function AboutSettingsScreen({ appName, version, description, sections, developerName, labels, styles, }: AboutSettingsScreenProps): import("react").JSX.Element;
24
32
  //# 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,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,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,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,yBAAyB,CAAC;IACnC,MAAM,CAAC,EAAE,yBAAyB,CAAC;CACpC;AA8BD,wBAAgB,mBAAmB,CAAC,EAClC,OAAO,EACP,OAAO,EACP,WAAW,EACX,aAAa,EACb,MAAM,EACN,MAAM,GACP,EAAE,wBAAwB,+BA8B1B"}
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,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { Text, View } from "react-native";
3
3
  const defaultLabels = {
4
4
  version: (version) => `Version ${version}`,
@@ -19,23 +19,31 @@ const defaultStyles = {
19
19
  color: "#111827",
20
20
  marginBottom: 12,
21
21
  },
22
+ sectionTitle: {
23
+ fontSize: 15,
24
+ fontWeight: "700",
25
+ color: "#111827",
26
+ marginBottom: 8,
27
+ },
22
28
  hint: { fontSize: 13, color: "#6b7280" },
23
29
  };
24
- // App name, version, a short description, and a "developed by" credit — the
25
- // standard "About" section of a settings tab. `appName`/`version` are
30
+ // App name, version, a short description, optional extra titled sections
31
+ // (e.g. a medical/legal disclaimer), and an optional "developed by" credit —
32
+ // the standard "About" section of a settings tab. `appName`/`version` are
26
33
  // required rather than defaulted from `expo-constants` so this stays
27
34
  // framework-agnostic; pass `Constants.expoConfig?.name`/`.version` from the
28
35
  // caller.
29
- export function AboutSettingsScreen({ appName, version, description, developerName, labels, styles, }) {
36
+ export function AboutSettingsScreen({ appName, version, description, sections, developerName, labels, styles, }) {
30
37
  const merged = {
31
38
  container: [defaultStyles.container, styles?.container],
32
39
  appName: [defaultStyles.appName, styles?.appName],
33
40
  version: [defaultStyles.version, styles?.version],
34
41
  separator: [defaultStyles.separator, styles?.separator],
35
42
  paragraph: [defaultStyles.paragraph, styles?.paragraph],
43
+ sectionTitle: [defaultStyles.sectionTitle, styles?.sectionTitle],
36
44
  hint: [defaultStyles.hint, styles?.hint],
37
45
  };
38
46
  const t = { ...defaultLabels, ...labels };
39
47
  const paragraphs = Array.isArray(description) ? description : [description];
40
- 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))), _jsx(View, { style: merged.separator }), _jsx(Text, { style: merged.hint, children: t.developedBy(developerName) })] }));
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) })] }))] }));
41
49
  }
@@ -1,4 +1,5 @@
1
1
  import type { StyleProp, TextStyle, ViewStyle } from "react-native";
2
+ import { Ionicons } from "@expo/vector-icons";
2
3
  export interface BackupSettingsScreenReminder {
3
4
  enabled: boolean;
4
5
  /** Set while a permission request or the toggle's own persistence is in flight. */
@@ -7,13 +8,29 @@ export interface BackupSettingsScreenReminder {
7
8
  /** How often the reminder fires, only used to word the hint (e.g. "every 7 days"). */
8
9
  intervalDays: number;
9
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
+ }
10
19
  export interface BackupSettingsScreenStyles {
11
20
  container?: StyleProp<ViewStyle>;
21
+ infoBox?: StyleProp<ViewStyle>;
22
+ infoLabel?: StyleProp<TextStyle>;
23
+ infoValue?: StyleProp<TextStyle>;
24
+ sectionTitle?: StyleProp<TextStyle>;
12
25
  hint?: StyleProp<TextStyle>;
13
26
  row?: StyleProp<ViewStyle>;
14
27
  button?: StyleProp<ViewStyle>;
15
28
  buttonDisabled?: StyleProp<ViewStyle>;
16
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>;
17
34
  reminderRow?: StyleProp<ViewStyle>;
18
35
  reminderTextColumn?: StyleProp<ViewStyle>;
19
36
  reminderLabel?: StyleProp<TextStyle>;
@@ -24,6 +41,11 @@ export interface BackupSettingsScreenLabels {
24
41
  hint?: string;
25
42
  exportButton?: string;
26
43
  importButton?: string;
44
+ /** Only shown in `layout="sections"`. */
45
+ exportSectionTitle?: string;
46
+ exportHelpText?: string;
47
+ importSectionTitle?: string;
48
+ importHelpText?: string;
27
49
  importConfirmTitle?: string;
28
50
  importConfirmMessage?: string;
29
51
  importConfirmLabel?: string;
@@ -45,8 +67,18 @@ export interface BackupSettingsScreenProps {
45
67
  onImport: () => Promise<void>;
46
68
  /** Omit entirely to not show a reminder toggle at all. */
47
69
  reminder?: BackupSettingsScreenReminder;
70
+ /** An info box above everything else, e.g. "Last auto-backup: ...". Omit to not show one. */
71
+ info?: BackupSettingsScreenInfo;
72
+ /**
73
+ * `"compact"` (default): one shared hint, both buttons side by side.
74
+ * `"sections"`: each action gets its own title + help text, buttons
75
+ * stacked full-width.
76
+ */
77
+ layout?: "compact" | "sections";
78
+ /** Leading icon for each button. Omit either (or both) for a text-only button (default). */
79
+ icons?: BackupSettingsScreenIcons;
48
80
  labels?: BackupSettingsScreenLabels;
49
81
  styles?: BackupSettingsScreenStyles;
50
82
  }
51
- export declare function BackupSettingsScreen({ onExport, onImport, reminder, labels, styles, }: BackupSettingsScreenProps): import("react").JSX.Element;
83
+ export declare function BackupSettingsScreen({ onExport, onImport, reminder, info, layout, icons, labels, styles, }: BackupSettingsScreenProps): import("react").JSX.Element;
52
84
  //# 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;AAYpE,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,0BAA0B;IACzC,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,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,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,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,MAAM,CAAC,EAAE,0BAA0B,CAAC;IACpC,MAAM,CAAC,EAAE,0BAA0B,CAAC;CACrC;AAiED,wBAAgB,oBAAoB,CAAC,EACnC,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,MAAM,GACP,EAAE,yBAAyB,+BA8H3B"}
1
+ {"version":3,"file":"BackupSettingsScreen.d.ts","sourceRoot":"","sources":["../../../src/components/settings/BackupSettingsScreen.tsx"],"names":[],"mappings":"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"}
@@ -1,11 +1,16 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from "react";
3
3
  import { ActivityIndicator, Alert, Pressable, Switch, Text, View, } from "react-native";
4
+ import { Ionicons } from "@expo/vector-icons";
4
5
  import { confirmDestructive } from "../../utils/helpers/confirmDestructive.js";
5
6
  const defaultLabels = {
6
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.",
7
8
  exportButton: "⬆️ Exporter",
8
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.",
9
14
  importConfirmTitle: "Importer une sauvegarde ?",
10
15
  importConfirmMessage: "Toutes les données actuelles seront remplacées par celles du fichier choisi.",
11
16
  importConfirmLabel: "Choisir un fichier",
@@ -18,9 +23,33 @@ const defaultLabels = {
18
23
  };
19
24
  const defaultStyles = {
20
25
  container: {},
21
- hint: { fontSize: 13, color: "#6b7280", marginBottom: 16 },
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
+ },
22
50
  row: { flexDirection: "row", gap: 10 },
23
51
  button: {
52
+ flexDirection: "row",
24
53
  flex: 1,
25
54
  paddingVertical: 12,
26
55
  borderRadius: 8,
@@ -28,9 +57,13 @@ const defaultStyles = {
28
57
  borderColor: "#2563eb",
29
58
  alignItems: "center",
30
59
  justifyContent: "center",
60
+ gap: 8,
31
61
  },
32
62
  buttonDisabled: { opacity: 0.5 },
33
63
  buttonText: { color: "#2563eb", fontWeight: "700" },
64
+ iconColor: "#2563eb",
65
+ importButton: undefined,
66
+ importButtonText: undefined,
34
67
  reminderRow: {
35
68
  flexDirection: "row",
36
69
  alignItems: "center",
@@ -55,16 +88,32 @@ function errorMessage(err, fallback) {
55
88
  // what gets exported/imported is entirely app-specific (its own database
56
89
  // tables), so `onExport`/`onImport` are required props, not something this
57
90
  // package could have a sensible default for.
58
- export function BackupSettingsScreen({ onExport, onImport, reminder, labels, styles, }) {
91
+ export function BackupSettingsScreen({ onExport, onImport, reminder, info, layout = "compact", icons, labels, styles, }) {
59
92
  const [exporting, setExporting] = useState(false);
60
93
  const [importing, setImporting] = useState(false);
61
94
  const merged = {
62
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],
63
100
  hint: [defaultStyles.hint, styles?.hint],
64
101
  row: [defaultStyles.row, styles?.row],
65
102
  button: [defaultStyles.button, styles?.button],
66
103
  buttonDisabled: [defaultStyles.buttonDisabled, styles?.buttonDisabled],
67
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
+ ],
68
117
  reminderRow: [defaultStyles.reminderRow, styles?.reminderRow],
69
118
  reminderTextColumn: [
70
119
  defaultStyles.reminderTextColumn,
@@ -75,6 +124,7 @@ export function BackupSettingsScreen({ onExport, onImport, reminder, labels, sty
75
124
  };
76
125
  const t = { ...defaultLabels, ...labels };
77
126
  const activityIndicatorColor = styles?.activityIndicatorColor ?? defaultStyles.activityIndicatorColor;
127
+ const iconColor = styles?.iconColor ?? defaultStyles.iconColor;
78
128
  async function handleExport() {
79
129
  if (exporting)
80
130
  return;
@@ -111,9 +161,11 @@ export function BackupSettingsScreen({ onExport, onImport, reminder, labels, sty
111
161
  confirmLabel: t.importConfirmLabel,
112
162
  });
113
163
  }
114
- return (_jsxs(View, { style: merged.container, children: [_jsx(Text, { style: merged.hint, children: t.hint }), _jsxs(View, { style: merged.row, children: [_jsx(Pressable, { style: [merged.button, exporting && merged.buttonDisabled], disabled: exporting, onPress: () => {
115
- void handleExport();
116
- }, accessibilityRole: "button", accessibilityLabel: t.exportButton, children: exporting ? (_jsx(ActivityIndicator, { color: activityIndicatorColor })) : (_jsx(Text, { style: merged.buttonText, children: t.exportButton })) }), _jsx(Pressable, { style: [merged.button, importing && merged.buttonDisabled], disabled: importing, onPress: handleImportPress, accessibilityRole: "button", accessibilityLabel: t.importButton, children: importing ? (_jsx(ActivityIndicator, { color: activityIndicatorColor })) : (_jsx(Text, { style: merged.buttonText, children: t.importButton })) })] }), reminder && (_jsxs(Pressable, { style: merged.reminderRow, disabled: reminder.busy, onPress: () => {
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 })] })) }));
168
+ 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: () => {
117
169
  reminder.onToggle(!reminder.enabled);
118
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) ??
119
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 }))] }))] }));