@sendbird/uikit-react-native-foundation 2.1.0 → 2.3.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 (123) hide show
  1. package/lib/commonjs/assets/icon/icon-radio-off.png +0 -0
  2. package/lib/commonjs/assets/icon/icon-radio-off@2x.png +0 -0
  3. package/lib/commonjs/assets/icon/icon-radio-off@3x.png +0 -0
  4. package/lib/commonjs/assets/icon/icon-radio-on.png +0 -0
  5. package/lib/commonjs/assets/icon/icon-radio-on@2x.png +0 -0
  6. package/lib/commonjs/assets/icon/icon-radio-on@3x.png +0 -0
  7. package/lib/commonjs/assets/icon/index.js +2 -0
  8. package/lib/commonjs/assets/icon/index.js.map +1 -1
  9. package/lib/commonjs/components/Modal/index.js +3 -3
  10. package/lib/commonjs/components/Modal/index.js.map +1 -1
  11. package/lib/commonjs/components/RegexText/index.js +50 -0
  12. package/lib/commonjs/components/RegexText/index.js.map +1 -0
  13. package/lib/commonjs/components/URLParsedText/index.js +15 -19
  14. package/lib/commonjs/components/URLParsedText/index.js.map +1 -1
  15. package/lib/commonjs/index.js +8 -0
  16. package/lib/commonjs/index.js.map +1 -1
  17. package/lib/commonjs/styles/createStyleSheet.js +2 -0
  18. package/lib/commonjs/styles/createStyleSheet.js.map +1 -1
  19. package/lib/commonjs/theme/DarkUIKitTheme.js +22 -0
  20. package/lib/commonjs/theme/DarkUIKitTheme.js.map +1 -1
  21. package/lib/commonjs/theme/LightUIKitTheme.js +22 -0
  22. package/lib/commonjs/theme/LightUIKitTheme.js.map +1 -1
  23. package/lib/commonjs/types.js.map +1 -1
  24. package/lib/commonjs/ui/Avatar/AvatarGroup.js +6 -7
  25. package/lib/commonjs/ui/Avatar/AvatarGroup.js.map +1 -1
  26. package/lib/commonjs/ui/Badge/index.js +1 -1
  27. package/lib/commonjs/ui/Badge/index.js.map +1 -1
  28. package/lib/commonjs/ui/BottomSheet/index.js +5 -2
  29. package/lib/commonjs/ui/BottomSheet/index.js.map +1 -1
  30. package/lib/commonjs/ui/Dialog/index.js +2 -1
  31. package/lib/commonjs/ui/Dialog/index.js.map +1 -1
  32. package/lib/commonjs/ui/GroupChannelPreview/index.js +16 -8
  33. package/lib/commonjs/ui/GroupChannelPreview/index.js.map +1 -1
  34. package/lib/module/assets/icon/icon-radio-off.png +0 -0
  35. package/lib/module/assets/icon/icon-radio-off@2x.png +0 -0
  36. package/lib/module/assets/icon/icon-radio-off@3x.png +0 -0
  37. package/lib/module/assets/icon/icon-radio-on.png +0 -0
  38. package/lib/module/assets/icon/icon-radio-on@2x.png +0 -0
  39. package/lib/module/assets/icon/icon-radio-on@3x.png +0 -0
  40. package/lib/module/assets/icon/index.js +2 -0
  41. package/lib/module/assets/icon/index.js.map +1 -1
  42. package/lib/module/components/Modal/index.js +3 -3
  43. package/lib/module/components/Modal/index.js.map +1 -1
  44. package/lib/module/components/RegexText/index.js +38 -0
  45. package/lib/module/components/RegexText/index.js.map +1 -0
  46. package/lib/module/components/URLParsedText/index.js +13 -15
  47. package/lib/module/components/URLParsedText/index.js.map +1 -1
  48. package/lib/module/index.js +1 -0
  49. package/lib/module/index.js.map +1 -1
  50. package/lib/module/styles/createStyleSheet.js +2 -0
  51. package/lib/module/styles/createStyleSheet.js.map +1 -1
  52. package/lib/module/theme/DarkUIKitTheme.js +22 -0
  53. package/lib/module/theme/DarkUIKitTheme.js.map +1 -1
  54. package/lib/module/theme/LightUIKitTheme.js +22 -0
  55. package/lib/module/theme/LightUIKitTheme.js.map +1 -1
  56. package/lib/module/types.js.map +1 -1
  57. package/lib/module/ui/Avatar/AvatarGroup.js +5 -4
  58. package/lib/module/ui/Avatar/AvatarGroup.js.map +1 -1
  59. package/lib/module/ui/Badge/index.js +2 -2
  60. package/lib/module/ui/Badge/index.js.map +1 -1
  61. package/lib/module/ui/BottomSheet/index.js +5 -2
  62. package/lib/module/ui/BottomSheet/index.js.map +1 -1
  63. package/lib/module/ui/Dialog/index.js +2 -1
  64. package/lib/module/ui/Dialog/index.js.map +1 -1
  65. package/lib/module/ui/GroupChannelPreview/index.js +16 -8
  66. package/lib/module/ui/GroupChannelPreview/index.js.map +1 -1
  67. package/lib/typescript/src/assets/icon/index.d.ts +2 -0
  68. package/lib/typescript/src/components/Divider/index.d.ts +1 -1
  69. package/lib/typescript/src/components/Icon/index.d.ts +2 -2
  70. package/lib/typescript/src/components/Image/index.d.ts +1 -1
  71. package/lib/typescript/src/components/Modal/index.d.ts +3 -2
  72. package/lib/typescript/src/components/RegexText/index.d.ts +16 -0
  73. package/lib/typescript/src/components/Switch/index.d.ts +1 -1
  74. package/lib/typescript/src/components/Text/index.d.ts +2 -2
  75. package/lib/typescript/src/components/URLParsedText/index.d.ts +2 -2
  76. package/lib/typescript/src/index.d.ts +1 -0
  77. package/lib/typescript/src/styles/HeaderStyleContext.d.ts +2 -2
  78. package/lib/typescript/src/styles/createTypography.d.ts +1 -1
  79. package/lib/typescript/src/theme/UIKitThemeProvider.d.ts +1 -1
  80. package/lib/typescript/src/theme/createTheme.d.ts +1 -1
  81. package/lib/typescript/src/types.d.ts +14 -10
  82. package/lib/typescript/src/ui/ActionMenu/index.d.ts +2 -2
  83. package/lib/typescript/src/ui/Alert/index.d.ts +2 -2
  84. package/lib/typescript/src/ui/Avatar/AvatarGroup.d.ts +1 -1
  85. package/lib/typescript/src/ui/Avatar/AvatarIcon.d.ts +1 -1
  86. package/lib/typescript/src/ui/Avatar/index.d.ts +2 -2
  87. package/lib/typescript/src/ui/Badge/index.d.ts +1 -1
  88. package/lib/typescript/src/ui/BottomSheet/index.d.ts +7 -3
  89. package/lib/typescript/src/ui/Button/index.d.ts +1 -1
  90. package/lib/typescript/src/ui/ChannelFrozenBanner/index.d.ts +1 -1
  91. package/lib/typescript/src/ui/Dialog/DialogBox.d.ts +1 -1
  92. package/lib/typescript/src/ui/Dialog/DialogSheet.d.ts +2 -2
  93. package/lib/typescript/src/ui/Dialog/index.d.ts +4 -4
  94. package/lib/typescript/src/ui/GroupChannelPreview/index.d.ts +4 -2
  95. package/lib/typescript/src/ui/Header/index.d.ts +2 -2
  96. package/lib/typescript/src/ui/LoadingSpinner/index.d.ts +1 -1
  97. package/lib/typescript/src/ui/MenuBar/index.d.ts +1 -1
  98. package/lib/typescript/src/ui/OutlinedButton/index.d.ts +1 -1
  99. package/lib/typescript/src/ui/Placeholder/index.d.ts +1 -1
  100. package/lib/typescript/src/ui/ProfileCard/index.d.ts +1 -1
  101. package/lib/typescript/src/ui/Prompt/index.d.ts +2 -2
  102. package/lib/typescript/src/ui/Toast/index.d.ts +3 -3
  103. package/package.json +6 -5
  104. package/src/assets/icon/icon-radio-off.png +0 -0
  105. package/src/assets/icon/icon-radio-off@2x.png +0 -0
  106. package/src/assets/icon/icon-radio-off@3x.png +0 -0
  107. package/src/assets/icon/icon-radio-on.png +0 -0
  108. package/src/assets/icon/icon-radio-on@2x.png +0 -0
  109. package/src/assets/icon/icon-radio-on@3x.png +0 -0
  110. package/src/assets/icon/index.ts +2 -0
  111. package/src/components/Modal/index.tsx +7 -6
  112. package/src/components/RegexText/index.tsx +48 -0
  113. package/src/components/URLParsedText/index.tsx +22 -24
  114. package/src/index.ts +1 -0
  115. package/src/styles/createStyleSheet.ts +2 -0
  116. package/src/theme/DarkUIKitTheme.ts +22 -0
  117. package/src/theme/LightUIKitTheme.ts +22 -0
  118. package/src/types.ts +6 -1
  119. package/src/ui/Avatar/AvatarGroup.tsx +10 -6
  120. package/src/ui/Badge/index.tsx +2 -2
  121. package/src/ui/BottomSheet/index.tsx +4 -1
  122. package/src/ui/Dialog/index.tsx +1 -0
  123. package/src/ui/GroupChannelPreview/index.tsx +18 -7
@@ -44,6 +44,8 @@ const IconAssets = {
44
44
  'play': require('./icon-play.png'),
45
45
  'plus': require('./icon-plus.png'),
46
46
  'question': require('./icon-question.png'),
47
+ 'radio-off': require('./icon-radio-off.png'),
48
+ 'radio-on': require('./icon-radio-on.png'),
47
49
  'refresh': require('./icon-refresh.png'),
48
50
  'remove': require('./icon-remove.png'),
49
51
  'reply-filled': require('./icon-reply-filled.png'),
@@ -19,8 +19,9 @@ import createStyleSheet from '../../styles/createStyleSheet';
19
19
  import useHeaderStyle from '../../styles/useHeaderStyle';
20
20
  import useUIKitTheme from '../../theme/useUIKitTheme';
21
21
 
22
+ type ModalAnimationType = 'slide' | 'slide-no-gesture' | 'fade';
22
23
  type Props = {
23
- type?: 'slide' | 'fade';
24
+ type?: ModalAnimationType;
24
25
  onClose: () => void;
25
26
  backgroundStyle?: StyleProp<ViewStyle>;
26
27
  disableBackgroundClose?: boolean;
@@ -117,12 +118,12 @@ const isHideGesture = (distanceY: number, velocityY: number) => {
117
118
  return distanceY > 125 || (distanceY > 0 && velocityY > 0.1);
118
119
  };
119
120
  const useModalPanResponder = (
120
- type: 'slide' | 'fade',
121
+ type: ModalAnimationType,
121
122
  translateY: Animated.Value,
122
123
  show: () => void,
123
124
  hide: () => void,
124
125
  ) => {
125
- if (type === 'fade') return { panHandlers: {} };
126
+ if (type === 'fade' || type === 'slide-no-gesture') return { panHandlers: {} };
126
127
  return React.useRef(
127
128
  PanResponder.create({
128
129
  onMoveShouldSetPanResponderCapture: (_, { dy }) => dy > 8,
@@ -137,15 +138,15 @@ const useModalPanResponder = (
137
138
  ).current;
138
139
  };
139
140
 
140
- const useModalAnimation = (type: 'slide' | 'fade') => {
141
- const initialY = type === 'slide' ? Dimensions.get('window').height : 0;
141
+ const useModalAnimation = (type: ModalAnimationType) => {
142
+ const initialY = type === 'fade' ? 0 : Dimensions.get('window').height;
142
143
  const baseAnimBackground = useRef(new Animated.Value(0)).current;
143
144
  const baseAnimContent = useRef(new Animated.Value(initialY)).current;
144
145
 
145
146
  const content = {
146
147
  opacity: baseAnimBackground.interpolate({
147
148
  inputRange: [0, 1],
148
- outputRange: [type === 'slide' ? 1 : 0, 1],
149
+ outputRange: [type === 'fade' ? 0 : 1, 1],
149
150
  }),
150
151
  translateY: baseAnimContent,
151
152
  };
@@ -0,0 +1,48 @@
1
+ import React from 'react';
2
+
3
+ import { replaceWithRegex } from '@sendbird/uikit-utils';
4
+
5
+ import Text, { TextProps } from '../Text';
6
+
7
+ interface Pattern {
8
+ regex: RegExp;
9
+ replacer(params: {
10
+ match: string;
11
+ groups: string[];
12
+ index: number;
13
+ keyPrefix: string;
14
+ parentProps?: TextProps;
15
+ }): string | JSX.Element;
16
+ }
17
+
18
+ type Props = { patterns: Pattern[] } & TextProps;
19
+
20
+ const RegexText = ({ children, patterns, ...props }: Props) => {
21
+ if (patterns.length === 0 || typeof children !== 'string') return <>{children}</>;
22
+
23
+ const matchedTexts: Array<string | JSX.Element> = [children];
24
+
25
+ patterns.forEach(({ regex, replacer }, patterIndex) => {
26
+ const matchedTextsTemp = matchedTexts.concat();
27
+ let offset = 0;
28
+ matchedTextsTemp.forEach((text, index) => {
29
+ if (typeof text === 'string' && text) {
30
+ const children = replaceWithRegex(
31
+ text,
32
+ regex,
33
+ (params) => replacer({ ...params, parentProps: props, keyPrefix: index + params.keyPrefix }),
34
+ String(patterIndex),
35
+ );
36
+
37
+ if (children.length > 1) {
38
+ matchedTexts.splice(index + offset, 1, ...children);
39
+ offset += children.length - 1;
40
+ }
41
+ }
42
+ });
43
+ });
44
+
45
+ return <Text {...props}>{matchedTexts}</Text>;
46
+ };
47
+
48
+ export default RegexText;
@@ -1,4 +1,4 @@
1
- import React, { useMemo } from 'react';
1
+ import React from 'react';
2
2
  import { Linking } from 'react-native';
3
3
 
4
4
  import { Logger, replaceUrlAsComponents } from '@sendbird/uikit-utils';
@@ -19,30 +19,28 @@ type Props = TextProps & {
19
19
  strict?: boolean;
20
20
  };
21
21
  const URLParsedText = ({ children, onPressUrl = openUrl, strict, ...props }: Props) => {
22
- const parsedChildren = useMemo((): React.ReactNode => {
23
- return React.Children.map(React.Children.toArray(children), (child) => {
24
- if (typeof child === 'string') {
25
- return replaceUrlAsComponents(
26
- child,
27
- (url) => {
28
- return (
29
- <Text
30
- {...props}
31
- suppressHighlighting
32
- onPress={() => onPressUrl?.(url, url.startsWith('http'))}
33
- style={[props.style, styles.url]}
34
- >
35
- {url}
36
- </Text>
37
- );
38
- },
39
- strict,
40
- );
41
- }
22
+ const parsedChildren = React.Children.map(React.Children.toArray(children), (child) => {
23
+ if (typeof child === 'string') {
24
+ return replaceUrlAsComponents(
25
+ child,
26
+ (url) => {
27
+ return (
28
+ <Text
29
+ {...props}
30
+ suppressHighlighting
31
+ onPress={() => onPressUrl?.(url, url.startsWith('http'))}
32
+ style={[props.style, styles.url]}
33
+ >
34
+ {url}
35
+ </Text>
36
+ );
37
+ },
38
+ strict,
39
+ );
40
+ }
42
41
 
43
- return child;
44
- });
45
- }, [children]);
42
+ return child;
43
+ });
46
44
 
47
45
  return <Text {...props}>{parsedChildren}</Text>;
48
46
  };
package/src/index.ts CHANGED
@@ -6,6 +6,7 @@ export { default as Divider } from './components/Divider';
6
6
  export { default as Icon } from './components/Icon';
7
7
  export { default as Image } from './components/Image';
8
8
  export { default as Modal } from './components/Modal';
9
+ export { default as RegexText } from './components/RegexText';
9
10
  export { default as Switch } from './components/Switch';
10
11
  export { default as Text } from './components/Text';
11
12
  export { default as TextInput } from './components/TextInput';
@@ -12,7 +12,9 @@ const preProcessor: Partial<StylePreprocessor> = {
12
12
  'lineHeight': DEFAULT_SCALE_FACTOR,
13
13
  'borderRadius': DEFAULT_SCALE_FACTOR,
14
14
  'minWidth': SCALE_FACTOR_WITH_STR,
15
+ 'maxWidth': SCALE_FACTOR_WITH_STR,
15
16
  'minHeight': SCALE_FACTOR_WITH_STR,
17
+ 'maxHeight': SCALE_FACTOR_WITH_STR,
16
18
  'height': SCALE_FACTOR_WITH_STR,
17
19
  'width': SCALE_FACTOR_WITH_STR,
18
20
  'padding': SCALE_FACTOR_WITH_STR,
@@ -179,6 +179,28 @@ const DarkUIKitTheme = createTheme({
179
179
  },
180
180
  },
181
181
  },
182
+ reaction: {
183
+ default: {
184
+ enabled: {
185
+ background: palette.transparent,
186
+ highlight: palette.onBackgroundDark03,
187
+ },
188
+ selected: {
189
+ background: palette.primary500,
190
+ highlight: palette.primary200,
191
+ },
192
+ },
193
+ rounded: {
194
+ enabled: {
195
+ background: palette.background400,
196
+ highlight: palette.transparent,
197
+ },
198
+ selected: {
199
+ background: palette.primary500,
200
+ highlight: palette.transparent,
201
+ },
202
+ },
203
+ },
182
204
  },
183
205
  }),
184
206
  });
@@ -179,6 +179,28 @@ const LightUIKitTheme = createTheme({
179
179
  },
180
180
  },
181
181
  },
182
+ reaction: {
183
+ default: {
184
+ enabled: {
185
+ background: palette.transparent,
186
+ highlight: palette.onBackgroundLight03,
187
+ },
188
+ selected: {
189
+ background: palette.primary100,
190
+ highlight: palette.primary300,
191
+ },
192
+ },
193
+ rounded: {
194
+ enabled: {
195
+ background: palette.background100,
196
+ highlight: palette.transparent,
197
+ },
198
+ selected: {
199
+ background: palette.primary100,
200
+ highlight: palette.transparent,
201
+ },
202
+ },
203
+ },
182
204
  },
183
205
  }),
184
206
  });
package/src/types.ts CHANGED
@@ -40,7 +40,8 @@ export type Component =
40
40
  | 'Message'
41
41
  | 'DateSeparator'
42
42
  | 'GroupChannelPreview'
43
- | 'ProfileCard';
43
+ | 'ProfileCard'
44
+ | 'Reaction';
44
45
 
45
46
  export type GetColorTree<
46
47
  Tree extends {
@@ -68,6 +69,7 @@ export type ComponentColorTree = GetColorTree<{
68
69
  DateSeparator: 'default';
69
70
  GroupChannelPreview: 'default';
70
71
  ProfileCard: 'default';
72
+ Reaction: 'default' | 'rounded';
71
73
  };
72
74
  State: {
73
75
  Header: 'none';
@@ -80,6 +82,7 @@ export type ComponentColorTree = GetColorTree<{
80
82
  DateSeparator: 'none';
81
83
  GroupChannelPreview: 'none';
82
84
  ProfileCard: 'none';
85
+ Reaction: 'enabled' | 'selected';
83
86
  };
84
87
  ColorPart: {
85
88
  Header: 'background' | 'borderBottom';
@@ -101,6 +104,7 @@ export type ComponentColorTree = GetColorTree<{
101
104
  | 'bodyIconBackground'
102
105
  | 'separator';
103
106
  ProfileCard: 'textUsername' | 'textBodyLabel' | 'textBody' | 'background';
107
+ Reaction: 'background' | 'highlight';
104
108
  };
105
109
  }>;
106
110
  export type ComponentColors<T extends Component> = {
@@ -145,6 +149,7 @@ export interface UIKitColors {
145
149
  dateSeparator: ComponentColors<'DateSeparator'>;
146
150
  groupChannelPreview: ComponentColors<'GroupChannelPreview'>;
147
151
  profileCard: ComponentColors<'ProfileCard'>;
152
+ reaction: ComponentColors<'Reaction'>;
148
153
  };
149
154
  }
150
155
 
@@ -1,4 +1,4 @@
1
- import React, { useMemo } from 'react';
1
+ import React, { ReactElement } from 'react';
2
2
  import { StyleProp, View, ViewStyle } from 'react-native';
3
3
 
4
4
  const MAX = 4;
@@ -27,13 +27,13 @@ const AvatarGroup = ({ children, containerStyle, size = 56 }: Props) => {
27
27
  );
28
28
  }
29
29
 
30
- const avatars = useMemo(() => {
30
+ const renderAvatars = () => {
31
31
  return (
32
32
  React.Children.map(children, (child, index) => {
33
33
  if (index + 1 > MAX) return child;
34
34
  if (!React.isValidElement(child)) return child;
35
35
 
36
- if (childAmount === 1) return React.cloneElement(child, { size, containerStyle });
36
+ if (childAmount === 1) return React.cloneElement(child as ReactElement, { size, containerStyle });
37
37
 
38
38
  const top = getTopPoint(index, childAmount) * size;
39
39
  const left = getLeftPoint(index) * size;
@@ -44,16 +44,20 @@ const AvatarGroup = ({ children, containerStyle, size = 56 }: Props) => {
44
44
 
45
45
  return (
46
46
  <View style={{ overflow: 'hidden', position: 'absolute', top, left, width, height }}>
47
- {React.cloneElement(child, { size, square: true, containerStyle: { left: innerLeft, top: innerTop } })}
47
+ {React.cloneElement(child as ReactElement, {
48
+ size,
49
+ square: true,
50
+ containerStyle: { left: innerLeft, top: innerTop },
51
+ })}
48
52
  </View>
49
53
  );
50
54
  })?.slice(0, 4) ?? []
51
55
  );
52
- }, [children]);
56
+ };
53
57
 
54
58
  return (
55
59
  <View style={[containerStyle, { overflow: 'hidden', width: size, height: size, borderRadius: size }]}>
56
- {avatars}
60
+ {renderAvatars()}
57
61
  </View>
58
62
  );
59
63
  };
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { Platform, StyleProp, View, ViewStyle } from 'react-native';
3
3
 
4
- import { truncatedBadgeCount } from '@sendbird/uikit-utils';
4
+ import { truncatedCount } from '@sendbird/uikit-utils';
5
5
 
6
6
  import Text from '../../components/Text';
7
7
  import createStyleSheet from '../../styles/createStyleSheet';
@@ -29,7 +29,7 @@ const Badge = ({ count, maxCount, badgeColor, textColor, style, size = 'default'
29
29
  ]}
30
30
  >
31
31
  <Text caption1 color={textColor ?? colors.ui.badge.default.none.text}>
32
- {truncatedBadgeCount(count, maxCount)}
32
+ {truncatedCount(count, maxCount)}
33
33
  </Text>
34
34
  </View>
35
35
  );
@@ -7,6 +7,7 @@ import Modal from '../../components/Modal';
7
7
  import useHeaderStyle from '../../styles/useHeaderStyle';
8
8
  import DialogSheet from '../Dialog/DialogSheet';
9
9
 
10
+ type HeaderProps = { onClose: () => Promise<void> };
10
11
  export type BottomSheetItem = {
11
12
  sheetItems: {
12
13
  icon?: keyof typeof Icon.Assets;
@@ -15,6 +16,7 @@ export type BottomSheetItem = {
15
16
  titleColor?: string;
16
17
  onPress: () => void;
17
18
  }[];
19
+ HeaderComponent?: (props: HeaderProps) => JSX.Element;
18
20
  };
19
21
  type Props = {
20
22
  visible: boolean;
@@ -22,7 +24,7 @@ type Props = {
22
24
  onError?: (error: unknown) => void;
23
25
  onDismiss?: () => void;
24
26
  } & BottomSheetItem;
25
- const BottomSheet = ({ onDismiss, onHide, visible, sheetItems }: Props) => {
27
+ const BottomSheet = ({ onDismiss, onHide, visible, sheetItems, HeaderComponent }: Props) => {
26
28
  const { statusBarTranslucent } = useHeaderStyle();
27
29
  const { width } = useWindowDimensions();
28
30
  const { bottom, left, right } = useSafeAreaInsets();
@@ -36,6 +38,7 @@ const BottomSheet = ({ onDismiss, onHide, visible, sheetItems }: Props) => {
36
38
  backgroundStyle={{ alignItems: 'center', justifyContent: 'flex-end' }}
37
39
  >
38
40
  <DialogSheet style={{ width, paddingBottom: bottom }}>
41
+ {HeaderComponent && <HeaderComponent onClose={onHide} />}
39
42
  {sheetItems.map(({ onPress, ...props }, idx) => (
40
43
  <TouchableOpacity
41
44
  activeOpacity={0.75}
@@ -154,6 +154,7 @@ export const DialogProvider = ({ defaultLabels, children }: Props) => {
154
154
  onDismiss={consumeQueue}
155
155
  visible={visibleState.current}
156
156
  sheetItems={workingDialogJob.current.props.sheetItems}
157
+ HeaderComponent={workingDialogJob.current.props.HeaderComponent}
157
158
  />
158
159
  )}
159
160
  </BottomSheetContext.Provider>
@@ -29,6 +29,8 @@ type Props = {
29
29
  frozen?: boolean;
30
30
  notificationOff?: boolean;
31
31
  broadcast?: boolean;
32
+ mentioned?: boolean;
33
+ mentionTrigger?: string;
32
34
  };
33
35
 
34
36
  const GroupChannelPreview = ({
@@ -45,6 +47,8 @@ const GroupChannelPreview = ({
45
47
  frozen,
46
48
  notificationOff,
47
49
  broadcast,
50
+ mentioned,
51
+ mentionTrigger = '@',
48
52
  }: Props) => {
49
53
  const { colors } = useUIKitTheme();
50
54
  const color = colors.ui.groupChannelPreview;
@@ -115,7 +119,14 @@ const GroupChannelPreview = ({
115
119
  </Text>
116
120
  </View>
117
121
  </View>
118
- <View>{badgeCount > 0 && <Badge count={badgeCount} maxCount={maxBadgeCount} />}</View>
122
+ <View style={styles.unreadContainer}>
123
+ {mentioned && (
124
+ <Text h2 color={colors.ui.badge.default.none.background} style={styles.unreadMention}>
125
+ {mentionTrigger}
126
+ </Text>
127
+ )}
128
+ {badgeCount > 0 && <Badge count={badgeCount} maxCount={maxBadgeCount} />}
129
+ </View>
119
130
  </View>
120
131
  <Separator color={color.default.none.separator} />
121
132
  </View>
@@ -204,12 +215,12 @@ const styles = createStyleSheet({
204
215
  height: 26,
205
216
  marginRight: 4,
206
217
  },
207
- unreadBadge: {
208
- minWidth: 20,
209
- minHeight: 20,
210
- borderRadius: 99,
211
- alignItems: 'center',
212
- justifyContent: 'center',
218
+ unreadContainer: {
219
+ flexDirection: 'row',
220
+ alignItems: 'flex-start',
221
+ },
222
+ unreadMention: {
223
+ marginRight: 4,
213
224
  },
214
225
  separator: {
215
226
  position: 'absolute',