@unif/react-native-chat 3.6.1 → 4.0.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 (102) hide show
  1. package/lib/module/components/Attachments/AttachmentItem.js +24 -16
  2. package/lib/module/components/Attachments/AttachmentItem.js.map +1 -1
  3. package/lib/module/components/Attachments/constants.js +5 -4
  4. package/lib/module/components/Attachments/constants.js.map +1 -1
  5. package/lib/module/components/Attachments/styles.js +4 -2
  6. package/lib/module/components/Attachments/styles.js.map +1 -1
  7. package/lib/module/components/Composer/Composer.js +10 -7
  8. package/lib/module/components/Composer/Composer.js.map +1 -1
  9. package/lib/module/components/Composer/ComposerIconAction.js +3 -3
  10. package/lib/module/components/Composer/ComposerIconAction.js.map +1 -1
  11. package/lib/module/components/Composer/styles.js +5 -2
  12. package/lib/module/components/Composer/styles.js.map +1 -1
  13. package/lib/module/components/Confirmation/Confirmation.js +4 -3
  14. package/lib/module/components/Confirmation/Confirmation.js.map +1 -1
  15. package/lib/module/components/Feedback/Feedback.js +4 -3
  16. package/lib/module/components/Feedback/Feedback.js.map +1 -1
  17. package/lib/module/components/Feedback/constants.js +5 -4
  18. package/lib/module/components/Feedback/constants.js.map +1 -1
  19. package/lib/module/components/Message/MarkdownContent/MarkdownContent.js +3 -1
  20. package/lib/module/components/Message/MarkdownContent/MarkdownContent.js.map +1 -1
  21. package/lib/module/components/Message/MarkdownContent/MarkdownImage/MarkdownImage.js +6 -3
  22. package/lib/module/components/Message/MarkdownContent/MarkdownImage/MarkdownImage.js.map +1 -1
  23. package/lib/module/components/Message/MarkdownContent/types.js +2 -0
  24. package/lib/module/components/Message/Message.js +7 -5
  25. package/lib/module/components/Message/Message.js.map +1 -1
  26. package/lib/module/components/MessageList/MessageListEndButton.js +25 -26
  27. package/lib/module/components/MessageList/MessageListEndButton.js.map +1 -1
  28. package/lib/module/components/MessageList/styles.js +1 -2
  29. package/lib/module/components/MessageList/styles.js.map +1 -1
  30. package/lib/module/components/Process/Process.js +4 -3
  31. package/lib/module/components/Process/Process.js.map +1 -1
  32. package/lib/module/components/Process/ProcessCompactStep.js +11 -10
  33. package/lib/module/components/Process/ProcessCompactStep.js.map +1 -1
  34. package/lib/module/components/Process/ProcessTimelineStep.js +3 -3
  35. package/lib/module/components/Process/ProcessTimelineStep.js.map +1 -1
  36. package/lib/module/components/Process/constants.js +6 -5
  37. package/lib/module/components/Process/constants.js.map +1 -1
  38. package/lib/module/components/Sources/Sources.js +6 -3
  39. package/lib/module/components/Sources/Sources.js.map +1 -1
  40. package/lib/module/components/Suggestions/Suggestions.js +2 -3
  41. package/lib/module/components/Suggestions/Suggestions.js.map +1 -1
  42. package/lib/typescript/src/actions/types.d.ts +3 -2
  43. package/lib/typescript/src/actions/types.d.ts.map +1 -1
  44. package/lib/typescript/src/components/Attachments/AttachmentItem.d.ts.map +1 -1
  45. package/lib/typescript/src/components/Attachments/constants.d.ts +3 -2
  46. package/lib/typescript/src/components/Attachments/constants.d.ts.map +1 -1
  47. package/lib/typescript/src/components/Attachments/styles.d.ts +4 -2
  48. package/lib/typescript/src/components/Attachments/styles.d.ts.map +1 -1
  49. package/lib/typescript/src/components/Composer/Composer.d.ts.map +1 -1
  50. package/lib/typescript/src/components/Composer/styles.d.ts +3 -1
  51. package/lib/typescript/src/components/Composer/styles.d.ts.map +1 -1
  52. package/lib/typescript/src/components/Composer/types.d.ts +5 -3
  53. package/lib/typescript/src/components/Composer/types.d.ts.map +1 -1
  54. package/lib/typescript/src/components/Confirmation/Confirmation.d.ts.map +1 -1
  55. package/lib/typescript/src/components/Feedback/Feedback.d.ts.map +1 -1
  56. package/lib/typescript/src/components/Feedback/constants.d.ts +3 -2
  57. package/lib/typescript/src/components/Feedback/constants.d.ts.map +1 -1
  58. package/lib/typescript/src/components/Message/MarkdownContent/MarkdownContent.d.ts +1 -1
  59. package/lib/typescript/src/components/Message/MarkdownContent/MarkdownContent.d.ts.map +1 -1
  60. package/lib/typescript/src/components/Message/MarkdownContent/MarkdownImage/MarkdownImage.d.ts.map +1 -1
  61. package/lib/typescript/src/components/Message/MarkdownContent/types.d.ts +2 -0
  62. package/lib/typescript/src/components/Message/MarkdownContent/types.d.ts.map +1 -1
  63. package/lib/typescript/src/components/Message/Message.d.ts.map +1 -1
  64. package/lib/typescript/src/components/MessageList/MessageListEndButton.d.ts.map +1 -1
  65. package/lib/typescript/src/components/MessageList/styles.d.ts +1 -2
  66. package/lib/typescript/src/components/MessageList/styles.d.ts.map +1 -1
  67. package/lib/typescript/src/components/Process/Process.d.ts.map +1 -1
  68. package/lib/typescript/src/components/Process/ProcessCompactStep.d.ts.map +1 -1
  69. package/lib/typescript/src/components/Process/constants.d.ts +3 -2
  70. package/lib/typescript/src/components/Process/constants.d.ts.map +1 -1
  71. package/lib/typescript/src/components/Process/types.d.ts +4 -0
  72. package/lib/typescript/src/components/Process/types.d.ts.map +1 -1
  73. package/lib/typescript/src/components/Sources/Sources.d.ts.map +1 -1
  74. package/lib/typescript/src/components/Suggestions/Suggestions.d.ts.map +1 -1
  75. package/lib/typescript/src/components/Suggestions/types.d.ts +3 -2
  76. package/lib/typescript/src/components/Suggestions/types.d.ts.map +1 -1
  77. package/package.json +5 -3
  78. package/src/actions/types.ts +3 -2
  79. package/src/components/Attachments/AttachmentItem.tsx +20 -20
  80. package/src/components/Attachments/constants.ts +14 -6
  81. package/src/components/Attachments/styles.ts +2 -2
  82. package/src/components/Composer/Composer.tsx +16 -5
  83. package/src/components/Composer/ComposerIconAction.tsx +3 -3
  84. package/src/components/Composer/styles.ts +3 -2
  85. package/src/components/Composer/types.ts +5 -3
  86. package/src/components/Confirmation/Confirmation.tsx +12 -12
  87. package/src/components/Feedback/Feedback.tsx +3 -2
  88. package/src/components/Feedback/constants.ts +16 -6
  89. package/src/components/Message/MarkdownContent/MarkdownContent.tsx +2 -1
  90. package/src/components/Message/MarkdownContent/MarkdownImage/MarkdownImage.tsx +4 -2
  91. package/src/components/Message/MarkdownContent/types.ts +3 -0
  92. package/src/components/Message/Message.tsx +10 -3
  93. package/src/components/MessageList/MessageListEndButton.tsx +18 -24
  94. package/src/components/MessageList/styles.ts +1 -2
  95. package/src/components/Process/Process.tsx +4 -3
  96. package/src/components/Process/ProcessCompactStep.tsx +26 -20
  97. package/src/components/Process/ProcessTimelineStep.tsx +2 -2
  98. package/src/components/Process/constants.ts +16 -7
  99. package/src/components/Process/types.ts +5 -0
  100. package/src/components/Sources/Sources.tsx +6 -2
  101. package/src/components/Suggestions/Suggestions.tsx +2 -6
  102. package/src/components/Suggestions/types.ts +4 -2
@@ -1,3 +1,10 @@
1
+ import {
2
+ CloseOutlined,
3
+ MicOutlined,
4
+ PlusOutlined,
5
+ SendOutlined,
6
+ StopFilled,
7
+ } from '@unif/react-native-icons';
1
8
  import {
2
9
  forwardRef,
3
10
  useEffect,
@@ -14,6 +21,7 @@ import {
14
21
  } from 'react-native';
15
22
  import {
16
23
  ActionMenuContent,
24
+ GlassLayer,
17
25
  fixed,
18
26
  Textarea,
19
27
  useTheme,
@@ -118,7 +126,7 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
118
126
  const moreAction =
119
127
  actions.length > 0 ? (
120
128
  <ComposerIconAction
121
- icon="plus"
129
+ icon={PlusOutlined}
122
130
  label="更多操作"
123
131
  expanded={menuOpen}
124
132
  disabled={moreDisabled}
@@ -137,6 +145,7 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
137
145
  }
138
146
  }}
139
147
  >
148
+ {surface === 'card' ? <GlassLayer style={styles.glass} /> : null}
140
149
  {header != null ? (
141
150
  <View
142
151
  style={[
@@ -241,7 +250,7 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
241
250
  <View style={styles.trailingActions}>
242
251
  {voice ? (
243
252
  <ComposerIconAction
244
- icon="mic"
253
+ icon={MicOutlined}
245
254
  label="开始语音输入"
246
255
  disabled={disabled || voice.disabled}
247
256
  onPress={() => {
@@ -252,7 +261,9 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
252
261
  ) : null}
253
262
  {showPrimary ? (
254
263
  <ComposerIconAction
255
- icon={primaryAction.kind === 'send' ? 'send' : 'stop'}
264
+ icon={
265
+ primaryAction.kind === 'send' ? SendOutlined : StopFilled
266
+ }
256
267
  label={primaryLabel}
257
268
  visual="primary"
258
269
  disabled={primaryDisabled}
@@ -274,7 +285,7 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
274
285
  {voice && voice.status !== 'idle' ? (
275
286
  <View style={styles.voice}>
276
287
  <ComposerIconAction
277
- icon="close"
288
+ icon={CloseOutlined}
278
289
  visual="cancel"
279
290
  label="取消语音输入"
280
291
  disabled={disabled || voice.disabled}
@@ -298,7 +309,7 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
298
309
  </View>
299
310
  {voice.status === 'listening' || voice.status === 'finishing' ? (
300
311
  <ComposerIconAction
301
- icon="stop"
312
+ icon={StopFilled}
302
313
  visual="primary"
303
314
  label="停止语音输入"
304
315
  disabled={
@@ -1,5 +1,5 @@
1
1
  import { ActivityIndicator, Pressable, View } from 'react-native';
2
- import { Icon, useColors, useThemedStyles } from '@unif/react-native-design';
2
+ import { useColors, useThemedStyles } from '@unif/react-native-design';
3
3
  import {
4
4
  COMPOSER_ACTION_ICON_SIZE,
5
5
  COMPOSER_PRIMARY_ICON_SIZE,
@@ -28,6 +28,7 @@ export function ComposerIconAction({
28
28
  ? colors.foregroundSubtle
29
29
  : colors.onPrimary
30
30
  : colors.foregroundMuted;
31
+ const Glyph = icon;
31
32
  return (
32
33
  <Pressable
33
34
  accessibilityRole="button"
@@ -54,8 +55,7 @@ export function ComposerIconAction({
54
55
  {busy ? (
55
56
  <ActivityIndicator size="small" color={color} />
56
57
  ) : (
57
- <Icon
58
- name={icon}
58
+ <Glyph
59
59
  size={
60
60
  primary
61
61
  ? COMPOSER_PRIMARY_ICON_SIZE
@@ -9,10 +9,11 @@ export const createStyles = (colors: ColorTokens, shadows: ShadowTokens) =>
9
9
  card: {
10
10
  borderRadius: r(20),
11
11
  borderWidth: 0.5,
12
- borderColor: colors.outline,
13
- backgroundColor: colors.surface,
12
+ borderColor: colors.glassBorder,
14
13
  ...shadows.card,
15
14
  },
15
+ // 仅材质层定义圆角,根容器保留浮菜单的溢出空间。
16
+ glass: { borderRadius: r(20) },
16
17
  accessory: { padding: space[3] },
17
18
  header: {
18
19
  padding: space[2],
@@ -1,6 +1,8 @@
1
+ import type { ComponentType } from 'react';
2
+ import type { IconProps } from '@unif/react-native-icons';
1
3
  import type { ReactNode } from 'react';
2
4
  import type { StyleProp, ViewStyle } from 'react-native';
3
- import type { IconName, TextFieldHandle } from '@unif/react-native-design';
5
+ import type { TextFieldHandle } from '@unif/react-native-design';
4
6
  import type { ChatAction } from '../../actions';
5
7
 
6
8
  export interface ComposerSendAction {
@@ -50,7 +52,7 @@ export interface ComposerProps {
50
52
  voice?: ComposerVoiceControl;
51
53
  header?: ReactNode;
52
54
  footer?: ReactNode;
53
- /** card 提供统一表面;plain 由外层提供表面,内部 Textarea 均不单独绘制表面。 */
55
+ /** card 提供统一玻璃表面;plain 由外层提供表面,内部 Textarea 均不单独绘制表面。 */
54
56
  surface?: 'card' | 'plain';
55
57
  /** Textarea 整体最小高度(含内间距),默认 44,不低于最小触达高度。 */
56
58
  minInputHeight?: number;
@@ -65,7 +67,7 @@ export interface ComposerProps {
65
67
  export type ComposerHandle = TextFieldHandle;
66
68
 
67
69
  export interface ComposerIconActionProps {
68
- icon: IconName;
70
+ icon: ComponentType<IconProps>;
69
71
  label: string;
70
72
  onPress?(): void;
71
73
  disabled?: boolean;
@@ -1,7 +1,11 @@
1
+ import {
2
+ CheckOutlined,
3
+ CloseOutlined,
4
+ WarningOutlined,
5
+ } from '@unif/react-native-icons';
1
6
  import { Text, View } from 'react-native';
2
7
  import {
3
8
  Button,
4
- Icon,
5
9
  Spinner,
6
10
  useColors,
7
11
  useThemedStyles,
@@ -44,23 +48,19 @@ export function Confirmation({
44
48
  ? statusText
45
49
  : (statusText ?? CONFIRMATION_STATUS_TEXT[status]);
46
50
 
51
+ const Glyph =
52
+ status === 'confirmed'
53
+ ? CheckOutlined
54
+ : status === 'cancelled'
55
+ ? CloseOutlined
56
+ : WarningOutlined;
47
57
  return (
48
58
  <View style={[styles.root, { borderColor }, style]} testID={testID}>
49
59
  <View style={styles.heading}>
50
60
  {status === 'processing' ? (
51
61
  <Spinner size={14} color={tint} />
52
62
  ) : (
53
- <Icon
54
- name={
55
- status === 'confirmed'
56
- ? 'check'
57
- : status === 'cancelled'
58
- ? 'close'
59
- : 'warning'
60
- }
61
- size={14}
62
- color={tint}
63
- />
63
+ <Glyph size={14} color={tint} />
64
64
  )}
65
65
  <Text
66
66
  style={[styles.title, status === 'cancelled' && styles.cancelled]}
@@ -1,7 +1,7 @@
1
1
  import { Text, View } from 'react-native';
2
2
  import {
3
3
  Button,
4
- Icon,
4
+ r,
5
5
  useColors,
6
6
  useThemedStyles,
7
7
  } from '@unif/react-native-design';
@@ -48,6 +48,7 @@ export function Feedback({
48
48
  const toneLabel = FEEDBACK_TONE_LABELS[tone];
49
49
  const accessibilityLabel = `${toneLabel}:${title ? `${title}。` : ''}${message}`;
50
50
 
51
+ const Glyph = FEEDBACK_TONE_ICONS[tone];
51
52
  return (
52
53
  <View
53
54
  style={[
@@ -57,7 +58,7 @@ export function Feedback({
57
58
  ]}
58
59
  testID={testID}
59
60
  >
60
- <Icon name={FEEDBACK_TONE_ICONS[tone]} color={toneColors.iconColor} />
61
+ <Glyph size={r(18)} color={toneColors.iconColor} />
61
62
  <View style={styles.content}>
62
63
  <View accessible accessibilityLabel={accessibilityLabel}>
63
64
  {title ? (
@@ -1,4 +1,12 @@
1
- import type { IconName } from '@unif/react-native-design';
1
+ import {
2
+ ErrorOutlined,
3
+ InfoOutlined,
4
+ SuccessOutlined,
5
+ WarningOutlined,
6
+ } from '@unif/react-native-icons';
7
+ import type { ComponentType } from 'react';
8
+ import type { IconProps } from '@unif/react-native-icons';
9
+
2
10
  import type { FeedbackTone } from './types';
3
11
 
4
12
  export const FEEDBACK_TONE_LABELS: Readonly<Record<FeedbackTone, string>> = {
@@ -8,9 +16,11 @@ export const FEEDBACK_TONE_LABELS: Readonly<Record<FeedbackTone, string>> = {
8
16
  error: '错误',
9
17
  };
10
18
 
11
- export const FEEDBACK_TONE_ICONS: Readonly<Record<FeedbackTone, IconName>> = {
12
- info: 'info',
13
- success: 'success',
14
- warning: 'warning',
15
- error: 'error',
19
+ export const FEEDBACK_TONE_ICONS: Readonly<
20
+ Record<FeedbackTone, ComponentType<IconProps>>
21
+ > = {
22
+ info: InfoOutlined,
23
+ success: SuccessOutlined,
24
+ warning: WarningOutlined,
25
+ error: ErrorOutlined,
16
26
  };
@@ -16,6 +16,7 @@ export function MarkdownContent({
16
16
  text,
17
17
  onLinkPress,
18
18
  outgoing = false,
19
+ style,
19
20
  }: MarkdownContentProps) {
20
21
  const { scheme } = useTheme();
21
22
  const styles = useThemedStyles(
@@ -96,5 +97,5 @@ export function MarkdownContent({
96
97
  styles: markdown.styles,
97
98
  });
98
99
  const content = Children.toArray(nodes);
99
- return content.length ? <View>{content}</View> : null;
100
+ return content.length ? <View style={style}>{content}</View> : null;
100
101
  }
@@ -1,10 +1,12 @@
1
+ import { ImageOutlined } from '@unif/react-native-icons';
1
2
  import { useEffect, useState } from 'react';
2
3
  import { Image, View } from 'react-native';
3
- import { Icon, Thumbnail } from '@unif/react-native-design';
4
+ import { Thumbnail, r, useColors } from '@unif/react-native-design';
4
5
  import { styles } from './styles';
5
6
  import type { ImageRatio, MarkdownImageProps } from './types';
6
7
 
7
8
  export function MarkdownImage({ uri, label }: MarkdownImageProps) {
9
+ const colors = useColors();
8
10
  const [width, setWidth] = useState(1);
9
11
  const [ratio, setRatio] = useState<ImageRatio | undefined>(undefined);
10
12
  useEffect(() => {
@@ -44,7 +46,7 @@ export function MarkdownImage({ uri, label }: MarkdownImageProps) {
44
46
  borderRadius: 0,
45
47
  }}
46
48
  resizeMode="contain"
47
- fallback={<Icon name="image" />}
49
+ fallback={<ImageOutlined size={r(18)} color={colors.foregroundMuted} />}
48
50
  accessibilityLabel={label || '图片'}
49
51
  />
50
52
  </View>
@@ -1,7 +1,10 @@
1
+ import type { StyleProp, ViewStyle } from 'react-native';
2
+
1
3
  export interface MarkdownContentProps {
2
4
  text: string;
3
5
  onLinkPress?(url: string): void;
4
6
  outgoing?: boolean;
7
+ style?: StyleProp<ViewStyle>;
5
8
  }
6
9
 
7
10
  export interface MarkdownSvgLabelProps {
@@ -1,3 +1,4 @@
1
+ import { AlertOutlined } from '@unif/react-native-icons';
1
2
  import { Pressable, Text, View } from 'react-native';
2
3
  import {
3
4
  Button,
@@ -49,7 +50,6 @@ export function Message(props: MessageProps) {
49
50
  placement === 'end' && styles.outgoing,
50
51
  ],
51
52
  surface === 'outlined' && styles.outlined,
52
- status === 'failed' && styles.failed,
53
53
  waiting &&
54
54
  surface === 'bubble' &&
55
55
  placement === 'start' &&
@@ -66,6 +66,7 @@ export function Message(props: MessageProps) {
66
66
  text={props.text}
67
67
  onLinkPress={props.onLinkPress}
68
68
  outgoing={surface === 'bubble' && placement === 'end'}
69
+ style={status === 'failed' ? styles.failed : undefined}
69
70
  />
70
71
  ) : (
71
72
  <Text
@@ -75,6 +76,7 @@ export function Message(props: MessageProps) {
75
76
  surface === 'bubble' &&
76
77
  placement === 'end' &&
77
78
  styles.outgoingText,
79
+ status === 'failed' && styles.failed,
78
80
  ]}
79
81
  numberOfLines={props.numberOfLines}
80
82
  >
@@ -86,7 +88,12 @@ export function Message(props: MessageProps) {
86
88
  )}
87
89
  {waiting ? <MessageWaiting label={statusText} /> : null}
88
90
  {statusText && !waiting ? (
89
- <Text style={[styles.status, status === 'failed' && styles.errorText]}>
91
+ <Text
92
+ style={[
93
+ styles.status,
94
+ status === 'failed' && [styles.errorText, styles.failed],
95
+ ]}
96
+ >
90
97
  {statusText}
91
98
  </Text>
92
99
  ) : null}
@@ -136,7 +143,7 @@ export function Message(props: MessageProps) {
136
143
  <View style={[styles.failureRow, placement === 'end' && styles.end]}>
137
144
  {bubble}
138
145
  <IconButton
139
- icon="alert"
146
+ icon={AlertOutlined}
140
147
  size="sm"
141
148
  variant="ghost"
142
149
  color={colors.error}
@@ -1,8 +1,8 @@
1
+ import { ArrowDownOutlined } from '@unif/react-native-icons';
1
2
  import { useEffect, useRef } from 'react';
2
3
  import { Animated, View } from 'react-native';
3
4
  import {
4
5
  IconButton,
5
- Reveal,
6
6
  Spinner,
7
7
  usePrefersReducedMotion,
8
8
  useThemedStyles,
@@ -33,29 +33,23 @@ export function MessageListEndButton({
33
33
  }, [reducedMotion, scale]);
34
34
  return (
35
35
  <View style={styles.returnToEnd} pointerEvents="box-none">
36
- <Reveal>
37
- <Animated.View
38
- style={[styles.returnVisual, { transform: [{ scale }] }]}
39
- >
40
- {busy ? (
41
- <View style={styles.returnProgress} pointerEvents="none">
42
- <Spinner size={44} thickness={2} />
43
- </View>
44
- ) : null}
45
- <IconButton
46
- icon="arrow-down"
47
- accessibilityLabel={
48
- busy ? '回到最新消息,正在处理' : '回到最新消息'
49
- }
50
- variant="ghost"
51
- size="md"
52
- surfaceSize={36}
53
- iconSize={18}
54
- style={styles.returnButton}
55
- onPress={onPress}
56
- />
57
- </Animated.View>
58
- </Reveal>
36
+ <Animated.View style={[styles.returnVisual, { transform: [{ scale }] }]}>
37
+ {busy ? (
38
+ <View style={styles.returnProgress} pointerEvents="none">
39
+ <Spinner size={44} thickness={2} />
40
+ </View>
41
+ ) : null}
42
+ <IconButton
43
+ icon={ArrowDownOutlined}
44
+ accessibilityLabel={busy ? '回到最新消息,正在处理' : '回到最新消息'}
45
+ variant="glass"
46
+ size="md"
47
+ surfaceSize={36}
48
+ iconSize={18}
49
+ style={styles.returnButton}
50
+ onPress={onPress}
51
+ />
52
+ </Animated.View>
59
53
  </View>
60
54
  );
61
55
  }
@@ -1,6 +1,6 @@
1
1
  import { StyleSheet } from 'react-native';
2
2
  import type { ColorTokens, ShadowTokens } from '@unif/react-native-design';
3
- export const createStyles = (colors: ColorTokens, shadows: ShadowTokens) =>
3
+ export const createStyles = (_colors: ColorTokens, shadows: ShadowTokens) =>
4
4
  StyleSheet.create({
5
5
  root: { flex: 1, minHeight: 0, minWidth: 0 },
6
6
  list: { flex: 1 },
@@ -23,7 +23,6 @@ export const createStyles = (colors: ColorTokens, shadows: ShadowTokens) =>
23
23
  returnButton: {
24
24
  alignSelf: 'center',
25
25
  borderRadius: 18,
26
- backgroundColor: colors.surface,
27
26
  ...shadows.card,
28
27
  },
29
28
  });
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
2
2
  import { Text, View } from 'react-native';
3
3
  import {
4
4
  Button,
5
- Icon,
5
+ r,
6
6
  useColors,
7
7
  useThemedStyles,
8
8
  } from '@unif/react-native-design';
@@ -130,6 +130,7 @@ export function Process(props: ProcessProps): React.JSX.Element {
130
130
  onToggle={() => toggleDetails(step.id)}
131
131
  />
132
132
  );
133
+ const Glyph = PROCESS_STATUS_ICONS[step.status];
133
134
  return (
134
135
  <View
135
136
  key={step.id}
@@ -150,8 +151,8 @@ export function Process(props: ProcessProps): React.JSX.Element {
150
151
  accessible
151
152
  accessibilityLabel={`${step.title},${statusLabel}`}
152
153
  >
153
- <Icon
154
- name={PROCESS_STATUS_ICONS[step.status]}
154
+ <Glyph
155
+ size={r(18)}
155
156
  color={
156
157
  step.status === 'failed'
157
158
  ? colors.error
@@ -1,7 +1,11 @@
1
+ import {
2
+ ChevronDownOutlined,
3
+ ChevronUpOutlined,
4
+ SparkOutlined,
5
+ } from '@unif/react-native-icons';
1
6
  import { Pressable, ScrollView, Text, View } from 'react-native';
2
7
  import {
3
8
  Button,
4
- Icon,
5
9
  Pulse,
6
10
  Reveal,
7
11
  motion,
@@ -32,24 +36,28 @@ export function ProcessCompactStep({
32
36
  : step.status === 'failed'
33
37
  ? colors.error
34
38
  : colors.foregroundMuted;
35
- const icon = (
36
- <Icon
37
- name={
38
- running || step.status === 'completed'
39
- ? 'spark'
40
- : PROCESS_STATUS_ICONS[step.status]
41
- }
42
- size={14}
43
- color={color}
44
- />
45
- );
39
+ const Glyph =
40
+ step.icon ??
41
+ (running || step.status === 'completed'
42
+ ? SparkOutlined
43
+ : PROCESS_STATUS_ICONS[step.status]);
44
+ const icon =
45
+ step.icon === null ? null : (
46
+ <Glyph
47
+ size={14}
48
+ color={step.icon === undefined ? color : colors.foregroundMuted}
49
+ />
50
+ );
51
+ const Glyph2 = expanded ? ChevronUpOutlined : ChevronDownOutlined;
46
52
  return (
47
53
  <View>
48
54
  <Pressable
49
55
  testID={`process-step-${step.id}-toggle`}
50
56
  accessible
51
57
  accessibilityRole={hasDetails ? 'button' : undefined}
52
- accessibilityLabel={`${step.title},${statusText}${elapsed ? `,${elapsed}` : ''}`}
58
+ accessibilityLabel={[step.title, statusText, elapsed]
59
+ .filter(Boolean)
60
+ .join(',')}
53
61
  accessibilityState={hasDetails ? { expanded } : undefined}
54
62
  disabled={!hasDetails}
55
63
  hitSlop={10}
@@ -65,7 +73,7 @@ export function ProcessCompactStep({
65
73
  <View style={styles.spacer} />
66
74
  </>
67
75
  ) : null}
68
- {running ? (
76
+ {running && icon ? (
69
77
  <Pulse from={0.4} duration={motion.pulse / 2}>
70
78
  {icon}
71
79
  </Pulse>
@@ -81,14 +89,12 @@ export function ProcessCompactStep({
81
89
  {step.title}
82
90
  </Text>
83
91
  ) : null}
84
- <Text style={styles.compactStatus}>{statusText}</Text>
92
+ {statusText ? (
93
+ <Text style={styles.compactStatus}>{statusText}</Text>
94
+ ) : null}
85
95
  {elapsed ? <Text style={styles.elapsed}>{elapsed}</Text> : null}
86
96
  {hasDetails ? (
87
- <Icon
88
- name={expanded ? 'chevron-up' : 'chevron-down'}
89
- size={14}
90
- color={colors.foregroundSubtle}
91
- />
97
+ <Glyph2 size={14} color={colors.foregroundSubtle} />
92
98
  ) : null}
93
99
  </Pressable>
94
100
  {step.description ? (
@@ -1,7 +1,7 @@
1
+ import { CloseOutlined } from '@unif/react-native-icons';
1
2
  import { Text, View } from 'react-native';
2
3
  import {
3
4
  Button,
4
- Icon,
5
5
  StatusDot,
6
6
  icon,
7
7
  useColors,
@@ -35,7 +35,7 @@ export function ProcessTimelineStep({
35
35
  >
36
36
  <View style={styles.timelineGutter}>
37
37
  {step.status === 'cancelled' ? (
38
- <Icon name="close" size={icon.xs} color={colors.foregroundSubtle} />
38
+ <CloseOutlined size={icon.xs} color={colors.foregroundSubtle} />
39
39
  ) : (
40
40
  <StatusDot
41
41
  status={status}
@@ -1,4 +1,13 @@
1
- import type { IconName } from '@unif/react-native-design';
1
+ import {
2
+ CircleMinusOutlined,
3
+ CloseOutlined,
4
+ ErrorOutlined,
5
+ SuccessOutlined,
6
+ ThinkingOutlined,
7
+ } from '@unif/react-native-icons';
8
+ import type { ComponentType } from 'react';
9
+ import type { IconProps } from '@unif/react-native-icons';
10
+
2
11
  import type { ProcessStepStatus } from './types';
3
12
 
4
13
  export const PROCESS_STATUS_LABELS: Readonly<
@@ -12,11 +21,11 @@ export const PROCESS_STATUS_LABELS: Readonly<
12
21
  };
13
22
 
14
23
  export const PROCESS_STATUS_ICONS: Readonly<
15
- Record<ProcessStepStatus, IconName>
24
+ Record<ProcessStepStatus, ComponentType<IconProps>>
16
25
  > = {
17
- pending: 'circle-minus',
18
- running: 'thinking',
19
- completed: 'success',
20
- failed: 'error',
21
- cancelled: 'close',
26
+ pending: CircleMinusOutlined,
27
+ running: ThinkingOutlined,
28
+ completed: SuccessOutlined,
29
+ failed: ErrorOutlined,
30
+ cancelled: CloseOutlined,
22
31
  };
@@ -1,4 +1,7 @@
1
+ import type { ComponentType } from 'react';
2
+ import type { IconProps } from '@unif/react-native-icons';
1
3
  import type { ReactNode } from 'react';
4
+
2
5
  import type { StyleProp, ViewStyle } from 'react-native';
3
6
  import type { ChatAction } from '../../actions';
4
7
 
@@ -9,6 +12,8 @@ export interface ProcessStep {
9
12
  id: string;
10
13
  title: string;
11
14
  status: ProcessStepStatus;
15
+ /** compact 的活动图标;null 不显示,省略时沿状态呈现。 */
16
+ icon?: ComponentType<IconProps> | null;
12
17
  /** 调用者提供的状态显示文案;不改变 status 的语义。 */
13
18
  statusText?: string;
14
19
  description?: string;
@@ -1,5 +1,6 @@
1
+ import { ChevronRightOutlined } from '@unif/react-native-icons';
1
2
  import { Pressable, Text, View } from 'react-native';
2
- import { Icon, useThemedStyles } from '@unif/react-native-design';
3
+ import { r, useColors, useThemedStyles } from '@unif/react-native-design';
3
4
  import { DEFAULT_SOURCES_TITLE } from './constants';
4
5
  import { createStyles } from './styles';
5
6
  import type { SourceItem, SourcesProps } from './types';
@@ -12,6 +13,7 @@ export function Sources({
12
13
  testID,
13
14
  }: SourcesProps): React.JSX.Element | null {
14
15
  const styles = useThemedStyles(createStyles);
16
+ const colors = useColors();
15
17
 
16
18
  if (items.length === 0) return null;
17
19
 
@@ -26,7 +28,9 @@ export function Sources({
26
28
  <Text style={styles.description}>{item.description}</Text>
27
29
  ) : null}
28
30
  </View>
29
- {showChevron ? <Icon name="chevron-right" /> : null}
31
+ {showChevron ? (
32
+ <ChevronRightOutlined size={r(18)} color={colors.foregroundMuted} />
33
+ ) : null}
30
34
  </>
31
35
  );
32
36
 
@@ -1,5 +1,5 @@
1
1
  import { View } from 'react-native';
2
- import { Chip, Icon, useColors } from '@unif/react-native-design';
2
+ import { Chip, useColors } from '@unif/react-native-design';
3
3
  import { SUGGESTION_ICON_SIZE } from './constants';
4
4
  import { styles } from './styles';
5
5
  import type { SuggestionsProps } from './types';
@@ -29,11 +29,7 @@ export function Suggestions({
29
29
  disabled={item.disabled}
30
30
  leading={
31
31
  item.icon ? (
32
- <Icon
33
- name={item.icon}
34
- size={SUGGESTION_ICON_SIZE}
35
- color={colors.primary}
36
- />
32
+ <item.icon size={SUGGESTION_ICON_SIZE} color={colors.primary} />
37
33
  ) : undefined
38
34
  }
39
35
  onPress={onSelect ? () => onSelect(item) : undefined}
@@ -1,11 +1,13 @@
1
- import type { IconName } from '@unif/react-native-design';
1
+ import type { ComponentType } from 'react';
2
+ import type { IconProps } from '@unif/react-native-icons';
3
+
2
4
  import type { StyleProp, ViewStyle } from 'react-native';
3
5
 
4
6
  export interface SuggestionItem {
5
7
  id: string;
6
8
  label: string;
7
9
  /** 14 布局单位的主题主色图标,普通与选中状态保持相同图标样式。 */
8
- icon?: IconName;
10
+ icon?: ComponentType<IconProps>;
9
11
  selected?: boolean;
10
12
  loading?: boolean;
11
13
  disabled?: boolean;