@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.
- package/LICENSE +21 -21
- package/README.md +701 -533
- package/dist/components/list/ColorDot.d.ts +57 -0
- package/dist/components/list/ColorDot.d.ts.map +1 -0
- package/dist/components/list/ColorDot.js +48 -0
- package/dist/components/list/UndoToast.d.ts +100 -0
- package/dist/components/list/UndoToast.d.ts.map +1 -0
- package/dist/components/list/UndoToast.js +104 -0
- package/dist/components/list/index.d.ts +2 -0
- package/dist/components/list/index.d.ts.map +1 -1
- package/dist/components/list/index.js +2 -0
- package/dist/components/settings/AboutSettingsScreen.d.ts +10 -2
- package/dist/components/settings/AboutSettingsScreen.d.ts.map +1 -1
- package/dist/components/settings/AboutSettingsScreen.js +13 -5
- package/dist/components/settings/BackupSettingsScreen.d.ts +33 -1
- package/dist/components/settings/BackupSettingsScreen.d.ts.map +1 -1
- package/dist/components/settings/BackupSettingsScreen.js +58 -6
- package/dist/components/settings/ContactSettingsScreen.d.ts +22 -1
- package/dist/components/settings/ContactSettingsScreen.d.ts.map +1 -1
- package/dist/components/settings/ContactSettingsScreen.js +28 -5
- package/dist/components/settings/SettingsMenu.d.ts +11 -2
- package/dist/components/settings/SettingsMenu.d.ts.map +1 -1
- package/dist/components/settings/SettingsMenu.js +19 -6
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/package.json +2 -2
|
@@ -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 +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,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
|
-
|
|
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;
|
|
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,
|
|
25
|
-
//
|
|
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;
|
|
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
|
-
|
|
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
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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 }))] }))] }));
|