@forthtilliath/react-native-kit 0.12.0 → 0.14.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 +603 -604
- package/dist/components/index.d.ts +0 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +0 -1
- 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/picker/PickerModal.d.ts +2 -29
- package/dist/components/picker/PickerModal.d.ts.map +1 -1
- package/dist/components/picker/PickerModal.js +10 -112
- package/dist/components/picker/PickerModal.styles.d.ts +32 -0
- package/dist/components/picker/PickerModal.styles.d.ts.map +1 -0
- package/dist/components/picker/PickerModal.styles.js +82 -0
- package/dist/components/picker/PickerModalRow.d.ts +17 -0
- package/dist/components/picker/PickerModalRow.d.ts.map +1 -0
- package/dist/components/picker/PickerModalRow.js +11 -0
- package/dist/components/picker/usePickerModalSections.d.ts +7 -0
- package/dist/components/picker/usePickerModalSections.d.ts.map +1 -0
- package/dist/components/picker/usePickerModalSections.js +28 -0
- package/dist/components/settings/UpdateSettingsScreen.d.ts +2 -46
- package/dist/components/settings/UpdateSettingsScreen.d.ts.map +1 -1
- package/dist/components/settings/UpdateSettingsScreen.js +4 -78
- package/dist/components/settings/UpdateSettingsScreen.styles.d.ts +49 -0
- package/dist/components/settings/UpdateSettingsScreen.styles.d.ts.map +1 -0
- package/dist/components/settings/UpdateSettingsScreen.styles.js +76 -0
- package/dist/components/settings/UpdateSettingsScreenHistory.d.ts +20 -0
- package/dist/components/settings/UpdateSettingsScreenHistory.d.ts.map +1 -0
- package/dist/components/settings/UpdateSettingsScreenHistory.js +10 -0
- package/dist/hooks/index.d.ts +0 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +0 -1
- package/dist/index.d.ts +10 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -11
- package/dist/utils/helpers/index.d.ts +1 -6
- package/dist/utils/helpers/index.d.ts.map +1 -1
- package/dist/utils/helpers/index.js +1 -6
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +0 -1
- package/package.json +4 -3
- package/dist/components/update/ChangelogNotes.d.ts +0 -22
- package/dist/components/update/ChangelogNotes.d.ts.map +0 -1
- package/dist/components/update/ChangelogNotes.js +0 -51
- package/dist/components/update/UpdateAvailableBanner.d.ts +0 -29
- package/dist/components/update/UpdateAvailableBanner.d.ts.map +0 -1
- package/dist/components/update/UpdateAvailableBanner.js +0 -63
- package/dist/components/update/index.d.ts +0 -3
- package/dist/components/update/index.d.ts.map +0 -1
- package/dist/components/update/index.js +0 -2
- package/dist/hooks/useUpdateCheck.d.ts +0 -35
- package/dist/hooks/useUpdateCheck.d.ts.map +0 -1
- package/dist/hooks/useUpdateCheck.js +0 -47
- package/dist/utils/format/escapeCsvField.d.ts +0 -2
- package/dist/utils/format/escapeCsvField.d.ts.map +0 -1
- package/dist/utils/format/escapeCsvField.js +0 -8
- package/dist/utils/format/escapeHtml.d.ts +0 -2
- package/dist/utils/format/escapeHtml.d.ts.map +0 -1
- package/dist/utils/format/escapeHtml.js +0 -9
- package/dist/utils/format/formatCsvNumber.d.ts +0 -2
- package/dist/utils/format/formatCsvNumber.d.ts.map +0 -1
- package/dist/utils/format/formatCsvNumber.js +0 -6
- package/dist/utils/format/index.d.ts +0 -4
- package/dist/utils/format/index.d.ts.map +0 -1
- package/dist/utils/format/index.js +0 -3
- package/dist/utils/helpers/getMostRecentIds.d.ts +0 -6
- package/dist/utils/helpers/getMostRecentIds.d.ts.map +0 -1
- package/dist/utils/helpers/getMostRecentIds.js +0 -19
- package/dist/utils/helpers/getPeriodStartMs.d.ts +0 -3
- package/dist/utils/helpers/getPeriodStartMs.d.ts.map +0 -1
- package/dist/utils/helpers/getPeriodStartMs.js +0 -14
- package/dist/utils/helpers/nextInCycle.d.ts +0 -2
- package/dist/utils/helpers/nextInCycle.d.ts.map +0 -1
- package/dist/utils/helpers/nextInCycle.js +0 -9
- package/dist/utils/helpers/normalizeForSearch.d.ts +0 -2
- package/dist/utils/helpers/normalizeForSearch.d.ts.map +0 -1
- package/dist/utils/helpers/normalizeForSearch.js +0 -15
- package/dist/utils/helpers/rankByNameMatch.d.ts +0 -2
- package/dist/utils/helpers/rankByNameMatch.d.ts.map +0 -1
- package/dist/utils/helpers/rankByNameMatch.js +0 -33
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC"}
|
package/dist/components/index.js
CHANGED
|
@@ -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,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PickerModalLabels, PickerModalStyles } from "./PickerModal.styles.js";
|
|
2
|
+
export type { PickerModalLabels, PickerModalStyles, } from "./PickerModal.styles.js";
|
|
2
3
|
export interface PickerItem {
|
|
3
4
|
id: number;
|
|
4
5
|
label: string;
|
|
@@ -11,34 +12,6 @@ export interface PickerItem {
|
|
|
11
12
|
*/
|
|
12
13
|
group?: string;
|
|
13
14
|
}
|
|
14
|
-
export interface PickerModalStyles {
|
|
15
|
-
container?: StyleProp<ViewStyle>;
|
|
16
|
-
header?: StyleProp<ViewStyle>;
|
|
17
|
-
title?: StyleProp<TextStyle>;
|
|
18
|
-
close?: StyleProp<TextStyle>;
|
|
19
|
-
searchRow?: StyleProp<ViewStyle>;
|
|
20
|
-
search?: StyleProp<TextStyle>;
|
|
21
|
-
row?: StyleProp<ViewStyle>;
|
|
22
|
-
rowThumbnail?: StyleProp<ImageStyle>;
|
|
23
|
-
rowThumbnailPlaceholder?: StyleProp<ViewStyle>;
|
|
24
|
-
rowLabel?: StyleProp<TextStyle>;
|
|
25
|
-
rowSubtitle?: StyleProp<TextStyle>;
|
|
26
|
-
empty?: StyleProp<TextStyle>;
|
|
27
|
-
sectionHeader?: StyleProp<TextStyle>;
|
|
28
|
-
extraActions?: StyleProp<ViewStyle>;
|
|
29
|
-
extraActionLabel?: StyleProp<TextStyle>;
|
|
30
|
-
extraActionIconColor?: string;
|
|
31
|
-
rowThumbnailPlaceholderIconColor?: string;
|
|
32
|
-
placeholderTextColor?: string;
|
|
33
|
-
}
|
|
34
|
-
export interface PickerModalLabels {
|
|
35
|
-
close?: string;
|
|
36
|
-
searchPlaceholder?: string;
|
|
37
|
-
searchAccessibilityLabel?: string;
|
|
38
|
-
voiceSearchAccessibilityLabel?: string;
|
|
39
|
-
defaultEmptyMessage?: string;
|
|
40
|
-
otherGroupLabel?: string;
|
|
41
|
-
}
|
|
42
15
|
export interface PickerModalProps {
|
|
43
16
|
visible: boolean;
|
|
44
17
|
title: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PickerModal.d.ts","sourceRoot":"","sources":["../../../src/components/picker/PickerModal.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PickerModal.d.ts","sourceRoot":"","sources":["../../../src/components/picker/PickerModal.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,yBAAyB,CAAC;AAMjC,YAAY,EACV,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACrC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8FAA8F;IAC9F,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,KAAK,UAAU,EAAE,CAAC;IACnE,qFAAqF;IACrF,YAAY,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,IAAI,CAAA;KAAE,EAAE,CAAC;IACxD;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC5B;AAID,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,KAAK,EACL,KAAK,EACL,QAAQ,EACR,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,UAAU,EACV,MAAM,EACN,MAAM,GACP,EAAE,gBAAgB,+BAwJlB"}
|
|
@@ -1,90 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useMemo, useState } from "react";
|
|
3
|
-
import {
|
|
3
|
+
import { Modal, Pressable, SectionList, Text, TextInput, View, } from "react-native";
|
|
4
4
|
import { Ionicons } from "@expo/vector-icons";
|
|
5
|
+
import { defaultLabels, defaultStyles } from "./PickerModal.styles.js";
|
|
6
|
+
import { PickerModalRow } from "./PickerModalRow.js";
|
|
7
|
+
import { usePickerModalSections } from "./usePickerModalSections.js";
|
|
5
8
|
import { VoiceSearchButton } from "./VoiceSearchButton.js";
|
|
6
|
-
const defaultStyles = {
|
|
7
|
-
container: {
|
|
8
|
-
flex: 1,
|
|
9
|
-
backgroundColor: "#ffffff",
|
|
10
|
-
paddingTop: 60,
|
|
11
|
-
paddingHorizontal: 16,
|
|
12
|
-
},
|
|
13
|
-
header: {
|
|
14
|
-
flexDirection: "row",
|
|
15
|
-
justifyContent: "space-between",
|
|
16
|
-
alignItems: "center",
|
|
17
|
-
marginBottom: 12,
|
|
18
|
-
},
|
|
19
|
-
title: { fontSize: 20, fontWeight: "700", color: "#111827" },
|
|
20
|
-
close: { fontSize: 16, color: "#2563eb" },
|
|
21
|
-
searchRow: {
|
|
22
|
-
flexDirection: "row",
|
|
23
|
-
alignItems: "center",
|
|
24
|
-
gap: 10,
|
|
25
|
-
marginBottom: 8,
|
|
26
|
-
},
|
|
27
|
-
search: {
|
|
28
|
-
backgroundColor: "#f9fafb",
|
|
29
|
-
borderWidth: 1,
|
|
30
|
-
borderColor: "#e5e7eb",
|
|
31
|
-
borderRadius: 10,
|
|
32
|
-
paddingHorizontal: 12,
|
|
33
|
-
paddingVertical: 10,
|
|
34
|
-
fontSize: 16,
|
|
35
|
-
color: "#111827",
|
|
36
|
-
flex: 1,
|
|
37
|
-
},
|
|
38
|
-
row: {
|
|
39
|
-
flexDirection: "row",
|
|
40
|
-
alignItems: "center",
|
|
41
|
-
gap: 12,
|
|
42
|
-
backgroundColor: "#f9fafb",
|
|
43
|
-
borderWidth: 1,
|
|
44
|
-
borderColor: "#e5e7eb",
|
|
45
|
-
borderRadius: 10,
|
|
46
|
-
padding: 14,
|
|
47
|
-
marginBottom: 8,
|
|
48
|
-
},
|
|
49
|
-
rowThumbnail: {
|
|
50
|
-
width: 40,
|
|
51
|
-
height: 40,
|
|
52
|
-
borderRadius: 8,
|
|
53
|
-
backgroundColor: "#ffffff",
|
|
54
|
-
},
|
|
55
|
-
rowThumbnailPlaceholder: {
|
|
56
|
-
width: 40,
|
|
57
|
-
height: 40,
|
|
58
|
-
borderRadius: 8,
|
|
59
|
-
backgroundColor: "#ffffff",
|
|
60
|
-
alignItems: "center",
|
|
61
|
-
justifyContent: "center",
|
|
62
|
-
},
|
|
63
|
-
rowLabel: { fontSize: 16, fontWeight: "600", color: "#111827" },
|
|
64
|
-
rowSubtitle: { fontSize: 13, color: "#6b7280", marginTop: 2 },
|
|
65
|
-
empty: { textAlign: "center", color: "#6b7280", marginTop: 24 },
|
|
66
|
-
sectionHeader: {
|
|
67
|
-
fontSize: 13,
|
|
68
|
-
fontWeight: "700",
|
|
69
|
-
color: "#6b7280",
|
|
70
|
-
textTransform: "uppercase",
|
|
71
|
-
marginTop: 8,
|
|
72
|
-
marginBottom: 6,
|
|
73
|
-
},
|
|
74
|
-
extraActions: { marginBottom: 4 },
|
|
75
|
-
extraActionLabel: { color: "#2563eb" },
|
|
76
|
-
extraActionIconColor: "#2563eb",
|
|
77
|
-
rowThumbnailPlaceholderIconColor: "#6b7280",
|
|
78
|
-
placeholderTextColor: "#6b7280",
|
|
79
|
-
};
|
|
80
|
-
const defaultLabels = {
|
|
81
|
-
close: "Fermer",
|
|
82
|
-
searchPlaceholder: "Rechercher…",
|
|
83
|
-
searchAccessibilityLabel: "Rechercher",
|
|
84
|
-
voiceSearchAccessibilityLabel: "Dicter la recherche",
|
|
85
|
-
defaultEmptyMessage: "Aucun résultat.",
|
|
86
|
-
otherGroupLabel: "Autres",
|
|
87
|
-
};
|
|
88
9
|
// Full-screen picker: search (typed or dictated), optional sections, and
|
|
89
10
|
// "add" actions always visible above the results.
|
|
90
11
|
export function PickerModal({ visible, title, items, onSelect, onClose, emptyMessage, initialQuery, filterItems, extraActions, groupOrder, labels, styles, }) {
|
|
@@ -139,33 +60,10 @@ export function PickerModal({ visible, title, items, onSelect, onClose, emptyMes
|
|
|
139
60
|
const q = query.trim().toLowerCase();
|
|
140
61
|
return items.filter((item) => item.label.toLowerCase().includes(q));
|
|
141
62
|
}, [items, query, filterItems, isSearching]);
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
return [{ title: null, data: filtered }];
|
|
149
|
-
}
|
|
150
|
-
const byGroup = new Map();
|
|
151
|
-
for (const item of filtered) {
|
|
152
|
-
const key = item.group ?? t.otherGroupLabel;
|
|
153
|
-
const group = byGroup.get(key);
|
|
154
|
-
if (group)
|
|
155
|
-
group.push(item);
|
|
156
|
-
else
|
|
157
|
-
byGroup.set(key, [item]);
|
|
158
|
-
}
|
|
159
|
-
function sortIndex(groupTitle) {
|
|
160
|
-
const index = groupOrder?.indexOf(groupTitle) ?? -1;
|
|
161
|
-
return index === -1 ? (groupOrder?.length ?? 0) : index;
|
|
162
|
-
}
|
|
163
|
-
return [...byGroup.entries()]
|
|
164
|
-
.sort(([a], [b]) => sortIndex(a) - sortIndex(b) || a.localeCompare(b))
|
|
165
|
-
.map(([sectionTitle, data]) => ({ title: sectionTitle, data }));
|
|
166
|
-
}, [filtered, isSearching, groupOrder, t.otherGroupLabel]);
|
|
167
|
-
return (_jsx(Modal, { visible: visible, animationType: "slide", onRequestClose: onClose, children: _jsxs(View, { style: merged.container, children: [_jsxs(View, { style: merged.header, children: [_jsx(Text, { style: merged.title, children: title }), _jsx(Pressable, { onPress: onClose, hitSlop: 12, accessibilityRole: "button", accessibilityLabel: t.close, children: _jsx(Text, { style: merged.close, children: t.close }) })] }), _jsxs(View, { style: merged.searchRow, children: [_jsx(TextInput, { style: merged.search, placeholder: t.searchPlaceholder, placeholderTextColor: merged.placeholderTextColor, value: query, onChangeText: setQuery, autoFocus: true, accessibilityLabel: t.searchAccessibilityLabel }), _jsx(VoiceSearchButton, { onResult: setQuery, accessibilityLabel: t.voiceSearchAccessibilityLabel })] }), _jsx(SectionList, { sections: sections, keyExtractor: (item) => String(item.id), keyboardShouldPersistTaps: "handled", stickySectionHeadersEnabled: false, ListHeaderComponent: extraActions && extraActions.length > 0 ? (_jsx(View, { style: merged.extraActions, children: extraActions.map((action) => (_jsxs(Pressable, { style: merged.row, onPress: action.onPress, accessibilityRole: "button", accessibilityLabel: action.label, children: [_jsx(Ionicons, { name: "add-circle-outline", size: 20, color: merged.extraActionIconColor }), _jsx(Text, { style: [merged.rowLabel, merged.extraActionLabel], children: action.label })] }, action.label))) })) : null, ListEmptyComponent: _jsx(Text, { style: merged.empty, children: emptyMessage ?? t.defaultEmptyMessage }), renderSectionHeader: ({ section: { title: sectionTitle }, }) => sectionTitle ? (_jsx(Text, { style: merged.sectionHeader, children: sectionTitle })) : null, renderItem: ({ item }) => (_jsxs(Pressable, { style: merged.row, onPress: () => {
|
|
168
|
-
onSelect(item);
|
|
169
|
-
setQuery("");
|
|
170
|
-
}, accessibilityRole: "button", accessibilityLabel: item.subtitle ? `${item.label}, ${item.subtitle}` : item.label, children: [item.imageUri ? (_jsx(Image, { source: { uri: item.imageUri }, style: merged.rowThumbnail, accessibilityIgnoresInvertColors: true })) : item.imageUri === null ? (_jsx(View, { style: merged.rowThumbnailPlaceholder, children: _jsx(Ionicons, { name: "cube-outline", size: 18, color: merged.rowThumbnailPlaceholderIconColor }) })) : null, _jsxs(View, { style: { flex: 1 }, children: [_jsx(Text, { style: merged.rowLabel, children: item.label }), item.subtitle ? (_jsx(Text, { style: merged.rowSubtitle, children: item.subtitle })) : null] })] })) })] }) }));
|
|
63
|
+
const sections = usePickerModalSections(filtered, isSearching, groupOrder, t.otherGroupLabel);
|
|
64
|
+
function handleSelect(item) {
|
|
65
|
+
onSelect(item);
|
|
66
|
+
setQuery("");
|
|
67
|
+
}
|
|
68
|
+
return (_jsx(Modal, { visible: visible, animationType: "slide", onRequestClose: onClose, children: _jsxs(View, { style: merged.container, children: [_jsxs(View, { style: merged.header, children: [_jsx(Text, { style: merged.title, children: title }), _jsx(Pressable, { onPress: onClose, hitSlop: 12, accessibilityRole: "button", accessibilityLabel: t.close, children: _jsx(Text, { style: merged.close, children: t.close }) })] }), _jsxs(View, { style: merged.searchRow, children: [_jsx(TextInput, { style: merged.search, placeholder: t.searchPlaceholder, placeholderTextColor: merged.placeholderTextColor, value: query, onChangeText: setQuery, autoFocus: true, accessibilityLabel: t.searchAccessibilityLabel }), _jsx(VoiceSearchButton, { onResult: setQuery, accessibilityLabel: t.voiceSearchAccessibilityLabel })] }), _jsx(SectionList, { sections: sections, keyExtractor: (item) => String(item.id), keyboardShouldPersistTaps: "handled", stickySectionHeadersEnabled: false, ListHeaderComponent: extraActions && extraActions.length > 0 ? (_jsx(View, { style: merged.extraActions, children: extraActions.map((action) => (_jsxs(Pressable, { style: merged.row, onPress: action.onPress, accessibilityRole: "button", accessibilityLabel: action.label, children: [_jsx(Ionicons, { name: "add-circle-outline", size: 20, color: merged.extraActionIconColor }), _jsx(Text, { style: [merged.rowLabel, merged.extraActionLabel], children: action.label })] }, action.label))) })) : null, ListEmptyComponent: _jsx(Text, { style: merged.empty, children: emptyMessage ?? t.defaultEmptyMessage }), renderSectionHeader: ({ section: { title: sectionTitle }, }) => sectionTitle ? (_jsx(Text, { style: merged.sectionHeader, children: sectionTitle })) : null, renderItem: ({ item }) => (_jsx(PickerModalRow, { item: item, styles: merged, onSelect: handleSelect })) })] }) }));
|
|
171
69
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ImageStyle, StyleProp, TextStyle, ViewStyle } from "react-native";
|
|
2
|
+
export interface PickerModalStyles {
|
|
3
|
+
container?: StyleProp<ViewStyle>;
|
|
4
|
+
header?: StyleProp<ViewStyle>;
|
|
5
|
+
title?: StyleProp<TextStyle>;
|
|
6
|
+
close?: StyleProp<TextStyle>;
|
|
7
|
+
searchRow?: StyleProp<ViewStyle>;
|
|
8
|
+
search?: StyleProp<TextStyle>;
|
|
9
|
+
row?: StyleProp<ViewStyle>;
|
|
10
|
+
rowThumbnail?: StyleProp<ImageStyle>;
|
|
11
|
+
rowThumbnailPlaceholder?: StyleProp<ViewStyle>;
|
|
12
|
+
rowLabel?: StyleProp<TextStyle>;
|
|
13
|
+
rowSubtitle?: StyleProp<TextStyle>;
|
|
14
|
+
empty?: StyleProp<TextStyle>;
|
|
15
|
+
sectionHeader?: StyleProp<TextStyle>;
|
|
16
|
+
extraActions?: StyleProp<ViewStyle>;
|
|
17
|
+
extraActionLabel?: StyleProp<TextStyle>;
|
|
18
|
+
extraActionIconColor?: string;
|
|
19
|
+
rowThumbnailPlaceholderIconColor?: string;
|
|
20
|
+
placeholderTextColor?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface PickerModalLabels {
|
|
23
|
+
close?: string;
|
|
24
|
+
searchPlaceholder?: string;
|
|
25
|
+
searchAccessibilityLabel?: string;
|
|
26
|
+
voiceSearchAccessibilityLabel?: string;
|
|
27
|
+
defaultEmptyMessage?: string;
|
|
28
|
+
otherGroupLabel?: string;
|
|
29
|
+
}
|
|
30
|
+
export declare const defaultStyles: Required<PickerModalStyles>;
|
|
31
|
+
export declare const defaultLabels: Required<PickerModalLabels>;
|
|
32
|
+
//# sourceMappingURL=PickerModal.styles.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export const defaultStyles = {
|
|
2
|
+
container: {
|
|
3
|
+
flex: 1,
|
|
4
|
+
backgroundColor: "#ffffff",
|
|
5
|
+
paddingTop: 60,
|
|
6
|
+
paddingHorizontal: 16,
|
|
7
|
+
},
|
|
8
|
+
header: {
|
|
9
|
+
flexDirection: "row",
|
|
10
|
+
justifyContent: "space-between",
|
|
11
|
+
alignItems: "center",
|
|
12
|
+
marginBottom: 12,
|
|
13
|
+
},
|
|
14
|
+
title: { fontSize: 20, fontWeight: "700", color: "#111827" },
|
|
15
|
+
close: { fontSize: 16, color: "#2563eb" },
|
|
16
|
+
searchRow: {
|
|
17
|
+
flexDirection: "row",
|
|
18
|
+
alignItems: "center",
|
|
19
|
+
gap: 10,
|
|
20
|
+
marginBottom: 8,
|
|
21
|
+
},
|
|
22
|
+
search: {
|
|
23
|
+
backgroundColor: "#f9fafb",
|
|
24
|
+
borderWidth: 1,
|
|
25
|
+
borderColor: "#e5e7eb",
|
|
26
|
+
borderRadius: 10,
|
|
27
|
+
paddingHorizontal: 12,
|
|
28
|
+
paddingVertical: 10,
|
|
29
|
+
fontSize: 16,
|
|
30
|
+
color: "#111827",
|
|
31
|
+
flex: 1,
|
|
32
|
+
},
|
|
33
|
+
row: {
|
|
34
|
+
flexDirection: "row",
|
|
35
|
+
alignItems: "center",
|
|
36
|
+
gap: 12,
|
|
37
|
+
backgroundColor: "#f9fafb",
|
|
38
|
+
borderWidth: 1,
|
|
39
|
+
borderColor: "#e5e7eb",
|
|
40
|
+
borderRadius: 10,
|
|
41
|
+
padding: 14,
|
|
42
|
+
marginBottom: 8,
|
|
43
|
+
},
|
|
44
|
+
rowThumbnail: {
|
|
45
|
+
width: 40,
|
|
46
|
+
height: 40,
|
|
47
|
+
borderRadius: 8,
|
|
48
|
+
backgroundColor: "#ffffff",
|
|
49
|
+
},
|
|
50
|
+
rowThumbnailPlaceholder: {
|
|
51
|
+
width: 40,
|
|
52
|
+
height: 40,
|
|
53
|
+
borderRadius: 8,
|
|
54
|
+
backgroundColor: "#ffffff",
|
|
55
|
+
alignItems: "center",
|
|
56
|
+
justifyContent: "center",
|
|
57
|
+
},
|
|
58
|
+
rowLabel: { fontSize: 16, fontWeight: "600", color: "#111827" },
|
|
59
|
+
rowSubtitle: { fontSize: 13, color: "#6b7280", marginTop: 2 },
|
|
60
|
+
empty: { textAlign: "center", color: "#6b7280", marginTop: 24 },
|
|
61
|
+
sectionHeader: {
|
|
62
|
+
fontSize: 13,
|
|
63
|
+
fontWeight: "700",
|
|
64
|
+
color: "#6b7280",
|
|
65
|
+
textTransform: "uppercase",
|
|
66
|
+
marginTop: 8,
|
|
67
|
+
marginBottom: 6,
|
|
68
|
+
},
|
|
69
|
+
extraActions: { marginBottom: 4 },
|
|
70
|
+
extraActionLabel: { color: "#2563eb" },
|
|
71
|
+
extraActionIconColor: "#2563eb",
|
|
72
|
+
rowThumbnailPlaceholderIconColor: "#6b7280",
|
|
73
|
+
placeholderTextColor: "#6b7280",
|
|
74
|
+
};
|
|
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",
|
|
82
|
+
};
|