@sendbird/uikit-react-native-foundation 2.0.3 → 2.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.
- package/lib/commonjs/assets/icon/{icon-moderations.png → icon-moderation.png} +0 -0
- package/lib/commonjs/assets/icon/{icon-moderations@2x.png → icon-moderation@2x.png} +0 -0
- package/lib/commonjs/assets/icon/{icon-moderations@3x.png → icon-moderation@3x.png} +0 -0
- package/lib/commonjs/assets/icon/icon-radio-off.png +0 -0
- package/lib/commonjs/assets/icon/icon-radio-off@2x.png +0 -0
- package/lib/commonjs/assets/icon/icon-radio-off@3x.png +0 -0
- package/lib/commonjs/assets/icon/icon-radio-on.png +0 -0
- package/lib/commonjs/assets/icon/icon-radio-on@2x.png +0 -0
- package/lib/commonjs/assets/icon/icon-radio-on@3x.png +0 -0
- package/lib/commonjs/assets/icon/index.js +3 -1
- package/lib/commonjs/assets/icon/index.js.map +1 -1
- package/lib/commonjs/components/Modal/index.js +4 -3
- package/lib/commonjs/components/Modal/index.js.map +1 -1
- package/lib/commonjs/components/RegexText/index.js +50 -0
- package/lib/commonjs/components/RegexText/index.js.map +1 -0
- package/lib/commonjs/components/URLParsedText/index.js +15 -19
- package/lib/commonjs/components/URLParsedText/index.js.map +1 -1
- package/lib/commonjs/index.js +27 -27
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/styles/HeaderStyleContext.js.map +1 -1
- package/lib/commonjs/styles/createStyleSheet.js +2 -0
- package/lib/commonjs/styles/createStyleSheet.js.map +1 -1
- package/lib/commonjs/theme/DarkUIKitTheme.js +32 -0
- package/lib/commonjs/theme/DarkUIKitTheme.js.map +1 -1
- package/lib/commonjs/theme/LightUIKitTheme.js +32 -0
- package/lib/commonjs/theme/LightUIKitTheme.js.map +1 -1
- package/lib/commonjs/types.js.map +1 -1
- package/lib/commonjs/ui/ActionMenu/index.js +1 -1
- package/lib/commonjs/ui/ActionMenu/index.js.map +1 -1
- package/lib/commonjs/ui/Avatar/AvatarGroup.js +6 -7
- package/lib/commonjs/ui/Avatar/AvatarGroup.js.map +1 -1
- package/lib/commonjs/ui/Badge/index.js +1 -1
- package/lib/commonjs/ui/Badge/index.js.map +1 -1
- package/lib/commonjs/ui/BottomSheet/index.js +5 -2
- package/lib/commonjs/ui/BottomSheet/index.js.map +1 -1
- package/lib/commonjs/ui/Dialog/index.js +2 -1
- package/lib/commonjs/ui/Dialog/index.js.map +1 -1
- package/lib/commonjs/ui/GroupChannelPreview/index.js +26 -9
- package/lib/commonjs/ui/GroupChannelPreview/index.js.map +1 -1
- package/lib/commonjs/ui/Header/index.js +3 -2
- package/lib/commonjs/ui/Header/index.js.map +1 -1
- package/lib/commonjs/ui/MenuBar/index.js +2 -0
- package/lib/commonjs/ui/MenuBar/index.js.map +1 -1
- package/lib/commonjs/ui/OutlinedButton/index.js +57 -0
- package/lib/commonjs/ui/OutlinedButton/index.js.map +1 -0
- package/lib/commonjs/ui/ProfileCard/index.js +94 -0
- package/lib/commonjs/ui/ProfileCard/index.js.map +1 -0
- package/lib/module/assets/icon/{icon-moderations.png → icon-moderation.png} +0 -0
- package/lib/module/assets/icon/{icon-moderations@2x.png → icon-moderation@2x.png} +0 -0
- package/lib/module/assets/icon/{icon-moderations@3x.png → icon-moderation@3x.png} +0 -0
- package/lib/module/assets/icon/icon-radio-off.png +0 -0
- package/lib/module/assets/icon/icon-radio-off@2x.png +0 -0
- package/lib/module/assets/icon/icon-radio-off@3x.png +0 -0
- package/lib/module/assets/icon/icon-radio-on.png +0 -0
- package/lib/module/assets/icon/icon-radio-on@2x.png +0 -0
- package/lib/module/assets/icon/icon-radio-on@3x.png +0 -0
- package/lib/module/assets/icon/index.js +3 -1
- package/lib/module/assets/icon/index.js.map +1 -1
- package/lib/module/components/Modal/index.js +4 -3
- package/lib/module/components/Modal/index.js.map +1 -1
- package/lib/module/components/RegexText/index.js +38 -0
- package/lib/module/components/RegexText/index.js.map +1 -0
- package/lib/module/components/URLParsedText/index.js +13 -15
- package/lib/module/components/URLParsedText/index.js.map +1 -1
- package/lib/module/index.js +7 -4
- package/lib/module/index.js.map +1 -1
- package/lib/module/styles/HeaderStyleContext.js.map +1 -1
- package/lib/module/styles/createStyleSheet.js +2 -0
- package/lib/module/styles/createStyleSheet.js.map +1 -1
- package/lib/module/theme/DarkUIKitTheme.js +32 -0
- package/lib/module/theme/DarkUIKitTheme.js.map +1 -1
- package/lib/module/theme/LightUIKitTheme.js +32 -0
- package/lib/module/theme/LightUIKitTheme.js.map +1 -1
- package/lib/module/types.js.map +1 -1
- package/lib/module/ui/ActionMenu/index.js +1 -1
- package/lib/module/ui/ActionMenu/index.js.map +1 -1
- package/lib/module/ui/Avatar/AvatarGroup.js +5 -4
- package/lib/module/ui/Avatar/AvatarGroup.js.map +1 -1
- package/lib/module/ui/Badge/index.js +2 -2
- package/lib/module/ui/Badge/index.js.map +1 -1
- package/lib/module/ui/BottomSheet/index.js +5 -2
- package/lib/module/ui/BottomSheet/index.js.map +1 -1
- package/lib/module/ui/Dialog/index.js +2 -1
- package/lib/module/ui/Dialog/index.js.map +1 -1
- package/lib/module/ui/GroupChannelPreview/index.js +26 -9
- package/lib/module/ui/GroupChannelPreview/index.js.map +1 -1
- package/lib/module/ui/Header/index.js +3 -2
- package/lib/module/ui/Header/index.js.map +1 -1
- package/lib/module/ui/MenuBar/index.js +2 -0
- package/lib/module/ui/MenuBar/index.js.map +1 -1
- package/lib/module/ui/OutlinedButton/index.js +43 -0
- package/lib/module/ui/OutlinedButton/index.js.map +1 -0
- package/lib/module/ui/ProfileCard/index.js +78 -0
- package/lib/module/ui/ProfileCard/index.js.map +1 -0
- package/lib/typescript/src/assets/icon/index.d.ts +3 -1
- package/lib/typescript/src/components/Divider/index.d.ts +1 -1
- package/lib/typescript/src/components/Icon/index.d.ts +2 -2
- package/lib/typescript/src/components/Image/index.d.ts +1 -1
- package/lib/typescript/src/components/Modal/index.d.ts +3 -2
- package/lib/typescript/src/components/RegexText/index.d.ts +16 -0
- package/lib/typescript/src/components/Switch/index.d.ts +1 -1
- package/lib/typescript/src/components/Text/index.d.ts +2 -2
- package/lib/typescript/src/components/URLParsedText/index.d.ts +2 -2
- package/lib/typescript/src/index.d.ts +11 -4
- package/lib/typescript/src/styles/HeaderStyleContext.d.ts +4 -12
- package/lib/typescript/src/styles/createTypography.d.ts +1 -1
- package/lib/typescript/src/theme/UIKitThemeProvider.d.ts +1 -1
- package/lib/typescript/src/theme/createTheme.d.ts +1 -1
- package/lib/typescript/src/types.d.ts +18 -10
- package/lib/typescript/src/ui/ActionMenu/index.d.ts +3 -2
- package/lib/typescript/src/ui/Alert/index.d.ts +2 -2
- package/lib/typescript/src/ui/Avatar/AvatarGroup.d.ts +1 -1
- package/lib/typescript/src/ui/Avatar/AvatarIcon.d.ts +1 -1
- package/lib/typescript/src/ui/Avatar/index.d.ts +2 -2
- package/lib/typescript/src/ui/Badge/index.d.ts +1 -1
- package/lib/typescript/src/ui/BottomSheet/index.d.ts +7 -3
- package/lib/typescript/src/ui/Button/index.d.ts +1 -1
- package/lib/typescript/src/ui/ChannelFrozenBanner/index.d.ts +1 -1
- package/lib/typescript/src/ui/Dialog/DialogBox.d.ts +1 -1
- package/lib/typescript/src/ui/Dialog/DialogSheet.d.ts +2 -2
- package/lib/typescript/src/ui/Dialog/index.d.ts +4 -4
- package/lib/typescript/src/ui/GroupChannelPreview/index.d.ts +5 -2
- package/lib/typescript/src/ui/Header/index.d.ts +3 -2
- package/lib/typescript/src/ui/LoadingSpinner/index.d.ts +1 -1
- package/lib/typescript/src/ui/MenuBar/index.d.ts +3 -2
- package/lib/typescript/src/ui/OutlinedButton/index.d.ts +8 -0
- package/lib/typescript/src/ui/Placeholder/index.d.ts +1 -1
- package/lib/typescript/src/ui/ProfileCard/index.d.ts +11 -0
- package/lib/typescript/src/ui/Prompt/index.d.ts +2 -2
- package/lib/typescript/src/ui/Toast/index.d.ts +3 -3
- package/package.json +6 -5
- package/src/assets/icon/{icon-moderations.png → icon-moderation.png} +0 -0
- package/src/assets/icon/{icon-moderations@2x.png → icon-moderation@2x.png} +0 -0
- package/src/assets/icon/{icon-moderations@3x.png → icon-moderation@3x.png} +0 -0
- package/src/assets/icon/icon-radio-off.png +0 -0
- package/src/assets/icon/icon-radio-off@2x.png +0 -0
- package/src/assets/icon/icon-radio-off@3x.png +0 -0
- package/src/assets/icon/icon-radio-on.png +0 -0
- package/src/assets/icon/icon-radio-on@2x.png +0 -0
- package/src/assets/icon/icon-radio-on@3x.png +0 -0
- package/src/assets/icon/index.ts +3 -1
- package/src/components/Modal/index.tsx +8 -6
- package/src/components/RegexText/index.tsx +48 -0
- package/src/components/URLParsedText/index.tsx +22 -24
- package/src/index.ts +11 -4
- package/src/styles/HeaderStyleContext.tsx +2 -13
- package/src/styles/createStyleSheet.ts +2 -0
- package/src/theme/DarkUIKitTheme.ts +32 -0
- package/src/theme/LightUIKitTheme.ts +32 -0
- package/src/types.ts +12 -1
- package/src/ui/ActionMenu/index.tsx +10 -1
- package/src/ui/Avatar/AvatarGroup.tsx +10 -6
- package/src/ui/Badge/index.tsx +2 -2
- package/src/ui/BottomSheet/index.tsx +4 -1
- package/src/ui/Dialog/index.tsx +1 -0
- package/src/ui/GroupChannelPreview/index.tsx +31 -7
- package/src/ui/Header/index.tsx +8 -3
- package/src/ui/MenuBar/index.tsx +4 -0
- package/src/ui/OutlinedButton/index.tsx +42 -0
- package/src/ui/ProfileCard/index.tsx +73 -0
|
@@ -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
|
|
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 =
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
}, [children]);
|
|
42
|
+
return child;
|
|
43
|
+
});
|
|
46
44
|
|
|
47
45
|
return <Text {...props}>{parsedChildren}</Text>;
|
|
48
46
|
};
|
package/src/index.ts
CHANGED
|
@@ -6,17 +6,18 @@ 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
13
|
export { default as URLParsedText } from './components/URLParsedText';
|
|
13
14
|
|
|
14
15
|
/** UI **/
|
|
15
|
-
export { default as ActionMenu
|
|
16
|
+
export { default as ActionMenu } from './ui/ActionMenu';
|
|
16
17
|
export { default as Alert } from './ui/Alert';
|
|
17
18
|
export { default as Avatar } from './ui/Avatar';
|
|
18
19
|
export { default as Badge } from './ui/Badge';
|
|
19
|
-
export { default as BottomSheet
|
|
20
|
+
export { default as BottomSheet } from './ui/BottomSheet';
|
|
20
21
|
export { default as Button } from './ui/Button';
|
|
21
22
|
export { default as ChannelFrozenBanner } from './ui/ChannelFrozenBanner';
|
|
22
23
|
export { DialogProvider, useActionMenu, useAlert, usePrompt, useBottomSheet } from './ui/Dialog';
|
|
@@ -24,7 +25,9 @@ export { default as GroupChannelPreview } from './ui/GroupChannelPreview';
|
|
|
24
25
|
export { default as Header } from './ui/Header';
|
|
25
26
|
export { default as LoadingSpinner } from './ui/LoadingSpinner';
|
|
26
27
|
export { default as MenuBar, MenuBarProps } from './ui/MenuBar';
|
|
28
|
+
export { default as OutlinedButton } from './ui/OutlinedButton';
|
|
27
29
|
export { default as Placeholder } from './ui/Placeholder';
|
|
30
|
+
export { default as ProfileCard } from './ui/ProfileCard';
|
|
28
31
|
export { default as Prompt } from './ui/Prompt';
|
|
29
32
|
export { default as Toast, useToast, ToastProvider } from './ui/Toast';
|
|
30
33
|
|
|
@@ -32,9 +35,9 @@ export { default as Toast, useToast, ToastProvider } from './ui/Toast';
|
|
|
32
35
|
export { default as createSelectByColorScheme } from './styles/createSelectByColorScheme';
|
|
33
36
|
export { default as createScaleFactor } from './styles/createScaleFactor';
|
|
34
37
|
export { default as createStyleSheet } from './styles/createStyleSheet';
|
|
35
|
-
export { default as createTypography
|
|
38
|
+
export { default as createTypography } from './styles/createTypography';
|
|
36
39
|
export { default as getDefaultHeaderHeight } from './styles/getDefaultHeaderHeight';
|
|
37
|
-
export { HeaderStyleContext, HeaderStyleProvider
|
|
40
|
+
export { HeaderStyleContext, HeaderStyleProvider } from './styles/HeaderStyleContext';
|
|
38
41
|
export { default as useHeaderStyle } from './styles/useHeaderStyle';
|
|
39
42
|
|
|
40
43
|
/** Theme **/
|
|
@@ -63,3 +66,7 @@ export type {
|
|
|
63
66
|
Component,
|
|
64
67
|
GetColorTree,
|
|
65
68
|
} from './types';
|
|
69
|
+
export type { ActionMenuItem } from './ui/ActionMenu';
|
|
70
|
+
export type { BottomSheetItem } from './ui/BottomSheet';
|
|
71
|
+
export type { UIKitTypographyOverrides } from './styles/createTypography';
|
|
72
|
+
export type { HeaderStyleContextType } from './styles/HeaderStyleContext';
|
|
@@ -2,22 +2,11 @@ import React from 'react';
|
|
|
2
2
|
import { StatusBar, useWindowDimensions } from 'react-native';
|
|
3
3
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
4
4
|
|
|
5
|
-
import type {
|
|
5
|
+
import type { HeaderProps } from '../ui/Header';
|
|
6
6
|
import getDefaultHeaderHeight from './getDefaultHeaderHeight';
|
|
7
7
|
|
|
8
8
|
export type HeaderStyleContextType = {
|
|
9
|
-
HeaderComponent: (
|
|
10
|
-
props: BaseHeaderProps<
|
|
11
|
-
{
|
|
12
|
-
title?: HeaderElement;
|
|
13
|
-
left?: HeaderElement;
|
|
14
|
-
right?: HeaderElement;
|
|
15
|
-
onPressLeft?: () => void;
|
|
16
|
-
onPressRight?: () => void;
|
|
17
|
-
},
|
|
18
|
-
{ clearTitleMargin?: boolean }
|
|
19
|
-
>,
|
|
20
|
-
) => React.ReactElement | null;
|
|
9
|
+
HeaderComponent: (props: HeaderProps) => React.ReactElement | null;
|
|
21
10
|
defaultTitleAlign: 'left' | 'center';
|
|
22
11
|
statusBarTranslucent: boolean;
|
|
23
12
|
topInset: number;
|
|
@@ -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,
|
|
@@ -169,6 +169,38 @@ const DarkUIKitTheme = createTheme({
|
|
|
169
169
|
},
|
|
170
170
|
},
|
|
171
171
|
},
|
|
172
|
+
profileCard: {
|
|
173
|
+
default: {
|
|
174
|
+
none: {
|
|
175
|
+
textUsername: palette.onBackgroundDark01,
|
|
176
|
+
textBodyLabel: palette.onBackgroundDark02,
|
|
177
|
+
textBody: palette.onBackgroundDark01,
|
|
178
|
+
background: palette.background500,
|
|
179
|
+
},
|
|
180
|
+
},
|
|
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
|
+
},
|
|
172
204
|
},
|
|
173
205
|
}),
|
|
174
206
|
});
|
|
@@ -169,6 +169,38 @@ const LightUIKitTheme = createTheme({
|
|
|
169
169
|
},
|
|
170
170
|
},
|
|
171
171
|
},
|
|
172
|
+
profileCard: {
|
|
173
|
+
default: {
|
|
174
|
+
none: {
|
|
175
|
+
textUsername: palette.onBackgroundLight01,
|
|
176
|
+
textBodyLabel: palette.onBackgroundLight02,
|
|
177
|
+
textBody: palette.onBackgroundLight01,
|
|
178
|
+
background: palette.background50,
|
|
179
|
+
},
|
|
180
|
+
},
|
|
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
|
+
},
|
|
172
204
|
},
|
|
173
205
|
}),
|
|
174
206
|
});
|
package/src/types.ts
CHANGED
|
@@ -39,7 +39,10 @@ export type Component =
|
|
|
39
39
|
| 'Placeholder'
|
|
40
40
|
| 'Message'
|
|
41
41
|
| 'DateSeparator'
|
|
42
|
-
| 'GroupChannelPreview'
|
|
42
|
+
| 'GroupChannelPreview'
|
|
43
|
+
| 'ProfileCard'
|
|
44
|
+
| 'Reaction';
|
|
45
|
+
|
|
43
46
|
export type GetColorTree<
|
|
44
47
|
Tree extends {
|
|
45
48
|
Variant: {
|
|
@@ -65,6 +68,8 @@ export type ComponentColorTree = GetColorTree<{
|
|
|
65
68
|
Message: 'incoming' | 'outgoing';
|
|
66
69
|
DateSeparator: 'default';
|
|
67
70
|
GroupChannelPreview: 'default';
|
|
71
|
+
ProfileCard: 'default';
|
|
72
|
+
Reaction: 'default' | 'rounded';
|
|
68
73
|
};
|
|
69
74
|
State: {
|
|
70
75
|
Header: 'none';
|
|
@@ -76,6 +81,8 @@ export type ComponentColorTree = GetColorTree<{
|
|
|
76
81
|
Message: 'enabled' | 'pressed';
|
|
77
82
|
DateSeparator: 'none';
|
|
78
83
|
GroupChannelPreview: 'none';
|
|
84
|
+
ProfileCard: 'none';
|
|
85
|
+
Reaction: 'enabled' | 'selected';
|
|
79
86
|
};
|
|
80
87
|
ColorPart: {
|
|
81
88
|
Header: 'background' | 'borderBottom';
|
|
@@ -96,6 +103,8 @@ export type ComponentColorTree = GetColorTree<{
|
|
|
96
103
|
| 'coverBackground'
|
|
97
104
|
| 'bodyIconBackground'
|
|
98
105
|
| 'separator';
|
|
106
|
+
ProfileCard: 'textUsername' | 'textBodyLabel' | 'textBody' | 'background';
|
|
107
|
+
Reaction: 'background' | 'highlight';
|
|
99
108
|
};
|
|
100
109
|
}>;
|
|
101
110
|
export type ComponentColors<T extends Component> = {
|
|
@@ -139,6 +148,8 @@ export interface UIKitColors {
|
|
|
139
148
|
message: ComponentColors<'Message'>;
|
|
140
149
|
dateSeparator: ComponentColors<'DateSeparator'>;
|
|
141
150
|
groupChannelPreview: ComponentColors<'GroupChannelPreview'>;
|
|
151
|
+
profileCard: ComponentColors<'ProfileCard'>;
|
|
152
|
+
reaction: ComponentColors<'Reaction'>;
|
|
142
153
|
};
|
|
143
154
|
}
|
|
144
155
|
|
|
@@ -15,6 +15,7 @@ export type ActionMenuItem = {
|
|
|
15
15
|
title?: string;
|
|
16
16
|
menuItems: {
|
|
17
17
|
title: string;
|
|
18
|
+
style?: 'destructive';
|
|
18
19
|
onPress?: (() => Promise<void>) | (() => void);
|
|
19
20
|
onError?: () => void;
|
|
20
21
|
}[];
|
|
@@ -83,7 +84,15 @@ const ActionMenu = ({ visible, onHide, onError, onDismiss, title, menuItems }: P
|
|
|
83
84
|
}
|
|
84
85
|
}}
|
|
85
86
|
>
|
|
86
|
-
<Text
|
|
87
|
+
<Text
|
|
88
|
+
subtitle2
|
|
89
|
+
color={
|
|
90
|
+
item.style === 'destructive'
|
|
91
|
+
? colors.ui.dialog.default.none.destructive
|
|
92
|
+
: colors.ui.dialog.default.none.text
|
|
93
|
+
}
|
|
94
|
+
numberOfLines={1}
|
|
95
|
+
>
|
|
87
96
|
{item.title}
|
|
88
97
|
</Text>
|
|
89
98
|
</TouchableOpacity>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import 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
|
|
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
|
|
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
|
-
}
|
|
56
|
+
};
|
|
53
57
|
|
|
54
58
|
return (
|
|
55
59
|
<View style={[containerStyle, { overflow: 'hidden', width: size, height: size, borderRadius: size }]}>
|
|
56
|
-
{
|
|
60
|
+
{renderAvatars()}
|
|
57
61
|
</View>
|
|
58
62
|
);
|
|
59
63
|
};
|
package/src/ui/Badge/index.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Platform, StyleProp, View, ViewStyle } from 'react-native';
|
|
3
3
|
|
|
4
|
-
import {
|
|
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
|
-
{
|
|
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}
|
package/src/ui/Dialog/index.tsx
CHANGED
|
@@ -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>
|
|
@@ -28,6 +28,9 @@ type Props = {
|
|
|
28
28
|
|
|
29
29
|
frozen?: boolean;
|
|
30
30
|
notificationOff?: boolean;
|
|
31
|
+
broadcast?: boolean;
|
|
32
|
+
mentioned?: boolean;
|
|
33
|
+
mentionTrigger?: string;
|
|
31
34
|
};
|
|
32
35
|
|
|
33
36
|
const GroupChannelPreview = ({
|
|
@@ -43,6 +46,9 @@ const GroupChannelPreview = ({
|
|
|
43
46
|
titleCaptionLeft,
|
|
44
47
|
frozen,
|
|
45
48
|
notificationOff,
|
|
49
|
+
broadcast,
|
|
50
|
+
mentioned,
|
|
51
|
+
mentionTrigger = '@',
|
|
46
52
|
}: Props) => {
|
|
47
53
|
const { colors } = useUIKitTheme();
|
|
48
54
|
const color = colors.ui.groupChannelPreview;
|
|
@@ -65,6 +71,14 @@ const GroupChannelPreview = ({
|
|
|
65
71
|
<View style={styles.rightSection}>
|
|
66
72
|
<View style={styles.rightTopSection}>
|
|
67
73
|
<View style={styles.channelInfoContainer}>
|
|
74
|
+
{broadcast && (
|
|
75
|
+
<Icon
|
|
76
|
+
size={16}
|
|
77
|
+
icon={'broadcast'}
|
|
78
|
+
color={colors.secondary}
|
|
79
|
+
containerStyle={styles.channelInfoBroadcast}
|
|
80
|
+
/>
|
|
81
|
+
)}
|
|
68
82
|
<Text numberOfLines={1} subtitle1 style={styles.channelInfoTitle} color={color.default.none.textTitle}>
|
|
69
83
|
{title}
|
|
70
84
|
</Text>
|
|
@@ -105,7 +119,14 @@ const GroupChannelPreview = ({
|
|
|
105
119
|
</Text>
|
|
106
120
|
</View>
|
|
107
121
|
</View>
|
|
108
|
-
<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>
|
|
109
130
|
</View>
|
|
110
131
|
<Separator color={color.default.none.separator} />
|
|
111
132
|
</View>
|
|
@@ -148,6 +169,9 @@ const styles = createStyleSheet({
|
|
|
148
169
|
alignItems: 'center',
|
|
149
170
|
flexDirection: 'row',
|
|
150
171
|
},
|
|
172
|
+
channelInfoBroadcast: {
|
|
173
|
+
marginRight: 4,
|
|
174
|
+
},
|
|
151
175
|
channelInfoTitle: {
|
|
152
176
|
flexShrink: 1,
|
|
153
177
|
marginRight: 4,
|
|
@@ -191,12 +215,12 @@ const styles = createStyleSheet({
|
|
|
191
215
|
height: 26,
|
|
192
216
|
marginRight: 4,
|
|
193
217
|
},
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
218
|
+
unreadContainer: {
|
|
219
|
+
flexDirection: 'row',
|
|
220
|
+
alignItems: 'flex-start',
|
|
221
|
+
},
|
|
222
|
+
unreadMention: {
|
|
223
|
+
marginRight: 4,
|
|
200
224
|
},
|
|
201
225
|
separator: {
|
|
202
226
|
position: 'absolute',
|
package/src/ui/Header/index.tsx
CHANGED
|
@@ -11,7 +11,7 @@ import useHeaderStyle from '../../styles/useHeaderStyle';
|
|
|
11
11
|
import useUIKitTheme from '../../theme/useUIKitTheme';
|
|
12
12
|
|
|
13
13
|
type HeaderElement = string | React.ReactElement | null;
|
|
14
|
-
type HeaderProps = BaseHeaderProps<
|
|
14
|
+
export type HeaderProps = BaseHeaderProps<
|
|
15
15
|
{
|
|
16
16
|
title?: HeaderElement;
|
|
17
17
|
left?: HeaderElement;
|
|
@@ -19,7 +19,10 @@ type HeaderProps = BaseHeaderProps<
|
|
|
19
19
|
onPressLeft?: () => void;
|
|
20
20
|
onPressRight?: () => void;
|
|
21
21
|
},
|
|
22
|
-
{
|
|
22
|
+
{
|
|
23
|
+
clearTitleMargin?: boolean;
|
|
24
|
+
statusBarTopInsetAs?: 'padding' | 'margin';
|
|
25
|
+
}
|
|
23
26
|
>;
|
|
24
27
|
|
|
25
28
|
const AlignMapper = { left: 'flex-start', center: 'center', right: 'flex-end' } as const;
|
|
@@ -36,8 +39,10 @@ const Header: ((props: HeaderProps) => JSX.Element) & {
|
|
|
36
39
|
onPressLeft,
|
|
37
40
|
onPressRight,
|
|
38
41
|
clearTitleMargin = false,
|
|
42
|
+
statusBarTopInsetAs = 'padding',
|
|
39
43
|
}) => {
|
|
40
44
|
const { topInset, defaultTitleAlign, defaultHeight } = useHeaderStyle();
|
|
45
|
+
|
|
41
46
|
const { colors } = useUIKitTheme();
|
|
42
47
|
const { left: paddingLeft, right: paddingRight } = useSafeAreaInsets();
|
|
43
48
|
|
|
@@ -54,9 +59,9 @@ const Header: ((props: HeaderProps) => JSX.Element) & {
|
|
|
54
59
|
style={[
|
|
55
60
|
styles.container,
|
|
56
61
|
{
|
|
62
|
+
[statusBarTopInsetAs === 'padding' ? 'paddingTop' : 'marginTop']: topInset,
|
|
57
63
|
paddingLeft: paddingLeft + styles.container.paddingHorizontal,
|
|
58
64
|
paddingRight: paddingRight + styles.container.paddingHorizontal,
|
|
59
|
-
paddingTop: topInset,
|
|
60
65
|
backgroundColor: colors.ui.header.nav.none.background,
|
|
61
66
|
borderBottomColor: colors.ui.header.nav.none.borderBottom,
|
|
62
67
|
},
|
package/src/ui/MenuBar/index.tsx
CHANGED
|
@@ -14,6 +14,7 @@ export type MenuBarProps = {
|
|
|
14
14
|
|
|
15
15
|
onPress: () => void;
|
|
16
16
|
disabled?: boolean;
|
|
17
|
+
visible?: boolean;
|
|
17
18
|
|
|
18
19
|
icon: keyof typeof Icon.Assets;
|
|
19
20
|
iconColor?: string;
|
|
@@ -26,6 +27,7 @@ export type MenuBarProps = {
|
|
|
26
27
|
const MenuBar = ({
|
|
27
28
|
variant = 'default',
|
|
28
29
|
disabled,
|
|
30
|
+
visible = true,
|
|
29
31
|
onPress,
|
|
30
32
|
name,
|
|
31
33
|
icon,
|
|
@@ -36,6 +38,8 @@ const MenuBar = ({
|
|
|
36
38
|
}: MenuBarProps) => {
|
|
37
39
|
const { palette, colors } = useUIKitTheme();
|
|
38
40
|
|
|
41
|
+
if (!visible) return null;
|
|
42
|
+
|
|
39
43
|
return (
|
|
40
44
|
<View>
|
|
41
45
|
<Pressable disabled={disabled} onPress={onPress} style={styles.container}>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Pressable, StyleProp, ViewStyle } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import Text from '../../components/Text';
|
|
5
|
+
import createStyleSheet from '../../styles/createStyleSheet';
|
|
6
|
+
import useUIKitTheme from '../../theme/useUIKitTheme';
|
|
7
|
+
|
|
8
|
+
type OutlinedButtonProps = {
|
|
9
|
+
children: string;
|
|
10
|
+
containerStyle?: StyleProp<ViewStyle>;
|
|
11
|
+
onPress?: () => void;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const OutlinedButton = ({ children, onPress, containerStyle }: OutlinedButtonProps) => {
|
|
15
|
+
const { colors } = useUIKitTheme();
|
|
16
|
+
return (
|
|
17
|
+
<Pressable
|
|
18
|
+
onPress={onPress}
|
|
19
|
+
style={[styles.outlinedButton, { borderColor: colors.onBackground01 }, containerStyle]}
|
|
20
|
+
>
|
|
21
|
+
<Text button color={colors.onBackground01} numberOfLines={1} style={styles.outlinedButtonText}>
|
|
22
|
+
{children}
|
|
23
|
+
</Text>
|
|
24
|
+
</Pressable>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const styles = createStyleSheet({
|
|
29
|
+
outlinedButton: {
|
|
30
|
+
borderRadius: 4,
|
|
31
|
+
padding: 16,
|
|
32
|
+
borderWidth: 1,
|
|
33
|
+
alignItems: 'center',
|
|
34
|
+
justifyContent: 'center',
|
|
35
|
+
},
|
|
36
|
+
outlinedButtonText: {
|
|
37
|
+
textAlign: 'center',
|
|
38
|
+
width: '100%',
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
export default OutlinedButton;
|