@pagopa/io-app-design-system 1.22.0 → 1.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/lib/commonjs/components/avatar/Avatar.js +21 -8
  2. package/lib/commonjs/components/avatar/Avatar.js.map +1 -1
  3. package/lib/commonjs/components/icons/Icon.js +4 -3
  4. package/lib/commonjs/components/icons/Icon.js.map +1 -1
  5. package/lib/commonjs/components/layout/HeaderSecondLevel.js +2 -0
  6. package/lib/commonjs/components/layout/HeaderSecondLevel.js.map +1 -1
  7. package/lib/commonjs/components/listitems/ListItemHeader.js +2 -1
  8. package/lib/commonjs/components/listitems/ListItemHeader.js.map +1 -1
  9. package/lib/commonjs/components/listitems/ListItemNav.js +13 -3
  10. package/lib/commonjs/components/listitems/ListItemNav.js.map +1 -1
  11. package/lib/commonjs/components/modules/ModuleAttachment.js +196 -0
  12. package/lib/commonjs/components/modules/ModuleAttachment.js.map +1 -0
  13. package/lib/commonjs/components/modules/index.js +11 -0
  14. package/lib/commonjs/components/modules/index.js.map +1 -1
  15. package/lib/module/components/avatar/Avatar.js +22 -8
  16. package/lib/module/components/avatar/Avatar.js.map +1 -1
  17. package/lib/module/components/icons/Icon.js +4 -3
  18. package/lib/module/components/icons/Icon.js.map +1 -1
  19. package/lib/module/components/layout/HeaderSecondLevel.js +2 -0
  20. package/lib/module/components/layout/HeaderSecondLevel.js.map +1 -1
  21. package/lib/module/components/listitems/ListItemHeader.js +2 -1
  22. package/lib/module/components/listitems/ListItemHeader.js.map +1 -1
  23. package/lib/module/components/listitems/ListItemNav.js +13 -3
  24. package/lib/module/components/listitems/ListItemNav.js.map +1 -1
  25. package/lib/module/components/modules/ModuleAttachment.js +186 -0
  26. package/lib/module/components/modules/ModuleAttachment.js.map +1 -0
  27. package/lib/module/components/modules/index.js +1 -0
  28. package/lib/module/components/modules/index.js.map +1 -1
  29. package/lib/typescript/components/avatar/Avatar.d.ts +9 -1
  30. package/lib/typescript/components/avatar/Avatar.d.ts.map +1 -1
  31. package/lib/typescript/components/icons/Icon.d.ts.map +1 -1
  32. package/lib/typescript/components/layout/HeaderSecondLevel.d.ts.map +1 -1
  33. package/lib/typescript/components/listitems/ListItemHeader.d.ts.map +1 -1
  34. package/lib/typescript/components/listitems/ListItemNav.d.ts +2 -1
  35. package/lib/typescript/components/listitems/ListItemNav.d.ts.map +1 -1
  36. package/lib/typescript/components/modules/ModuleAttachment.d.ts +32 -0
  37. package/lib/typescript/components/modules/ModuleAttachment.d.ts.map +1 -0
  38. package/lib/typescript/components/modules/index.d.ts +1 -0
  39. package/lib/typescript/components/modules/index.d.ts.map +1 -1
  40. package/package.json +1 -1
  41. package/src/components/avatar/Avatar.tsx +31 -13
  42. package/src/components/icons/Icon.tsx +4 -3
  43. package/src/components/layout/HeaderSecondLevel.tsx +2 -0
  44. package/src/components/listitems/ListItemHeader.tsx +4 -1
  45. package/src/components/listitems/ListItemNav.tsx +15 -3
  46. package/src/components/modules/ModuleAttachment.tsx +254 -0
  47. package/src/components/modules/index.tsx +1 -0
@@ -0,0 +1,254 @@
1
+ import React, { useCallback } from "react";
2
+ import {
3
+ GestureResponderEvent,
4
+ Pressable,
5
+ PressableProps,
6
+ StyleSheet,
7
+ View
8
+ } from "react-native";
9
+ import Animated, {
10
+ Extrapolate,
11
+ interpolate,
12
+ useAnimatedStyle,
13
+ useDerivedValue,
14
+ useSharedValue,
15
+ withSpring
16
+ } from "react-native-reanimated";
17
+ import Placeholder from "rn-placeholder";
18
+ import {
19
+ IOColors,
20
+ IOListItemVisualParams,
21
+ IOScaleValues,
22
+ IOSpringValues,
23
+ useIOTheme
24
+ } from "../../core";
25
+ import { WithTestID } from "../../utils/types";
26
+ import { Icon } from "../icons";
27
+ import { LabelSmall } from "../typography";
28
+ import { VSpacer } from "../spacer";
29
+ import { Badge } from "../badge";
30
+ import { LoadingSpinner } from "../loadingSpinner";
31
+
32
+ type PartialProps = WithTestID<{
33
+ title: string;
34
+ format: "doc" | "pdf";
35
+ isLoading?: boolean;
36
+ loadingAccessibilityLabel?: string;
37
+ isFetching?: boolean;
38
+ fetchingAccessibilityLabel?: string;
39
+ onPress: (event: GestureResponderEvent) => void;
40
+ }>;
41
+
42
+ export type ModuleAttachmentProps = PartialProps &
43
+ Pick<
44
+ PressableProps,
45
+ "onPress" | "accessibilityLabel" | "disabled" | "testID"
46
+ >;
47
+
48
+ type SkeletonComponentProps = {
49
+ loadingAccessibilityLabel?: string;
50
+ };
51
+
52
+ const styles = StyleSheet.create({
53
+ button: {
54
+ flexDirection: "row",
55
+ alignItems: "center",
56
+ paddingHorizontal: 16,
57
+ paddingVertical: 16,
58
+ borderRadius: 8,
59
+ borderColor: IOColors.bluegreyLight,
60
+ backgroundColor: IOColors.white,
61
+ borderStyle: "solid",
62
+ borderWidth: 1
63
+ },
64
+ innerContent: {
65
+ flex: 1,
66
+ flexDirection: "column"
67
+ },
68
+ rightSection: {
69
+ marginLeft: IOListItemVisualParams.iconMargin,
70
+ alignItems: "center"
71
+ }
72
+ });
73
+
74
+ const DISABLED_OPACITY = 0.5;
75
+
76
+ const ModuleAttachmentContent = ({
77
+ isFetching,
78
+ format,
79
+ title,
80
+ testID
81
+ }: Pick<
82
+ ModuleAttachmentProps,
83
+ "isFetching" | "format" | "title" | "testID"
84
+ >) => {
85
+ const theme = useIOTheme();
86
+ const IconOrActivityIndicatorComponent = () => {
87
+ if (isFetching) {
88
+ const activityIndicatorTestId = testID
89
+ ? `${testID}_activityIndicator`
90
+ : undefined;
91
+ return <LoadingSpinner testID={activityIndicatorTestId} />;
92
+ }
93
+
94
+ return (
95
+ <Icon
96
+ name="chevronRightListItem"
97
+ color={theme["interactiveElem-default"]}
98
+ size={IOListItemVisualParams.chevronSize}
99
+ />
100
+ );
101
+ };
102
+
103
+ return (
104
+ <>
105
+ <View style={styles.innerContent}>
106
+ <LabelSmall
107
+ numberOfLines={1}
108
+ weight="SemiBold"
109
+ font="ReadexPro"
110
+ color="blueIO-500"
111
+ >
112
+ {title}
113
+ </LabelSmall>
114
+ <VSpacer size={4} />
115
+ <View style={{ width: 44 }}>
116
+ <Badge text={format.toUpperCase()} variant="default" />
117
+ </View>
118
+ </View>
119
+ <View style={styles.rightSection}>
120
+ <IconOrActivityIndicatorComponent />
121
+ </View>
122
+ </>
123
+ );
124
+ };
125
+
126
+ /**
127
+ * The `ModuleAttachment` component is a custom button component with an extended outline style.
128
+ * It provides an animated scaling effect when pressed.
129
+ *
130
+ * @param {string} accessibilityLabel - Optional accessibility label.
131
+ * @param {boolean} disabled - If true, the button is disabled.
132
+ * @param {string} fetchingAccessibilityLabel - Optional accessibility label to use during fetching.
133
+ * @param {string} format - Badge content. PDF or DOC.
134
+ * @param {boolean} isLoading - If true, displays a skeleton loading component.
135
+ * @param {boolean} isFetching - If true, displays an activity indicator.
136
+ * @param {string} loadingAccessibilityLabel - Optional accessibility label to use during loading.
137
+ * @param {function} onPress - The function to be executed when the item is pressed.
138
+ * @param {string} testID - The test ID for testing purposes.
139
+ * @param {string} title - The title text to display.
140
+ *
141
+ */
142
+ export const ModuleAttachment = ({
143
+ accessibilityLabel,
144
+ disabled = false,
145
+ fetchingAccessibilityLabel,
146
+ format,
147
+ isLoading = false,
148
+ isFetching = false,
149
+ loadingAccessibilityLabel,
150
+ onPress,
151
+ testID,
152
+ title
153
+ }: ModuleAttachmentProps) => {
154
+ const isPressed: Animated.SharedValue<number> = useSharedValue(0);
155
+
156
+ // Scaling transformation applied when the button is pressed
157
+ const animationScaleValue = IOScaleValues?.magnifiedButton?.pressedState;
158
+
159
+ const scaleTraversed = useDerivedValue(() =>
160
+ withSpring(isPressed.value, IOSpringValues.button)
161
+ );
162
+
163
+ // Interpolate animation values from `isPressed` values
164
+ const animatedStyle = useAnimatedStyle(() => {
165
+ const scale = interpolate(
166
+ scaleTraversed.value,
167
+ [0, 1],
168
+ [1, animationScaleValue],
169
+ Extrapolate.CLAMP
170
+ );
171
+
172
+ return {
173
+ transform: [{ scale }]
174
+ };
175
+ });
176
+
177
+ const onPressIn = useCallback(() => {
178
+ // eslint-disable-next-line functional/immutable-data
179
+ isPressed.value = 1;
180
+ }, [isPressed]);
181
+
182
+ const onPressOut = useCallback(() => {
183
+ // eslint-disable-next-line functional/immutable-data
184
+ isPressed.value = 0;
185
+ }, [isPressed]);
186
+
187
+ const handleOnPress = useCallback(
188
+ (event: GestureResponderEvent) => {
189
+ if (isFetching) {
190
+ return;
191
+ }
192
+ onPress(event);
193
+ },
194
+ [isFetching, onPress]
195
+ );
196
+
197
+ if (isLoading) {
198
+ return (
199
+ <SkeletonComponent
200
+ loadingAccessibilityLabel={loadingAccessibilityLabel}
201
+ />
202
+ );
203
+ }
204
+
205
+ const pressableAccessibilityLabel =
206
+ (isFetching && !!fetchingAccessibilityLabel
207
+ ? fetchingAccessibilityLabel
208
+ : accessibilityLabel) ?? title;
209
+ return (
210
+ <Pressable
211
+ testID={testID}
212
+ onPress={handleOnPress}
213
+ onPressIn={onPressIn}
214
+ onPressOut={onPressOut}
215
+ accessible={true}
216
+ accessibilityRole={"button"}
217
+ accessibilityHint={format}
218
+ accessibilityLabel={pressableAccessibilityLabel}
219
+ disabled={disabled || isFetching}
220
+ >
221
+ <Animated.View
222
+ style={[
223
+ styles.button,
224
+ animatedStyle,
225
+ { opacity: disabled ? DISABLED_OPACITY : 1 }
226
+ ]}
227
+ accessibilityElementsHidden={true}
228
+ importantForAccessibility="no-hide-descendants"
229
+ >
230
+ <ModuleAttachmentContent
231
+ isFetching={isFetching}
232
+ title={title}
233
+ format={format}
234
+ />
235
+ </Animated.View>
236
+ </Pressable>
237
+ );
238
+ };
239
+
240
+ const SkeletonComponent = ({
241
+ loadingAccessibilityLabel
242
+ }: SkeletonComponentProps) => (
243
+ <View
244
+ style={styles.button}
245
+ accessible={true}
246
+ accessibilityLabel={loadingAccessibilityLabel}
247
+ >
248
+ <View style={styles.innerContent}>
249
+ <Placeholder.Box animate="fade" radius={8} width={107} height={22} />
250
+ <VSpacer size={4} />
251
+ <Placeholder.Box animate="fade" radius={8} width={44} height={22} />
252
+ </View>
253
+ </View>
254
+ );
@@ -2,3 +2,4 @@ export * from "./ModuleIDP";
2
2
  export * from "./ModulePaymentNotice";
3
3
  export * from "./PressableModuleBase";
4
4
  export * from "./ModuleCheckout";
5
+ export * from "./ModuleAttachment";