@pagopa/io-app-design-system 1.1.3 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/README.md +1 -0
  2. package/lib/commonjs/components/common/AnimatedTick.js +2 -1
  3. package/lib/commonjs/components/common/AnimatedTick.js.map +1 -1
  4. package/lib/commonjs/components/icons/Icon.js +124 -120
  5. package/lib/commonjs/components/icons/Icon.js.map +1 -1
  6. package/lib/commonjs/components/icons/svg/IconLight.js +31 -0
  7. package/lib/commonjs/components/icons/svg/IconLight.js.map +1 -0
  8. package/lib/commonjs/components/icons/svg/IconLightFilled.js +31 -0
  9. package/lib/commonjs/components/icons/svg/IconLightFilled.js.map +1 -0
  10. package/lib/commonjs/components/icons/svg/originals/IconLight.svg +3 -0
  11. package/lib/commonjs/components/icons/svg/originals/IconLightFilled.svg +3 -0
  12. package/lib/commonjs/components/index.js +11 -0
  13. package/lib/commonjs/components/index.js.map +1 -1
  14. package/lib/commonjs/components/pictograms/Pictogram.js +31 -29
  15. package/lib/commonjs/components/pictograms/Pictogram.js.map +1 -1
  16. package/lib/commonjs/components/pictograms/svg/PictogramSuccess.js +61 -0
  17. package/lib/commonjs/components/pictograms/svg/PictogramSuccess.js.map +1 -0
  18. package/lib/commonjs/components/pictograms/svg/originals/PictogramSuccess.svg +35 -0
  19. package/lib/commonjs/components/tabs/TabItem.js +123 -0
  20. package/lib/commonjs/components/tabs/TabItem.js.map +1 -0
  21. package/lib/commonjs/components/tabs/TabNavigation.js +80 -0
  22. package/lib/commonjs/components/tabs/TabNavigation.js.map +1 -0
  23. package/lib/commonjs/components/tabs/index.js +20 -0
  24. package/lib/commonjs/components/tabs/index.js.map +1 -0
  25. package/lib/commonjs/components/typography/LabelHeader.js +37 -0
  26. package/lib/commonjs/components/typography/LabelHeader.js.map +1 -0
  27. package/lib/commonjs/utils/hooks/useSpringPressProgressValue.js +31 -0
  28. package/lib/commonjs/utils/hooks/useSpringPressProgressValue.js.map +1 -0
  29. package/lib/module/components/common/AnimatedTick.js +2 -1
  30. package/lib/module/components/common/AnimatedTick.js.map +1 -1
  31. package/lib/module/components/icons/Icon.js +124 -120
  32. package/lib/module/components/icons/Icon.js.map +1 -1
  33. package/lib/module/components/icons/svg/IconLight.js +23 -0
  34. package/lib/module/components/icons/svg/IconLight.js.map +1 -0
  35. package/lib/module/components/icons/svg/IconLightFilled.js +23 -0
  36. package/lib/module/components/icons/svg/IconLightFilled.js.map +1 -0
  37. package/lib/module/components/icons/svg/originals/IconLight.svg +3 -0
  38. package/lib/module/components/icons/svg/originals/IconLightFilled.svg +3 -0
  39. package/lib/module/components/index.js +1 -0
  40. package/lib/module/components/index.js.map +1 -1
  41. package/lib/module/components/pictograms/Pictogram.js +31 -29
  42. package/lib/module/components/pictograms/Pictogram.js.map +1 -1
  43. package/lib/module/components/pictograms/svg/PictogramSuccess.js +51 -0
  44. package/lib/module/components/pictograms/svg/PictogramSuccess.js.map +1 -0
  45. package/lib/module/components/pictograms/svg/originals/PictogramSuccess.svg +35 -0
  46. package/lib/module/components/tabs/TabItem.js +114 -0
  47. package/lib/module/components/tabs/TabItem.js.map +1 -0
  48. package/lib/module/components/tabs/TabNavigation.js +73 -0
  49. package/lib/module/components/tabs/TabNavigation.js.map +1 -0
  50. package/lib/module/components/tabs/index.js +3 -0
  51. package/lib/module/components/tabs/index.js.map +1 -0
  52. package/lib/module/components/typography/LabelHeader.js +27 -0
  53. package/lib/module/components/typography/LabelHeader.js.map +1 -0
  54. package/lib/module/utils/hooks/useSpringPressProgressValue.js +22 -0
  55. package/lib/module/utils/hooks/useSpringPressProgressValue.js.map +1 -0
  56. package/lib/typescript/components/common/AnimatedTick.d.ts.map +1 -1
  57. package/lib/typescript/components/icons/Icon.d.ts +2 -0
  58. package/lib/typescript/components/icons/Icon.d.ts.map +1 -1
  59. package/lib/typescript/components/icons/svg/IconLight.d.ts +5 -0
  60. package/lib/typescript/components/icons/svg/IconLight.d.ts.map +1 -0
  61. package/lib/typescript/components/icons/svg/IconLightFilled.d.ts +5 -0
  62. package/lib/typescript/components/icons/svg/IconLightFilled.d.ts.map +1 -0
  63. package/lib/typescript/components/index.d.ts +1 -0
  64. package/lib/typescript/components/index.d.ts.map +1 -1
  65. package/lib/typescript/components/pictograms/Pictogram.d.ts +1 -0
  66. package/lib/typescript/components/pictograms/Pictogram.d.ts.map +1 -1
  67. package/lib/typescript/components/pictograms/svg/PictogramSuccess.d.ts +5 -0
  68. package/lib/typescript/components/pictograms/svg/PictogramSuccess.d.ts.map +1 -0
  69. package/lib/typescript/components/tabs/TabItem.d.ts +19 -0
  70. package/lib/typescript/components/tabs/TabItem.d.ts.map +1 -0
  71. package/lib/typescript/components/tabs/TabNavigation.d.ts +15 -0
  72. package/lib/typescript/components/tabs/TabNavigation.d.ts.map +1 -0
  73. package/lib/typescript/components/tabs/index.d.ts +3 -0
  74. package/lib/typescript/components/tabs/index.d.ts.map +1 -0
  75. package/lib/typescript/components/typography/LabelHeader.d.ts +19 -0
  76. package/lib/typescript/components/typography/LabelHeader.d.ts.map +1 -0
  77. package/lib/typescript/utils/hooks/useSpringPressProgressValue.d.ts +11 -0
  78. package/lib/typescript/utils/hooks/useSpringPressProgressValue.d.ts.map +1 -0
  79. package/package.json +5 -4
  80. package/src/components/common/AnimatedTick.tsx +1 -0
  81. package/src/components/icons/Icon.tsx +124 -120
  82. package/src/components/icons/svg/IconLight.tsx +16 -0
  83. package/src/components/icons/svg/IconLightFilled.tsx +16 -0
  84. package/src/components/icons/svg/originals/IconLight.svg +3 -0
  85. package/src/components/icons/svg/originals/IconLightFilled.svg +3 -0
  86. package/src/components/index.tsx +1 -0
  87. package/src/components/pictograms/Pictogram.tsx +31 -29
  88. package/src/components/pictograms/svg/PictogramSuccess.tsx +49 -0
  89. package/src/components/pictograms/svg/originals/PictogramSuccess.svg +35 -0
  90. package/src/components/tabs/TabItem.tsx +183 -0
  91. package/src/components/tabs/TabNavigation.tsx +114 -0
  92. package/src/components/tabs/index.tsx +2 -0
  93. package/src/components/typography/LabelHeader.tsx +44 -0
  94. package/src/utils/hooks/useSpringPressProgressValue.ts +28 -0
@@ -0,0 +1,183 @@
1
+ import React from "react";
2
+ import { GestureResponderEvent, Pressable, StyleSheet } from "react-native";
3
+ import Animated, {
4
+ Extrapolate,
5
+ interpolate,
6
+ interpolateColor,
7
+ useAnimatedStyle,
8
+ useDerivedValue,
9
+ useSharedValue,
10
+ withSpring
11
+ } from "react-native-reanimated";
12
+ import { WithTestID } from "../../utils/types";
13
+ import { IOIcons, Icon } from "../icons";
14
+ import { HSpacer } from "../spacer";
15
+ import { LabelHeader } from "../typography/LabelHeader";
16
+ import { IOSpringValues, IOColors, hexToRgba, IOScaleValues } from "../../core";
17
+ import { useSpringPressProgressValue } from "../../utils/hooks/useSpringPressProgressValue";
18
+
19
+ type ColorMode = "light" | "dark";
20
+
21
+ export type TabItem = WithTestID<{
22
+ label: string;
23
+ color?: ColorMode;
24
+ selected?: boolean;
25
+ fullWidth?: boolean;
26
+ // Icons
27
+ icon?: IOIcons;
28
+ iconSelected?: IOIcons;
29
+ // Accessibility
30
+ accessibilityLabel: string;
31
+ accessibilityHint?: string;
32
+ // Events
33
+ onPress?: (event: GestureResponderEvent) => void;
34
+ }>;
35
+
36
+ type ColorStates = {
37
+ background: {
38
+ default: string;
39
+ selected: string;
40
+ pressed: string;
41
+ };
42
+ foreground: {
43
+ default: IOColors;
44
+ selected: IOColors;
45
+ };
46
+ };
47
+
48
+ const mapColorStates: Record<NonNullable<TabItem["color"]>, ColorStates> = {
49
+ light: {
50
+ background: {
51
+ default: "#ffffff00",
52
+ selected: IOColors["grey-50"],
53
+ pressed: IOColors["grey-50"]
54
+ },
55
+ foreground: {
56
+ default: "grey-650",
57
+ selected: "black"
58
+ }
59
+ },
60
+ dark: {
61
+ background: {
62
+ default: "#ffffff00",
63
+ selected: IOColors.white,
64
+ pressed: IOColors.white
65
+ },
66
+ foreground: {
67
+ default: "white",
68
+ selected: "grey-850"
69
+ }
70
+ }
71
+ };
72
+
73
+ const TabItem = ({
74
+ label,
75
+ color = "light",
76
+ selected = false,
77
+ fullWidth = false,
78
+ accessibilityLabel,
79
+ accessibilityHint,
80
+ testID,
81
+ onPress,
82
+ icon,
83
+ iconSelected
84
+ }: TabItem) => {
85
+ const {
86
+ progress: progressPressed,
87
+ onPressIn,
88
+ onPressOut
89
+ } = useSpringPressProgressValue(IOSpringValues.selection);
90
+
91
+ const colors = mapColorStates[color];
92
+ const foregroundColor = colors.foreground[selected ? "selected" : "default"];
93
+
94
+ const opaquePressedBackgroundColor = hexToRgba(
95
+ colors.background.pressed,
96
+ 0.1
97
+ );
98
+
99
+ const isSelected: Animated.SharedValue<number> = useSharedValue(0);
100
+ const progressSelected = useDerivedValue(() =>
101
+ withSpring(isSelected.value, IOSpringValues.selection)
102
+ );
103
+
104
+ React.useEffect(() => {
105
+ // eslint-disable-next-line functional/immutable-data
106
+ isSelected.value = selected ? 1 : 0;
107
+ }, [isSelected, selected]);
108
+
109
+ // Interpolate animation values from `pressed` values
110
+ const animatedStyle = useAnimatedStyle(() => {
111
+ // Link color states to the pressed states
112
+ const pressedBackgroundColor = interpolateColor(
113
+ progressPressed.value,
114
+ [0, 1],
115
+ [colors.background.default, opaquePressedBackgroundColor]
116
+ );
117
+
118
+ const selectedBackgroundColor = interpolateColor(
119
+ progressSelected.value,
120
+ [0, 1],
121
+ [opaquePressedBackgroundColor, colors.background.selected]
122
+ );
123
+
124
+ // Scale down button slightly when pressed
125
+ const scale = interpolate(
126
+ progressPressed.value,
127
+ [0, 1],
128
+ [1, IOScaleValues?.basicButton?.pressedState],
129
+ Extrapolate.CLAMP
130
+ );
131
+
132
+ return {
133
+ backgroundColor: selected
134
+ ? selectedBackgroundColor
135
+ : pressedBackgroundColor,
136
+ transform: [{ scale }]
137
+ };
138
+ }, [progressPressed, progressSelected, selected]);
139
+
140
+ const activeIcon = selected ? iconSelected ?? icon : icon;
141
+
142
+ return (
143
+ <Pressable
144
+ accessibilityLabel={accessibilityLabel}
145
+ accessibilityHint={accessibilityHint}
146
+ accessibilityRole={"button"}
147
+ testID={testID}
148
+ onPress={onPress}
149
+ onPressIn={onPressIn}
150
+ onPressOut={onPressOut}
151
+ accessible={true}
152
+ >
153
+ <Animated.View
154
+ style={[styles.container, animatedStyle, fullWidth && styles.fullWidth]}
155
+ >
156
+ {activeIcon && (
157
+ <>
158
+ <Icon name={activeIcon} color={foregroundColor} size={16} />
159
+ <HSpacer size={4} />
160
+ </>
161
+ )}
162
+ <LabelHeader color={foregroundColor}>{label}</LabelHeader>
163
+ </Animated.View>
164
+ </Pressable>
165
+ );
166
+ };
167
+
168
+ const styles = StyleSheet.create({
169
+ container: {
170
+ flexDirection: "row",
171
+ alignItems: "center",
172
+ paddingHorizontal: 16,
173
+ paddingVertical: 8,
174
+ borderRadius: 65,
175
+ justifyContent: "center",
176
+ alignSelf: "flex-start"
177
+ },
178
+ fullWidth: {
179
+ alignSelf: "auto"
180
+ }
181
+ });
182
+
183
+ export { TabItem };
@@ -0,0 +1,114 @@
1
+ import React from "react";
2
+ import { FlexStyle, LayoutChangeEvent, StyleSheet, View } from "react-native";
3
+ import { ScrollView } from "react-native-gesture-handler";
4
+ import { TabItem } from "./TabItem";
5
+
6
+ export type TabNavigationItem = Omit<
7
+ TabItem,
8
+ "onPress" | "color" | "selected" | "accessibilityLabel" | "accessibilityHint"
9
+ >;
10
+
11
+ type TabNavigationChildren =
12
+ | React.ReactElement<TabItem>
13
+ | Array<React.ReactElement<TabItem>>;
14
+
15
+ type TabAlignment = "start" | "center" | "end" | "stretch";
16
+
17
+ type TabNavigation = {
18
+ // Configuration
19
+ color?: TabItem["color"];
20
+ selectedIndex?: number;
21
+ tabAlignment?: TabAlignment;
22
+ // Events
23
+ onItemPress?: (index: number) => void;
24
+ // Tabs
25
+ children: TabNavigationChildren;
26
+ };
27
+
28
+ const itemsJustify: Record<TabAlignment, FlexStyle["justifyContent"]> = {
29
+ start: "flex-start",
30
+ center: "center",
31
+ end: "flex-end",
32
+ stretch: "space-between"
33
+ };
34
+
35
+ const TabNavigation = ({
36
+ color = "light",
37
+ selectedIndex: forceSelectedIndex,
38
+ tabAlignment = "center",
39
+ onItemPress,
40
+ children
41
+ }: TabNavigation) => {
42
+ const [itemMinWidth, setItemMinWidth] = React.useState<number>(0);
43
+ const [selectedIndex, setSelectedIndex] = React.useState(
44
+ forceSelectedIndex ?? 0
45
+ );
46
+
47
+ const handleItemPress = (index: number) => {
48
+ setSelectedIndex(forceSelectedIndex ?? index);
49
+ onItemPress?.(index);
50
+ };
51
+
52
+ const handleItemOnLayout = (event: LayoutChangeEvent) => {
53
+ const { width } = event.nativeEvent.layout;
54
+ setItemMinWidth(current => Math.max(current, width));
55
+ };
56
+
57
+ const stretchItems = tabAlignment === "stretch";
58
+
59
+ const wrapChild = (child: React.ReactElement<TabItem>, index: number = 0) => (
60
+ <View
61
+ key={index}
62
+ style={[
63
+ styles.item,
64
+ {
65
+ marginEnd: index === React.Children.count(children) - 1 ? 0 : 8
66
+ },
67
+ stretchItems && {
68
+ minWidth: itemMinWidth
69
+ }
70
+ ]}
71
+ onLayout={handleItemOnLayout}
72
+ >
73
+ {React.cloneElement<TabItem>(child, {
74
+ onPress: event => {
75
+ child.props.onPress?.(event);
76
+ handleItemPress(index);
77
+ },
78
+ selected: selectedIndex === index,
79
+ color
80
+ })}
81
+ </View>
82
+ );
83
+
84
+ return (
85
+ <ScrollView
86
+ horizontal={true}
87
+ centerContent={true}
88
+ showsHorizontalScrollIndicator={false}
89
+ contentContainerStyle={[
90
+ styles.container,
91
+ {
92
+ justifyContent: itemsJustify[tabAlignment]
93
+ }
94
+ ]}
95
+ >
96
+ {Array.isArray(children) ? children.map(wrapChild) : wrapChild(children)}
97
+ </ScrollView>
98
+ );
99
+ };
100
+
101
+ const styles = StyleSheet.create({
102
+ container: {
103
+ flexGrow: 1,
104
+ paddingHorizontal: 24
105
+ },
106
+ item: {
107
+ flexGrow: 0,
108
+ flexShrink: 1,
109
+ flexBasis: 100,
110
+ alignItems: "center"
111
+ }
112
+ });
113
+
114
+ export { TabNavigation };
@@ -0,0 +1,2 @@
1
+ export { TabItem } from "./TabItem";
2
+ export { TabNavigation } from "./TabNavigation";
@@ -0,0 +1,44 @@
1
+ import * as React from "react";
2
+ import { IOFontFamily, IOFontWeight } from "../../utils/fonts";
3
+ import { IOTheme, IOThemeLight } from "../../core";
4
+ import { useTypographyFactory } from "./Factory";
5
+ import { ExternalTypographyProps, TypographyProps } from "./common";
6
+
7
+ type AllowedColors =
8
+ | IOTheme["textBody-default"]
9
+ | "grey-650"
10
+ | "grey-850"
11
+ | "white"
12
+ | "black";
13
+ type AllowedWeight = Extract<IOFontWeight, "Regular">;
14
+
15
+ type OwnProps = ExternalTypographyProps<
16
+ TypographyProps<AllowedWeight, AllowedColors>
17
+ >;
18
+
19
+ /* Common typographic styles */
20
+ export const labelHeaderFontSize = 14;
21
+ export const labelHeaderLineHeight = 18;
22
+ export const labelHeaderDefaultColor: AllowedColors =
23
+ IOThemeLight["textBody-default"];
24
+ /* New typographic styles */
25
+ const labelHeaderFontName: IOFontFamily = "ReadexPro";
26
+ const labelHeaderDefaultWeight: AllowedWeight = "Regular";
27
+
28
+ /**
29
+ * Typography component to render `LabelHeader` text with font size {@link fontSize} and fontFamily {@link fontName}.
30
+ * default values(if not defined) are weight: `Regular`, color: `bluegreyDark`
31
+ * @param props
32
+ * @constructor
33
+ */
34
+ export const LabelHeader: React.FunctionComponent<OwnProps> = props =>
35
+ useTypographyFactory<AllowedWeight, AllowedColors>({
36
+ ...props,
37
+ defaultWeight: labelHeaderDefaultWeight,
38
+ defaultColor: labelHeaderDefaultColor,
39
+ font: labelHeaderFontName,
40
+ fontStyle: {
41
+ fontSize: labelHeaderFontSize,
42
+ lineHeight: labelHeaderLineHeight
43
+ }
44
+ });
@@ -0,0 +1,28 @@
1
+ import * as React from "react";
2
+ import Animated, {
3
+ useDerivedValue,
4
+ useSharedValue,
5
+ withSpring
6
+ } from "react-native-reanimated";
7
+ import { IOSpringValues } from "../../core";
8
+
9
+ export const useSpringPressProgressValue = (
10
+ springValue = IOSpringValues.button
11
+ ) => {
12
+ const isPressed: Animated.SharedValue<number> = useSharedValue(0);
13
+
14
+ const progress = useDerivedValue(() =>
15
+ withSpring(isPressed.value, springValue)
16
+ );
17
+
18
+ const onPressIn = React.useCallback(() => {
19
+ // eslint-disable-next-line functional/immutable-data
20
+ isPressed.value = 1;
21
+ }, [isPressed]);
22
+ const onPressOut = React.useCallback(() => {
23
+ // eslint-disable-next-line functional/immutable-data
24
+ isPressed.value = 0;
25
+ }, [isPressed]);
26
+
27
+ return { onPressIn, onPressOut, progress };
28
+ };