@unif/react-native-design 0.28.0 → 0.30.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 (76) hide show
  1. package/README.md +14 -14
  2. package/jest-resolver.js +12 -1
  3. package/jest-setup.js +26 -8
  4. package/lib/module/components/ui/Avatar/Avatar.js +4 -3
  5. package/lib/module/components/ui/Avatar/Avatar.js.map +1 -1
  6. package/lib/module/components/ui/Avatar/styles.js +10 -2
  7. package/lib/module/components/ui/Avatar/styles.js.map +1 -1
  8. package/lib/module/components/ui/AvatarGroup/AvatarGroup.js +112 -0
  9. package/lib/module/components/ui/AvatarGroup/AvatarGroup.js.map +1 -0
  10. package/lib/module/components/ui/AvatarGroup/index.js +4 -0
  11. package/lib/module/components/ui/AvatarGroup/index.js.map +1 -0
  12. package/lib/module/components/ui/AvatarGroup/layout.js +44 -0
  13. package/lib/module/components/ui/AvatarGroup/layout.js.map +1 -0
  14. package/lib/module/components/ui/AvatarGroup/normalize.js +20 -0
  15. package/lib/module/components/ui/AvatarGroup/normalize.js.map +1 -0
  16. package/lib/module/components/ui/AvatarGroup/styles.js +20 -0
  17. package/lib/module/components/ui/AvatarGroup/styles.js.map +1 -0
  18. package/lib/module/components/ui/AvatarGroup/types.js +4 -0
  19. package/lib/module/components/ui/AvatarGroup/types.js.map +1 -0
  20. package/lib/module/components/ui/CircularProgress/CircularProgress.js +108 -0
  21. package/lib/module/components/ui/CircularProgress/CircularProgress.js.map +1 -0
  22. package/lib/module/components/ui/CircularProgress/index.js +4 -0
  23. package/lib/module/components/ui/CircularProgress/index.js.map +1 -0
  24. package/lib/module/components/ui/CircularProgress/normalizeCircularProgress.js +42 -0
  25. package/lib/module/components/ui/CircularProgress/normalizeCircularProgress.js.map +1 -0
  26. package/lib/module/components/ui/CircularProgress/types.js +4 -0
  27. package/lib/module/components/ui/CircularProgress/types.js.map +1 -0
  28. package/lib/module/components/ui/index.js +2 -0
  29. package/lib/module/components/ui/index.js.map +1 -1
  30. package/lib/typescript/manual-tests/runtime-api/RuntimeApiScreen.d.ts +1 -1
  31. package/lib/typescript/src/components/ui/Avatar/Avatar.d.ts +2 -2
  32. package/lib/typescript/src/components/ui/Avatar/Avatar.d.ts.map +1 -1
  33. package/lib/typescript/src/components/ui/Avatar/index.d.ts +1 -1
  34. package/lib/typescript/src/components/ui/Avatar/index.d.ts.map +1 -1
  35. package/lib/typescript/src/components/ui/Avatar/styles.d.ts +4 -2
  36. package/lib/typescript/src/components/ui/Avatar/styles.d.ts.map +1 -1
  37. package/lib/typescript/src/components/ui/Avatar/types.d.ts +4 -0
  38. package/lib/typescript/src/components/ui/Avatar/types.d.ts.map +1 -1
  39. package/lib/typescript/src/components/ui/AvatarGroup/AvatarGroup.d.ts +5 -0
  40. package/lib/typescript/src/components/ui/AvatarGroup/AvatarGroup.d.ts.map +1 -0
  41. package/lib/typescript/src/components/ui/AvatarGroup/index.d.ts +3 -0
  42. package/lib/typescript/src/components/ui/AvatarGroup/index.d.ts.map +1 -0
  43. package/lib/typescript/src/components/ui/AvatarGroup/layout.d.ts +16 -0
  44. package/lib/typescript/src/components/ui/AvatarGroup/layout.d.ts.map +1 -0
  45. package/lib/typescript/src/components/ui/AvatarGroup/normalize.d.ts +9 -0
  46. package/lib/typescript/src/components/ui/AvatarGroup/normalize.d.ts.map +1 -0
  47. package/lib/typescript/src/components/ui/AvatarGroup/styles.d.ts +17 -0
  48. package/lib/typescript/src/components/ui/AvatarGroup/styles.d.ts.map +1 -0
  49. package/lib/typescript/src/components/ui/AvatarGroup/types.d.ts +36 -0
  50. package/lib/typescript/src/components/ui/AvatarGroup/types.d.ts.map +1 -0
  51. package/lib/typescript/src/components/ui/CircularProgress/CircularProgress.d.ts +3 -0
  52. package/lib/typescript/src/components/ui/CircularProgress/CircularProgress.d.ts.map +1 -0
  53. package/lib/typescript/src/components/ui/CircularProgress/index.d.ts +3 -0
  54. package/lib/typescript/src/components/ui/CircularProgress/index.d.ts.map +1 -0
  55. package/lib/typescript/src/components/ui/CircularProgress/normalizeCircularProgress.d.ts +15 -0
  56. package/lib/typescript/src/components/ui/CircularProgress/normalizeCircularProgress.d.ts.map +1 -0
  57. package/lib/typescript/src/components/ui/CircularProgress/types.d.ts +24 -0
  58. package/lib/typescript/src/components/ui/CircularProgress/types.d.ts.map +1 -0
  59. package/lib/typescript/src/components/ui/index.d.ts +5 -1
  60. package/lib/typescript/src/components/ui/index.d.ts.map +1 -1
  61. package/package.json +12 -12
  62. package/src/components/ui/Avatar/Avatar.tsx +9 -3
  63. package/src/components/ui/Avatar/index.ts +6 -1
  64. package/src/components/ui/Avatar/styles.ts +14 -3
  65. package/src/components/ui/Avatar/types.ts +5 -0
  66. package/src/components/ui/AvatarGroup/AvatarGroup.tsx +147 -0
  67. package/src/components/ui/AvatarGroup/index.ts +2 -0
  68. package/src/components/ui/AvatarGroup/layout.ts +56 -0
  69. package/src/components/ui/AvatarGroup/normalize.ts +28 -0
  70. package/src/components/ui/AvatarGroup/styles.ts +19 -0
  71. package/src/components/ui/AvatarGroup/types.ts +40 -0
  72. package/src/components/ui/CircularProgress/CircularProgress.tsx +111 -0
  73. package/src/components/ui/CircularProgress/index.ts +2 -0
  74. package/src/components/ui/CircularProgress/normalizeCircularProgress.ts +64 -0
  75. package/src/components/ui/CircularProgress/types.ts +24 -0
  76. package/src/components/ui/index.ts +10 -1
@@ -0,0 +1,147 @@
1
+ import React, { useEffect } from 'react';
2
+ import { Text, View, type ViewStyle } from 'react-native';
3
+ import { Pressable } from 'react-native-gesture-handler';
4
+ import {
5
+ pressedOpacity,
6
+ scaleFontMetric,
7
+ useColors,
8
+ useFontScale,
9
+ useThemedStyles,
10
+ } from '../../../theme';
11
+ import { createLogger } from '../../../utils/logger';
12
+ import { childTestID } from '../../../utils/testID';
13
+ import { Avatar } from '../Avatar';
14
+ import { resolveAvatarBorderRadius, sizingFor } from '../Avatar/styles';
15
+ import { normalizeNonBlankText } from '../shared/accessibilityName';
16
+ import { resolveAvatarGroupLayout } from './layout';
17
+ import { normalizeAvatarGroup } from './normalize';
18
+ import { makeStyles } from './styles';
19
+ import type { AvatarGroupProps } from './types';
20
+
21
+ const log = createLogger('AvatarGroup');
22
+ const warned = new Set<string>();
23
+
24
+ function warnOnce(key: string, message: string): void {
25
+ if (warned.has(key)) return;
26
+ warned.add(key);
27
+ log.warn(message);
28
+ }
29
+
30
+ /** 重叠头像组;只拥有布局、溢出计数和可选溢出 action。 */
31
+ export function AvatarGroup({
32
+ items,
33
+ size = 'md',
34
+ shape = 'circle',
35
+ max,
36
+ style,
37
+ testID,
38
+ onOverflowPress,
39
+ overflowAccessibilityLabel,
40
+ overflowAccessibilityHint,
41
+ }: AvatarGroupProps): React.JSX.Element | null {
42
+ const colors = useColors();
43
+ const fontScale = useFontScale();
44
+ const styles = useThemedStyles(makeStyles);
45
+ const normalized = normalizeAvatarGroup(items, max);
46
+ const layout = resolveAvatarGroupLayout(size);
47
+ const avatarSizing = sizingFor(size);
48
+ const overflowFontSize = scaleFontMetric(avatarSizing.fs, fontScale);
49
+ const customOverflowLabel = normalizeNonBlankText(overflowAccessibilityLabel);
50
+ const hasBlankOverflowLabel =
51
+ normalized.overflowCount > 0 &&
52
+ onOverflowPress !== undefined &&
53
+ overflowAccessibilityLabel !== undefined &&
54
+ customOverflowLabel === undefined;
55
+
56
+ useEffect(() => {
57
+ if (typeof __DEV__ === 'undefined' || !__DEV__) return;
58
+ if (normalized.invalidMax) {
59
+ warnOnce(
60
+ `max:${String(max)}`,
61
+ `max 必须是大于等于 2 的有限整数,传入 ${String(max)},已展示全部成员。`
62
+ );
63
+ }
64
+ if (hasBlankOverflowLabel) {
65
+ warnOnce(
66
+ 'overflowAccessibilityLabel:blank',
67
+ 'overflowAccessibilityLabel 不能为空白,已回退默认名称。'
68
+ );
69
+ }
70
+ }, [hasBlankOverflowLabel, max, normalized.invalidMax]);
71
+
72
+ if (items.length === 0) return null;
73
+
74
+ const slotStyle = (index: number): ViewStyle => ({
75
+ borderColor: colors.surface,
76
+ borderWidth: layout.borderWidth,
77
+ marginStart: index === 0 ? 0 : -layout.overlap,
78
+ zIndex: index,
79
+ });
80
+ const overflowCount = normalized.overflowCount;
81
+ const overflowLabel = `+${overflowCount}`;
82
+ const overflowA11yLabel =
83
+ onOverflowPress === undefined
84
+ ? `还有 ${overflowCount} 位成员`
85
+ : (customOverflowLabel ?? `查看其余 ${overflowCount} 位成员`);
86
+ const overflowStyle: ViewStyle = {
87
+ ...slotStyle(normalized.visibleItems.length),
88
+ width: layout.box,
89
+ height: layout.box,
90
+ borderRadius: resolveAvatarBorderRadius(size, shape),
91
+ backgroundColor: colors.primaryContainer,
92
+ };
93
+ const overflowText = (
94
+ <Text
95
+ style={[
96
+ styles.overflowText,
97
+ { color: colors.primary, fontSize: overflowFontSize },
98
+ ]}
99
+ numberOfLines={1}
100
+ >
101
+ {overflowLabel}
102
+ </Text>
103
+ );
104
+
105
+ return (
106
+ <View style={[styles.root, style]} testID={testID}>
107
+ {normalized.visibleItems.map((item, index) => (
108
+ <Avatar
109
+ key={item.key}
110
+ label={item.label}
111
+ source={item.source}
112
+ variant={item.variant}
113
+ size={size}
114
+ shape={shape}
115
+ style={slotStyle(index)}
116
+ />
117
+ ))}
118
+ {overflowCount === 0 ? null : onOverflowPress === undefined ? (
119
+ <View
120
+ accessible
121
+ accessibilityLabel={overflowA11yLabel}
122
+ style={[styles.overflow, overflowStyle]}
123
+ testID={childTestID(testID, 'overflow')}
124
+ >
125
+ {overflowText}
126
+ </View>
127
+ ) : (
128
+ <Pressable
129
+ accessible
130
+ accessibilityRole="button"
131
+ accessibilityLabel={overflowA11yLabel}
132
+ accessibilityHint={overflowAccessibilityHint}
133
+ onPress={onOverflowPress}
134
+ hitSlop={layout.hitSlop}
135
+ style={({ pressed }) => [
136
+ styles.overflow,
137
+ overflowStyle,
138
+ { opacity: pressed ? pressedOpacity : 1 },
139
+ ]}
140
+ testID={childTestID(testID, 'overflow')}
141
+ >
142
+ {overflowText}
143
+ </Pressable>
144
+ )}
145
+ </View>
146
+ );
147
+ }
@@ -0,0 +1,2 @@
1
+ export { AvatarGroup } from './AvatarGroup';
2
+ export type { AvatarGroupItem, AvatarGroupProps } from './types';
@@ -0,0 +1,56 @@
1
+ import { avatar, fixed, r, space } from '../../../theme';
2
+ import type { AvatarSize } from '../Avatar';
3
+
4
+ export type AvatarGroupHitSlop = Readonly<{
5
+ top: number;
6
+ right: number;
7
+ bottom: number;
8
+ left: number;
9
+ }>;
10
+
11
+ export type ResolvedAvatarGroupLayout = Readonly<{
12
+ box: number;
13
+ overlap: number;
14
+ borderWidth: number;
15
+ hitSlop: AvatarGroupHitSlop;
16
+ }>;
17
+
18
+ /** 五档尺寸共享的重叠、分隔边与 44pt 命中区几何。 */
19
+ export function resolveAvatarGroupLayout(
20
+ size: AvatarSize
21
+ ): ResolvedAvatarGroupLayout {
22
+ const box = avatar[size];
23
+ let overlap: number;
24
+ let borderWidth: number;
25
+
26
+ switch (size) {
27
+ case 'xs':
28
+ overlap = space['1'];
29
+ borderWidth = r(1);
30
+ break;
31
+ case 'sm':
32
+ overlap = space['2'];
33
+ borderWidth = r(1);
34
+ break;
35
+ case 'md':
36
+ overlap = space['3'];
37
+ borderWidth = r(1);
38
+ break;
39
+ case 'lg':
40
+ overlap = space['4'];
41
+ borderWidth = r(2);
42
+ break;
43
+ case 'xl':
44
+ overlap = space['6'];
45
+ borderWidth = r(2);
46
+ break;
47
+ }
48
+
49
+ const inset = Math.max(0, (fixed.hitTarget - box) / 2);
50
+ return {
51
+ box,
52
+ overlap,
53
+ borderWidth,
54
+ hitSlop: { top: inset, right: inset, bottom: inset, left: inset },
55
+ };
56
+ }
@@ -0,0 +1,28 @@
1
+ import type { AvatarGroupItem } from './types';
2
+
3
+ export type NormalizedAvatarGroup = Readonly<{
4
+ visibleItems: readonly AvatarGroupItem[];
5
+ overflowCount: number;
6
+ invalidMax: boolean;
7
+ }>;
8
+
9
+ /** AvatarGroup 唯一的 max 与可见成员归一化入口。 */
10
+ export function normalizeAvatarGroup(
11
+ items: readonly AvatarGroupItem[],
12
+ max: number | undefined
13
+ ): NormalizedAvatarGroup {
14
+ const invalidMax =
15
+ max !== undefined &&
16
+ (!Number.isFinite(max) || !Number.isInteger(max) || max < 2);
17
+
18
+ if (max === undefined || invalidMax || items.length <= max) {
19
+ return { visibleItems: items, overflowCount: 0, invalidMax };
20
+ }
21
+
22
+ const visibleCount = max - 1;
23
+ return {
24
+ visibleItems: items.slice(0, visibleCount),
25
+ overflowCount: items.length - visibleCount,
26
+ invalidMax: false,
27
+ };
28
+ }
@@ -0,0 +1,19 @@
1
+ import { StyleSheet } from 'react-native';
2
+ import { fw, type ColorTokens } from '../../../theme';
3
+
4
+ export const makeStyles = (_colors: ColorTokens) =>
5
+ StyleSheet.create({
6
+ root: {
7
+ alignItems: 'center',
8
+ flexDirection: 'row',
9
+ },
10
+ overflow: {
11
+ alignItems: 'center',
12
+ justifyContent: 'center',
13
+ overflow: 'hidden',
14
+ },
15
+ overflowText: {
16
+ fontWeight: fw.semi,
17
+ lineHeight: undefined,
18
+ },
19
+ });
@@ -0,0 +1,40 @@
1
+ import type { ImageSourcePropType, StyleProp, ViewStyle } from 'react-native';
2
+ import type { AvatarShape, AvatarSize, AvatarVariant } from '../Avatar';
3
+
4
+ export type AvatarGroupItem = Readonly<{
5
+ /** 列表内唯一且稳定的身份键。 */
6
+ key: string;
7
+ /** 可见回退文字与 Avatar accessible name。 */
8
+ label: string;
9
+ source?: ImageSourcePropType;
10
+ variant?: AvatarVariant;
11
+ }>;
12
+
13
+ type SharedAvatarGroupProps = {
14
+ items: readonly AvatarGroupItem[];
15
+ /** 所有成员共用的尺寸,默认 'md'。 */
16
+ size?: AvatarSize;
17
+ /** 所有成员与溢出位共用的形态,默认 'circle'。 */
18
+ shape?: AvatarShape;
19
+ /** 最大视觉位数量,包含 +N 溢出位,必须是大于等于 2 的整数。 */
20
+ max?: number;
21
+ style?: StyleProp<ViewStyle>;
22
+ testID?: string;
23
+ };
24
+
25
+ type StaticOverflowProps = {
26
+ onOverflowPress?: never;
27
+ overflowAccessibilityLabel?: never;
28
+ overflowAccessibilityHint?: never;
29
+ };
30
+
31
+ type ActionableOverflowProps = {
32
+ onOverflowPress: () => void;
33
+ /** 默认按实际数量生成“查看其余 N 位成员”。 */
34
+ overflowAccessibilityLabel?: string;
35
+ /** 描述打开弹层、抽屉或跳转等消费端结果。 */
36
+ overflowAccessibilityHint?: string;
37
+ };
38
+
39
+ export type AvatarGroupProps = SharedAvatarGroupProps &
40
+ (StaticOverflowProps | ActionableOverflowProps);
@@ -0,0 +1,111 @@
1
+ import { Text, View } from 'react-native';
2
+ import type { TextStyle, ViewStyle } from 'react-native';
3
+ import Svg, { Circle } from 'react-native-svg';
4
+ import { r, type, useColors } from '../../../theme';
5
+ import { A11Y_HIDDEN_PROPS } from '../shared/a11y';
6
+ import { normalizeCircularProgress } from './normalizeCircularProgress';
7
+ import type { CircularProgressProps } from './types';
8
+
9
+ const OUTER_CENTER_STYLE = {
10
+ alignItems: 'center',
11
+ justifyContent: 'center',
12
+ } as const satisfies ViewStyle;
13
+
14
+ const VISUAL_CONTAINER_STYLE = {
15
+ position: 'relative',
16
+ } as const satisfies ViewStyle;
17
+
18
+ const LABEL_CENTER_STYLE = {
19
+ fontWeight: '600',
20
+ left: 0,
21
+ position: 'absolute',
22
+ textAlign: 'center',
23
+ top: 0,
24
+ } as const satisfies TextStyle;
25
+
26
+ export function CircularProgress({
27
+ value,
28
+ size = r(32),
29
+ thickness = r(2),
30
+ color,
31
+ trackColor,
32
+ showLabel = false,
33
+ labelColor,
34
+ accessibilityLabel = '进度',
35
+ style,
36
+ testID,
37
+ }: CircularProgressProps): React.JSX.Element {
38
+ const colors = useColors();
39
+ const normalized = normalizeCircularProgress({ value, size, thickness });
40
+ const {
41
+ circumference,
42
+ dashOffset,
43
+ percentage,
44
+ radius,
45
+ safeSize,
46
+ safeThickness,
47
+ } = normalized;
48
+ const center = safeSize / 2;
49
+
50
+ return (
51
+ <View
52
+ accessible
53
+ accessibilityLabel={accessibilityLabel}
54
+ accessibilityRole="progressbar"
55
+ accessibilityValue={{
56
+ min: 0,
57
+ max: 100,
58
+ now: percentage,
59
+ text: `${percentage}%`,
60
+ }}
61
+ style={[{ height: safeSize, width: safeSize }, style, OUTER_CENTER_STYLE]}
62
+ testID={testID}
63
+ >
64
+ <View
65
+ style={[{ height: safeSize, width: safeSize }, VISUAL_CONTAINER_STYLE]}
66
+ {...A11Y_HIDDEN_PROPS}
67
+ >
68
+ <Svg height={safeSize} width={safeSize}>
69
+ <Circle
70
+ cx={center}
71
+ cy={center}
72
+ fill="none"
73
+ r={radius}
74
+ stroke={trackColor ?? colors.outline}
75
+ strokeWidth={safeThickness}
76
+ />
77
+ <Circle
78
+ cx={center}
79
+ cy={center}
80
+ fill="none"
81
+ r={radius}
82
+ rotation={-90}
83
+ originX={center}
84
+ originY={center}
85
+ stroke={color ?? colors.primary}
86
+ strokeDasharray={circumference}
87
+ strokeDashoffset={dashOffset}
88
+ strokeLinecap="round"
89
+ strokeWidth={safeThickness}
90
+ />
91
+ </Svg>
92
+ {showLabel ? (
93
+ <Text
94
+ style={[
95
+ {
96
+ color: labelColor ?? colors.foreground,
97
+ fontSize: type.nano,
98
+ height: safeSize,
99
+ lineHeight: safeSize,
100
+ width: safeSize,
101
+ },
102
+ LABEL_CENTER_STYLE,
103
+ ]}
104
+ >
105
+ {`${percentage}%`}
106
+ </Text>
107
+ ) : null}
108
+ </View>
109
+ </View>
110
+ );
111
+ }
@@ -0,0 +1,2 @@
1
+ export { CircularProgress } from './CircularProgress';
2
+ export type { CircularProgressProps } from './types';
@@ -0,0 +1,64 @@
1
+ import { createLogger } from '../../../utils/logger';
2
+
3
+ const log = createLogger('CircularProgress');
4
+ const warnedKeys = new Set<string>();
5
+
6
+ export type NormalizedCircularProgress = Readonly<{
7
+ safeValue: number;
8
+ percentage: number;
9
+ safeSize: number;
10
+ safeThickness: number;
11
+ radius: number;
12
+ circumference: number;
13
+ dashOffset: number;
14
+ }>;
15
+
16
+ function warnOnce(key: string, message: string): void {
17
+ if (warnedKeys.has(key)) return;
18
+ warnedKeys.add(key);
19
+ log.warn(message);
20
+ }
21
+
22
+ export function normalizeCircularProgress(input: {
23
+ value: number;
24
+ size: number;
25
+ thickness: number;
26
+ }): NormalizedCircularProgress {
27
+ const { value, size, thickness } = input;
28
+
29
+ if (!Number.isFinite(value) || value < 0 || value > 1) {
30
+ warnOnce(
31
+ `value:${value}`,
32
+ `value 应为 0..1 的有限数,传入 ${value},已收敛到安全范围`
33
+ );
34
+ }
35
+ if (!Number.isFinite(size) || size < 16) {
36
+ warnOnce(`size:${size}`, `size 应为 ≥16 的有限数,传入 ${size},已钳到 16`);
37
+ }
38
+ if (!Number.isFinite(thickness) || thickness <= 0) {
39
+ warnOnce(
40
+ `thickness:${thickness}`,
41
+ `thickness 应为正有限数,传入 ${thickness},已 fallback 为 2`
42
+ );
43
+ }
44
+
45
+ const safeValue = Number.isFinite(value)
46
+ ? Math.min(1, Math.max(0, value))
47
+ : 0;
48
+ const safeSize = Number.isFinite(size) && size >= 16 ? size : 16;
49
+ const fallbackThickness =
50
+ Number.isFinite(thickness) && thickness > 0 ? thickness : 2;
51
+ const safeThickness = Math.min(fallbackThickness, safeSize / 2);
52
+ const radius = (safeSize - safeThickness) / 2;
53
+ const circumference = 2 * Math.PI * radius;
54
+
55
+ return {
56
+ safeValue,
57
+ percentage: Math.round(safeValue * 100),
58
+ safeSize,
59
+ safeThickness,
60
+ radius,
61
+ circumference,
62
+ dashOffset: circumference * (1 - safeValue),
63
+ };
64
+ }
@@ -0,0 +1,24 @@
1
+ import type { StyleProp, ViewStyle } from 'react-native';
2
+
3
+ export type CircularProgressProps = {
4
+ /** 当前进度,使用 0..1;越界值会收敛到边界,非有限值按 0 处理。 */
5
+ value: number;
6
+ /** 圆环直径,默认 32,最小 16。 */
7
+ size?: number;
8
+ /** 圆环描边宽度,默认 2,最大为半径。 */
9
+ thickness?: number;
10
+ /** 进度颜色,默认 c.primary。 */
11
+ color?: string;
12
+ /** 轨道颜色,默认 c.outline。 */
13
+ trackColor?: string;
14
+ /** 是否在圆环中央显示取整后的百分比,默认 false。 */
15
+ showLabel?: boolean;
16
+ /** 百分比文字颜色,默认 c.foreground。 */
17
+ labelColor?: string;
18
+ /** 进度条可访问性名称,默认“进度”。 */
19
+ accessibilityLabel?: string;
20
+ /** 外层布局样式。 */
21
+ style?: StyleProp<ViewStyle>;
22
+ /** E2E / 测试定位。 */
23
+ testID?: string;
24
+ };
@@ -1,5 +1,12 @@
1
1
  export { Avatar } from './Avatar';
2
- export type { AvatarProps, AvatarSize, AvatarVariant } from './Avatar';
2
+ export type {
3
+ AvatarProps,
4
+ AvatarShape,
5
+ AvatarSize,
6
+ AvatarVariant,
7
+ } from './Avatar';
8
+ export { AvatarGroup } from './AvatarGroup';
9
+ export type { AvatarGroupItem, AvatarGroupProps } from './AvatarGroup';
3
10
  export { BlurLayer } from './BlurLayer';
4
11
  export type { BlurLayerProps } from './BlurLayer';
5
12
  export { Button } from './Button';
@@ -20,6 +27,8 @@ export { Checkbox } from './Checkbox';
20
27
  export type { CheckboxProps } from './Checkbox';
21
28
  export { Chip } from './Chip';
22
29
  export type { ChipProps } from './Chip';
30
+ export { CircularProgress } from './CircularProgress';
31
+ export type { CircularProgressProps } from './CircularProgress';
23
32
  export { confirm, ConfirmHost } from './Confirm';
24
33
  export type { ConfirmOptions } from './Confirm';
25
34
  export { DrawerHeader } from './DrawerHeader';