@unif/react-native-ui 0.1.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/LICENSE +20 -0
- package/README.md +103 -0
- package/lib/module/README.md +99 -0
- package/lib/module/action-sheet/index.js +63 -0
- package/lib/module/action-sheet/index.js.map +1 -0
- package/lib/module/action-sheet/index.md +69 -0
- package/lib/module/action-sheet/style/index.js +38 -0
- package/lib/module/action-sheet/style/index.js.map +1 -0
- package/lib/module/avatar/index.js +42 -0
- package/lib/module/avatar/index.js.map +1 -0
- package/lib/module/avatar/index.md +51 -0
- package/lib/module/avatar/style/index.js +17 -0
- package/lib/module/avatar/style/index.js.map +1 -0
- package/lib/module/button/index.js +52 -0
- package/lib/module/button/index.js.map +1 -0
- package/lib/module/button/index.md +90 -0
- package/lib/module/button/style/index.js +94 -0
- package/lib/module/button/style/index.js.map +1 -0
- package/lib/module/center/index.js +21 -0
- package/lib/module/center/index.js.map +1 -0
- package/lib/module/center/index.md +28 -0
- package/lib/module/center/style/index.js +10 -0
- package/lib/module/center/style/index.js.map +1 -0
- package/lib/module/chip/index.js +59 -0
- package/lib/module/chip/index.js.map +1 -0
- package/lib/module/chip/index.md +60 -0
- package/lib/module/chip/style/index.js +40 -0
- package/lib/module/chip/style/index.js.map +1 -0
- package/lib/module/column/index.js +30 -0
- package/lib/module/column/index.js.map +1 -0
- package/lib/module/column/index.md +34 -0
- package/lib/module/column/style/index.js +9 -0
- package/lib/module/column/style/index.js.map +1 -0
- package/lib/module/divider/index.js +21 -0
- package/lib/module/divider/index.js.map +1 -0
- package/lib/module/divider/index.md +44 -0
- package/lib/module/divider/style/index.js +17 -0
- package/lib/module/divider/style/index.js.map +1 -0
- package/lib/module/hooks/index.js +4 -0
- package/lib/module/hooks/index.js.map +1 -0
- package/lib/module/hooks/index.md +71 -0
- package/lib/module/hooks/useMergeStyles.js +27 -0
- package/lib/module/hooks/useMergeStyles.js.map +1 -0
- package/lib/module/index.js +29 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/input/index.js +69 -0
- package/lib/module/input/index.js.map +1 -0
- package/lib/module/input/index.md +73 -0
- package/lib/module/input/style/index.js +27 -0
- package/lib/module/input/style/index.js.map +1 -0
- package/lib/module/list-item/index.js +69 -0
- package/lib/module/list-item/index.js.map +1 -0
- package/lib/module/list-item/index.md +101 -0
- package/lib/module/list-item/style/index.js +39 -0
- package/lib/module/list-item/style/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/popover/index.js +60 -0
- package/lib/module/popover/index.js.map +1 -0
- package/lib/module/popover/index.md +57 -0
- package/lib/module/popover/style/index.js +22 -0
- package/lib/module/popover/style/index.js.map +1 -0
- package/lib/module/row/index.js +31 -0
- package/lib/module/row/index.js.map +1 -0
- package/lib/module/row/index.md +46 -0
- package/lib/module/row/style/index.js +15 -0
- package/lib/module/row/style/index.js.map +1 -0
- package/lib/module/space/index.js +20 -0
- package/lib/module/space/index.js.map +1 -0
- package/lib/module/space/index.md +31 -0
- package/lib/module/space/style/index.js +9 -0
- package/lib/module/space/style/index.js.map +1 -0
- package/lib/module/text/index.js +30 -0
- package/lib/module/text/index.js.map +1 -0
- package/lib/module/text/index.md +63 -0
- package/lib/module/text/style/index.js +51 -0
- package/lib/module/text/style/index.js.map +1 -0
- package/lib/module/theme/config.js +27 -0
- package/lib/module/theme/config.js.map +1 -0
- package/lib/module/theme/tokens.js +67 -0
- package/lib/module/theme/tokens.js.map +1 -0
- package/lib/module/touchable/index.js +35 -0
- package/lib/module/touchable/index.js.map +1 -0
- package/lib/module/touchable/index.md +42 -0
- package/lib/module/touchable/style/index.js +9 -0
- package/lib/module/touchable/style/index.js.map +1 -0
- package/lib/module/wave-animation/index.js +67 -0
- package/lib/module/wave-animation/index.js.map +1 -0
- package/lib/module/wave-animation/index.md +50 -0
- package/lib/typescript/jest.setup.d.ts +1 -0
- package/lib/typescript/jest.setup.d.ts.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/action-sheet/index.d.ts +22 -0
- package/lib/typescript/src/action-sheet/index.d.ts.map +1 -0
- package/lib/typescript/src/action-sheet/style/index.d.ts +16 -0
- package/lib/typescript/src/action-sheet/style/index.d.ts.map +1 -0
- package/lib/typescript/src/avatar/index.d.ts +19 -0
- package/lib/typescript/src/avatar/index.d.ts.map +1 -0
- package/lib/typescript/src/avatar/style/index.d.ts +7 -0
- package/lib/typescript/src/avatar/style/index.d.ts.map +1 -0
- package/lib/typescript/src/button/index.d.ts +24 -0
- package/lib/typescript/src/button/index.d.ts.map +1 -0
- package/lib/typescript/src/button/style/index.d.ts +16 -0
- package/lib/typescript/src/button/style/index.d.ts.map +1 -0
- package/lib/typescript/src/center/index.d.ts +11 -0
- package/lib/typescript/src/center/index.d.ts.map +1 -0
- package/lib/typescript/src/center/style/index.d.ts +5 -0
- package/lib/typescript/src/center/style/index.d.ts.map +1 -0
- package/lib/typescript/src/chip/index.d.ts +22 -0
- package/lib/typescript/src/chip/index.d.ts.map +1 -0
- package/lib/typescript/src/chip/style/index.d.ts +10 -0
- package/lib/typescript/src/chip/style/index.d.ts.map +1 -0
- package/lib/typescript/src/column/index.d.ts +20 -0
- package/lib/typescript/src/column/index.d.ts.map +1 -0
- package/lib/typescript/src/column/style/index.d.ts +4 -0
- package/lib/typescript/src/column/style/index.d.ts.map +1 -0
- package/lib/typescript/src/divider/index.d.ts +13 -0
- package/lib/typescript/src/divider/index.d.ts.map +1 -0
- package/lib/typescript/src/divider/style/index.d.ts +9 -0
- package/lib/typescript/src/divider/style/index.d.ts.map +1 -0
- package/lib/typescript/src/hooks/index.d.ts +2 -0
- package/lib/typescript/src/hooks/index.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useMergeStyles.d.ts +13 -0
- package/lib/typescript/src/hooks/useMergeStyles.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +39 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/input/index.d.ts +29 -0
- package/lib/typescript/src/input/index.d.ts.map +1 -0
- package/lib/typescript/src/input/style/index.d.ts +8 -0
- package/lib/typescript/src/input/style/index.d.ts.map +1 -0
- package/lib/typescript/src/list-item/index.d.ts +25 -0
- package/lib/typescript/src/list-item/index.d.ts.map +1 -0
- package/lib/typescript/src/list-item/style/index.d.ts +17 -0
- package/lib/typescript/src/list-item/style/index.d.ts.map +1 -0
- package/lib/typescript/src/popover/index.d.ts +27 -0
- package/lib/typescript/src/popover/index.d.ts.map +1 -0
- package/lib/typescript/src/popover/style/index.d.ts +7 -0
- package/lib/typescript/src/popover/style/index.d.ts.map +1 -0
- package/lib/typescript/src/row/index.d.ts +22 -0
- package/lib/typescript/src/row/index.d.ts.map +1 -0
- package/lib/typescript/src/row/style/index.d.ts +8 -0
- package/lib/typescript/src/row/style/index.d.ts.map +1 -0
- package/lib/typescript/src/space/index.d.ts +15 -0
- package/lib/typescript/src/space/index.d.ts.map +1 -0
- package/lib/typescript/src/space/style/index.d.ts +7 -0
- package/lib/typescript/src/space/style/index.d.ts.map +1 -0
- package/lib/typescript/src/text/index.d.ts +18 -0
- package/lib/typescript/src/text/index.d.ts.map +1 -0
- package/lib/typescript/src/text/style/index.d.ts +35 -0
- package/lib/typescript/src/text/style/index.d.ts.map +1 -0
- package/lib/typescript/src/theme/config.d.ts +18 -0
- package/lib/typescript/src/theme/config.d.ts.map +1 -0
- package/lib/typescript/src/theme/tokens.d.ts +61 -0
- package/lib/typescript/src/theme/tokens.d.ts.map +1 -0
- package/lib/typescript/src/touchable/index.d.ts +19 -0
- package/lib/typescript/src/touchable/index.d.ts.map +1 -0
- package/lib/typescript/src/touchable/style/index.d.ts +4 -0
- package/lib/typescript/src/touchable/style/index.d.ts.map +1 -0
- package/lib/typescript/src/wave-animation/index.d.ts +20 -0
- package/lib/typescript/src/wave-animation/index.d.ts.map +1 -0
- package/lib/typescript/tests/component/component.coverage.test.d.ts +2 -0
- package/lib/typescript/tests/component/component.coverage.test.d.ts.map +1 -0
- package/lib/typescript/tests/component/component.interaction.test.d.ts +2 -0
- package/lib/typescript/tests/component/component.interaction.test.d.ts.map +1 -0
- package/lib/typescript/tests/component/component.snapshot.test.d.ts +2 -0
- package/lib/typescript/tests/component/component.snapshot.test.d.ts.map +1 -0
- package/lib/typescript/tests/e2e/app.e2e.test.d.ts +2 -0
- package/lib/typescript/tests/e2e/app.e2e.test.d.ts.map +1 -0
- package/lib/typescript/tests/integration/ui.integration.test.d.ts +2 -0
- package/lib/typescript/tests/integration/ui.integration.test.d.ts.map +1 -0
- package/lib/typescript/tests/unit/mergeStyles.unit.test.d.ts +2 -0
- package/lib/typescript/tests/unit/mergeStyles.unit.test.d.ts.map +1 -0
- package/lib/typescript/tests/unit/public-api.unit.test.d.ts +2 -0
- package/lib/typescript/tests/unit/public-api.unit.test.d.ts.map +1 -0
- package/lib/typescript/tests/unit/theme-config.unit.test.d.ts +2 -0
- package/lib/typescript/tests/unit/theme-config.unit.test.d.ts.map +1 -0
- package/package.json +134 -0
- package/src/README.md +99 -0
- package/src/action-sheet/index.md +69 -0
- package/src/action-sheet/index.tsx +85 -0
- package/src/action-sheet/style/index.tsx +52 -0
- package/src/avatar/index.md +51 -0
- package/src/avatar/index.tsx +56 -0
- package/src/avatar/style/index.tsx +21 -0
- package/src/button/index.md +90 -0
- package/src/button/index.tsx +86 -0
- package/src/button/style/index.tsx +67 -0
- package/src/center/index.md +28 -0
- package/src/center/index.tsx +18 -0
- package/src/center/style/index.tsx +8 -0
- package/src/chip/index.md +60 -0
- package/src/chip/index.tsx +80 -0
- package/src/chip/style/index.tsx +47 -0
- package/src/column/index.md +34 -0
- package/src/column/index.tsx +43 -0
- package/src/column/style/index.tsx +7 -0
- package/src/divider/index.md +44 -0
- package/src/divider/index.tsx +30 -0
- package/src/divider/style/index.tsx +13 -0
- package/src/hooks/index.md +71 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useMergeStyles.ts +27 -0
- package/src/index.tsx +49 -0
- package/src/input/index.md +73 -0
- package/src/input/index.tsx +95 -0
- package/src/input/style/index.tsx +32 -0
- package/src/list-item/index.md +101 -0
- package/src/list-item/index.tsx +91 -0
- package/src/list-item/style/index.tsx +41 -0
- package/src/popover/index.md +57 -0
- package/src/popover/index.tsx +80 -0
- package/src/popover/style/index.tsx +23 -0
- package/src/row/index.md +46 -0
- package/src/row/index.tsx +47 -0
- package/src/row/style/index.tsx +14 -0
- package/src/space/index.md +31 -0
- package/src/space/index.tsx +28 -0
- package/src/space/style/index.tsx +3 -0
- package/src/text/index.md +63 -0
- package/src/text/index.tsx +45 -0
- package/src/text/style/index.tsx +32 -0
- package/src/theme/config.ts +26 -0
- package/src/theme/tokens.ts +66 -0
- package/src/touchable/index.md +42 -0
- package/src/touchable/index.tsx +45 -0
- package/src/touchable/style/index.tsx +5 -0
- package/src/wave-animation/index.md +50 -0
- package/src/wave-animation/index.tsx +93 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Popover 基础组件
|
|
3
|
+
*
|
|
4
|
+
* 锚定定位下拉容器,仅做定位,内容由 children 传入。
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React, { useMemo } from 'react';
|
|
8
|
+
import {
|
|
9
|
+
View,
|
|
10
|
+
TouchableWithoutFeedback,
|
|
11
|
+
Modal,
|
|
12
|
+
} from 'react-native';
|
|
13
|
+
import type { ViewStyle } from 'react-native';
|
|
14
|
+
import { mergeStyles } from '../hooks';
|
|
15
|
+
import type { PopoverSemanticStyles } from './style';
|
|
16
|
+
import { DEFAULT_STYLES } from './style';
|
|
17
|
+
|
|
18
|
+
export interface PopoverProps {
|
|
19
|
+
visible: boolean;
|
|
20
|
+
onClose: () => void;
|
|
21
|
+
anchorLayout: { x: number; y: number; width: number; height: number };
|
|
22
|
+
width?: number;
|
|
23
|
+
placement?: 'bottom' | 'top';
|
|
24
|
+
children: React.ReactNode;
|
|
25
|
+
style?: ViewStyle;
|
|
26
|
+
styles?: Partial<PopoverSemanticStyles>;
|
|
27
|
+
testID?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const GAP = 4;
|
|
31
|
+
|
|
32
|
+
const Popover: React.FC<PopoverProps> = ({
|
|
33
|
+
visible,
|
|
34
|
+
onClose,
|
|
35
|
+
anchorLayout,
|
|
36
|
+
width = 180,
|
|
37
|
+
placement = 'bottom',
|
|
38
|
+
children,
|
|
39
|
+
style,
|
|
40
|
+
styles: semanticStyles,
|
|
41
|
+
testID,
|
|
42
|
+
}) => {
|
|
43
|
+
const s = useMemo(
|
|
44
|
+
() => mergeStyles<PopoverSemanticStyles>(DEFAULT_STYLES, semanticStyles),
|
|
45
|
+
[semanticStyles],
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
if (!visible) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const positionStyle: ViewStyle =
|
|
53
|
+
placement === 'bottom'
|
|
54
|
+
? { top: anchorLayout.y + anchorLayout.height + GAP, left: anchorLayout.x }
|
|
55
|
+
: { bottom: anchorLayout.y - GAP, left: anchorLayout.x };
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<Modal
|
|
59
|
+
visible={visible}
|
|
60
|
+
transparent
|
|
61
|
+
animationType="fade"
|
|
62
|
+
onRequestClose={onClose}
|
|
63
|
+
>
|
|
64
|
+
<TouchableWithoutFeedback onPress={onClose}>
|
|
65
|
+
<View style={s.overlay}>
|
|
66
|
+
<TouchableWithoutFeedback>
|
|
67
|
+
<View
|
|
68
|
+
style={[s.content, positionStyle, { width }, style]}
|
|
69
|
+
testID={testID}
|
|
70
|
+
>
|
|
71
|
+
{children}
|
|
72
|
+
</View>
|
|
73
|
+
</TouchableWithoutFeedback>
|
|
74
|
+
</View>
|
|
75
|
+
</TouchableWithoutFeedback>
|
|
76
|
+
</Modal>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export default Popover;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ViewStyle } from 'react-native';
|
|
2
|
+
import { tokens } from '../../theme/tokens';
|
|
3
|
+
|
|
4
|
+
export type PopoverSemanticStyles = {
|
|
5
|
+
overlay?: ViewStyle;
|
|
6
|
+
content?: ViewStyle;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const DEFAULT_STYLES: PopoverSemanticStyles = {
|
|
10
|
+
overlay: {
|
|
11
|
+
flex: 1,
|
|
12
|
+
},
|
|
13
|
+
content: {
|
|
14
|
+
position: 'absolute',
|
|
15
|
+
backgroundColor: tokens.colorBgElevated,
|
|
16
|
+
borderRadius: 12,
|
|
17
|
+
shadowColor: '#000',
|
|
18
|
+
shadowOffset: { width: 0, height: 4 },
|
|
19
|
+
shadowOpacity: 0.12,
|
|
20
|
+
shadowRadius: 12,
|
|
21
|
+
elevation: 8,
|
|
22
|
+
},
|
|
23
|
+
};
|
package/src/row/index.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Row 水平布局
|
|
2
|
+
|
|
3
|
+
水平排列子元素,默认垂直居中。替代 `flexDirection: 'row' + alignItems: 'center'` 的手写样式。
|
|
4
|
+
|
|
5
|
+
## 何时使用
|
|
6
|
+
|
|
7
|
+
- 需要水平排列元素时
|
|
8
|
+
- 替代 `<View style={{flexDirection: 'row', alignItems: 'center'}}>` 的场景
|
|
9
|
+
|
|
10
|
+
## 代码演示
|
|
11
|
+
|
|
12
|
+
```tsx
|
|
13
|
+
// 基础用法 — 默认 alignItems: 'center'
|
|
14
|
+
<Row>
|
|
15
|
+
<Icon name="star" />
|
|
16
|
+
<Text>标题</Text>
|
|
17
|
+
</Row>
|
|
18
|
+
|
|
19
|
+
// 两端对齐
|
|
20
|
+
<Row justify="space-between">
|
|
21
|
+
<Text>左侧</Text>
|
|
22
|
+
<Text>右侧</Text>
|
|
23
|
+
</Row>
|
|
24
|
+
|
|
25
|
+
// 间距
|
|
26
|
+
<Row gap={10}>
|
|
27
|
+
<Button block onPress={...}>修改</Button>
|
|
28
|
+
<Button block onPress={...}>确认</Button>
|
|
29
|
+
</Row>
|
|
30
|
+
|
|
31
|
+
// 换行
|
|
32
|
+
<Row wrap gap={8}>
|
|
33
|
+
{tags.map(tag => <Tag key={tag}>{tag}</Tag>)}
|
|
34
|
+
</Row>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## API
|
|
38
|
+
|
|
39
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
40
|
+
|------|------|------|--------|
|
|
41
|
+
| align | alignItems | `ViewStyle['alignItems']` | `'center'` |
|
|
42
|
+
| justify | justifyContent | `ViewStyle['justifyContent']` | - |
|
|
43
|
+
| gap | 子元素间距 | `number` | - |
|
|
44
|
+
| wrap | 是否换行 | `boolean` | `false` |
|
|
45
|
+
|
|
46
|
+
> 继承所有 RN `ViewProps`(`style`、`testID` 等)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 水平布局容器
|
|
3
|
+
*
|
|
4
|
+
* 默认 flexDirection: 'row' + alignItems: 'center'。
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import { View } from 'react-native';
|
|
9
|
+
import type { ViewProps, ViewStyle } from 'react-native';
|
|
10
|
+
import { baseStyle, wrapStyle } from './style';
|
|
11
|
+
|
|
12
|
+
type AlignItems = ViewStyle['alignItems'];
|
|
13
|
+
type JustifyContent = ViewStyle['justifyContent'];
|
|
14
|
+
|
|
15
|
+
export interface RowProps extends ViewProps {
|
|
16
|
+
/** alignItems,默认 'center' */
|
|
17
|
+
align?: AlignItems;
|
|
18
|
+
/** justifyContent */
|
|
19
|
+
justify?: JustifyContent;
|
|
20
|
+
/** 子元素间距 */
|
|
21
|
+
gap?: number;
|
|
22
|
+
/** 是否换行 */
|
|
23
|
+
wrap?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const Row: React.FC<RowProps> = ({
|
|
27
|
+
align,
|
|
28
|
+
justify,
|
|
29
|
+
gap,
|
|
30
|
+
wrap,
|
|
31
|
+
style,
|
|
32
|
+
...rest
|
|
33
|
+
}: RowProps) => (
|
|
34
|
+
<View
|
|
35
|
+
style={[
|
|
36
|
+
baseStyle,
|
|
37
|
+
align != null && { alignItems: align },
|
|
38
|
+
justify != null && { justifyContent: justify },
|
|
39
|
+
gap != null && { gap },
|
|
40
|
+
wrap && wrapStyle,
|
|
41
|
+
style,
|
|
42
|
+
]}
|
|
43
|
+
{...rest}
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
export default Row;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export const baseStyle = StyleSheet.create({
|
|
4
|
+
row: {
|
|
5
|
+
flexDirection: 'row',
|
|
6
|
+
alignItems: 'center',
|
|
7
|
+
},
|
|
8
|
+
}).row;
|
|
9
|
+
|
|
10
|
+
export const wrapStyle = StyleSheet.create({
|
|
11
|
+
wrap: {
|
|
12
|
+
flexWrap: 'wrap',
|
|
13
|
+
},
|
|
14
|
+
}).wrap;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Space 间距占位
|
|
2
|
+
|
|
3
|
+
在两个元素之间插入固定间距。替代 `<View style={{height: 12}} />` 或 `marginTop` 手写。
|
|
4
|
+
|
|
5
|
+
## 何时使用
|
|
6
|
+
|
|
7
|
+
- 两个块级元素之间需要固定间距
|
|
8
|
+
- 不想在元素上写 margin 时
|
|
9
|
+
|
|
10
|
+
## 代码演示
|
|
11
|
+
|
|
12
|
+
```tsx
|
|
13
|
+
// 垂直间距(默认)
|
|
14
|
+
<Text variant="title">标题</Text>
|
|
15
|
+
<Space size={16} />
|
|
16
|
+
<Text variant="body">正文内容</Text>
|
|
17
|
+
|
|
18
|
+
// 水平间距
|
|
19
|
+
<Row>
|
|
20
|
+
<Icon name="star" />
|
|
21
|
+
<Space size={8} direction="horizontal" />
|
|
22
|
+
<Text>收藏</Text>
|
|
23
|
+
</Row>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## API
|
|
27
|
+
|
|
28
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
29
|
+
|------|------|------|--------|
|
|
30
|
+
| size | 间距大小(px) | `number` | `12` |
|
|
31
|
+
| direction | 方向 | `'vertical'` \| `'horizontal'` | `'vertical'` |
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 间距占位组件
|
|
3
|
+
*
|
|
4
|
+
* 在两个元素之间插入固定间距。
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import { View } from 'react-native';
|
|
9
|
+
import { verticalStyle, horizontalStyle } from './style';
|
|
10
|
+
|
|
11
|
+
export interface SpaceProps {
|
|
12
|
+
/** 间距大小,默认 12 */
|
|
13
|
+
size?: number;
|
|
14
|
+
/** 方向,默认 'vertical' */
|
|
15
|
+
direction?: 'horizontal' | 'vertical';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const Space: React.FC<SpaceProps> = ({ size = 12, direction = 'vertical' }) => (
|
|
19
|
+
<View
|
|
20
|
+
style={
|
|
21
|
+
direction === 'vertical'
|
|
22
|
+
? verticalStyle(size)
|
|
23
|
+
: horizontalStyle(size)
|
|
24
|
+
}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
export default Space;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Text 语义化文字
|
|
2
|
+
|
|
3
|
+
通过 `variant` 驱动排版样式。继承 RN `Text`,支持嵌套。
|
|
4
|
+
|
|
5
|
+
## 何时使用
|
|
6
|
+
|
|
7
|
+
- 替代直接写 `fontSize` + `fontWeight` + `color` 的 `<Text>` 组合
|
|
8
|
+
- 需要统一排版规范时
|
|
9
|
+
|
|
10
|
+
## 代码演示
|
|
11
|
+
|
|
12
|
+
```tsx
|
|
13
|
+
// 基础用法
|
|
14
|
+
<Text variant="title">标题文字</Text>
|
|
15
|
+
<Text variant="caption" secondary>辅助说明</Text>
|
|
16
|
+
|
|
17
|
+
// 颜色与字重
|
|
18
|
+
<Text variant="caption" primary weight="bold">¥88.00</Text>
|
|
19
|
+
|
|
20
|
+
// 嵌套 Text
|
|
21
|
+
<Text variant="body" numberOfLines={1}>
|
|
22
|
+
<Text primary weight="semibold">新 </Text>
|
|
23
|
+
{productName}
|
|
24
|
+
</Text>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## API
|
|
28
|
+
|
|
29
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
30
|
+
|------|------|------|--------|
|
|
31
|
+
| variant | 排版变体 | `'title'` \| `'heading'` \| `'body'` \| `'caption'` \| `'micro'` | `'body'` |
|
|
32
|
+
| secondary | 次要色(colorTextSecondary) | `boolean` | `false` |
|
|
33
|
+
| primary | 主题色(colorPrimary) | `boolean` | `false` |
|
|
34
|
+
| color | 自定义颜色 | `string` | - |
|
|
35
|
+
| weight | 字重 | `'medium'` \| `'semibold'` \| `'bold'` | - |
|
|
36
|
+
|
|
37
|
+
> 继承所有 RN `TextProps`(`numberOfLines`、`ellipsizeMode`、`onPress`、`style` 等)
|
|
38
|
+
|
|
39
|
+
## Variant 规格
|
|
40
|
+
|
|
41
|
+
| variant | fontSize | lineHeight | fontWeight | 场景 |
|
|
42
|
+
|---------|----------|------------|------------|------|
|
|
43
|
+
| title | 20 | 26 | 600 | 页面标题、问候语 |
|
|
44
|
+
| heading | 16 | 22 | 600 | 弹窗标题、区块标题 |
|
|
45
|
+
| body | 15 | 22 | 正常 | 默认正文 |
|
|
46
|
+
| caption | 13 | 18 | 正常 | 信息行、标签 |
|
|
47
|
+
| micro | 12 | 18 | 正常 | 地址、规格、描述 |
|
|
48
|
+
|
|
49
|
+
## Weight 映射
|
|
50
|
+
|
|
51
|
+
| weight | fontWeight | 场景 |
|
|
52
|
+
|--------|----------|------|
|
|
53
|
+
| medium | 500 | 产品名、模型名 |
|
|
54
|
+
| semibold | 600 | 标题、按钮文字、客户名 |
|
|
55
|
+
| bold | 700 | 价格金额 |
|
|
56
|
+
|
|
57
|
+
## 样式优先级
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
VARIANT_MAP → secondary/primary → color → weight → style
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
后传入的属性覆盖先传入的,`style` prop 拥有最高优先级。
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 语义化文字组件
|
|
3
|
+
*
|
|
4
|
+
* variant 驱动样式,支持嵌套 Text。
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import { Text as RNText } from 'react-native';
|
|
9
|
+
import type { TextProps as RNTextProps } from 'react-native';
|
|
10
|
+
import type { FontWeight } from './style';
|
|
11
|
+
import { VARIANT_MAP, WEIGHT_MAP, secondaryStyle, primaryStyle } from './style';
|
|
12
|
+
|
|
13
|
+
export interface TextProps extends RNTextProps {
|
|
14
|
+
variant?: 'title' | 'heading' | 'body' | 'caption' | 'micro';
|
|
15
|
+
secondary?: boolean;
|
|
16
|
+
primary?: boolean;
|
|
17
|
+
color?: string;
|
|
18
|
+
weight?: FontWeight;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const Text: React.FC<TextProps> = ({
|
|
22
|
+
variant = 'body',
|
|
23
|
+
secondary,
|
|
24
|
+
primary,
|
|
25
|
+
color,
|
|
26
|
+
weight,
|
|
27
|
+
style,
|
|
28
|
+
...rest
|
|
29
|
+
}: TextProps) => {
|
|
30
|
+
return (
|
|
31
|
+
<RNText
|
|
32
|
+
style={[
|
|
33
|
+
VARIANT_MAP[variant],
|
|
34
|
+
secondary && secondaryStyle,
|
|
35
|
+
primary && primaryStyle,
|
|
36
|
+
color != null && { color },
|
|
37
|
+
weight != null && WEIGHT_MAP[weight],
|
|
38
|
+
style,
|
|
39
|
+
]}
|
|
40
|
+
{...rest}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export default Text;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import type { TextStyle } from 'react-native';
|
|
3
|
+
import { tokens } from '../../theme/tokens';
|
|
4
|
+
|
|
5
|
+
export type FontWeight = 'medium' | 'semibold' | 'bold';
|
|
6
|
+
|
|
7
|
+
export const VARIANT_MAP = StyleSheet.create({
|
|
8
|
+
title: {
|
|
9
|
+
fontSize: 20,
|
|
10
|
+
lineHeight: 26,
|
|
11
|
+
fontWeight: '600',
|
|
12
|
+
color: tokens.colorText,
|
|
13
|
+
},
|
|
14
|
+
heading: {
|
|
15
|
+
fontSize: 16,
|
|
16
|
+
lineHeight: 22,
|
|
17
|
+
fontWeight: '600',
|
|
18
|
+
color: tokens.colorText,
|
|
19
|
+
},
|
|
20
|
+
body: { fontSize: 15, lineHeight: 22, color: tokens.colorText },
|
|
21
|
+
caption: { fontSize: 13, lineHeight: 18, color: tokens.colorText },
|
|
22
|
+
micro: { fontSize: 12, lineHeight: 18, color: tokens.colorText },
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export const WEIGHT_MAP: Record<FontWeight, TextStyle> = {
|
|
26
|
+
medium: { fontWeight: '500' },
|
|
27
|
+
semibold: { fontWeight: '600' },
|
|
28
|
+
bold: { fontWeight: '700' },
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const secondaryStyle: TextStyle = { color: tokens.colorTextSecondary };
|
|
32
|
+
export const primaryStyle: TextStyle = { color: tokens.colorPrimary };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 主题配置
|
|
3
|
+
*
|
|
4
|
+
* 消费方通过 configure() 注入主题色,实现包与业务解耦。
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface ThemeConfig {
|
|
8
|
+
primaryColor?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let _config: ThemeConfig = {};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 配置主题
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* import { configure } from '@unif/react-native-ui';
|
|
18
|
+
* configure({ primaryColor: getAppThemeColor() });
|
|
19
|
+
*/
|
|
20
|
+
export function configure(options: ThemeConfig): void {
|
|
21
|
+
_config = { ..._config, ...options };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function getPrimaryColor(): string {
|
|
25
|
+
return _config.primaryColor || '#EB6E00';
|
|
26
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Design Tokens
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { getPrimaryColor } from './config';
|
|
6
|
+
|
|
7
|
+
export const tokens = {
|
|
8
|
+
get colorPrimary() {
|
|
9
|
+
return getPrimaryColor();
|
|
10
|
+
},
|
|
11
|
+
colorSuccess: '#34C759',
|
|
12
|
+
colorWarning: '#FF9500',
|
|
13
|
+
colorError: '#FF3B30',
|
|
14
|
+
|
|
15
|
+
colorBgPage: '#F7F7F8',
|
|
16
|
+
colorBgElevated: '#FFFFFF',
|
|
17
|
+
colorBgUserMsg: '#F0F0F0',
|
|
18
|
+
|
|
19
|
+
colorText: '#1D1D1F',
|
|
20
|
+
colorTextSecondary: '#8E8E93',
|
|
21
|
+
colorTextPlaceholder: '#C7C7CC',
|
|
22
|
+
colorBorder: '#E5E5EA',
|
|
23
|
+
colorLink: '#007AFF',
|
|
24
|
+
|
|
25
|
+
colorBgHeader: '#FFFFFF',
|
|
26
|
+
colorHeaderText: '#1D1D1F',
|
|
27
|
+
colorHeaderIcon: '#8E8E93',
|
|
28
|
+
|
|
29
|
+
fontSizeXs: 11,
|
|
30
|
+
fontSizeSm: 13,
|
|
31
|
+
fontSize: 15,
|
|
32
|
+
fontSizeMd: 16,
|
|
33
|
+
fontSizeLg: 17,
|
|
34
|
+
fontSizeXl: 20,
|
|
35
|
+
lineHeight: 22,
|
|
36
|
+
lineHeightLg: 26,
|
|
37
|
+
|
|
38
|
+
spaceXs: 4,
|
|
39
|
+
spaceSm: 8,
|
|
40
|
+
space: 12,
|
|
41
|
+
spaceMd: 16,
|
|
42
|
+
spaceLg: 20,
|
|
43
|
+
spaceXl: 24,
|
|
44
|
+
spaceXxl: 32,
|
|
45
|
+
|
|
46
|
+
radiusSm: 6,
|
|
47
|
+
radius: 10,
|
|
48
|
+
radiusLg: 16,
|
|
49
|
+
radiusXl: 20,
|
|
50
|
+
radiusFull: 999,
|
|
51
|
+
|
|
52
|
+
shadowSm: {
|
|
53
|
+
shadowColor: '#000',
|
|
54
|
+
shadowOffset: { width: 0, height: 1 },
|
|
55
|
+
shadowOpacity: 0.04,
|
|
56
|
+
shadowRadius: 2,
|
|
57
|
+
elevation: 1,
|
|
58
|
+
},
|
|
59
|
+
shadow: {
|
|
60
|
+
shadowColor: '#000',
|
|
61
|
+
shadowOffset: { width: 0, height: 2 },
|
|
62
|
+
shadowOpacity: 0.06,
|
|
63
|
+
shadowRadius: 4,
|
|
64
|
+
elevation: 2,
|
|
65
|
+
},
|
|
66
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Touchable 统一触摸反馈
|
|
2
|
+
|
|
3
|
+
基于 `Pressable`,统一替代 `TouchableOpacity`。按下时降低透明度,支持自定义 `activeOpacity`。
|
|
4
|
+
|
|
5
|
+
## 何时使用
|
|
6
|
+
|
|
7
|
+
- 替代所有 `TouchableOpacity` 的场景
|
|
8
|
+
- 需要可点击区域(非按钮语义)时
|
|
9
|
+
|
|
10
|
+
## 代码演示
|
|
11
|
+
|
|
12
|
+
```tsx
|
|
13
|
+
// 基础用法
|
|
14
|
+
<Touchable onPress={handlePress}>
|
|
15
|
+
<Row gap={10}>
|
|
16
|
+
<Icon name="settings" />
|
|
17
|
+
<Text>设置</Text>
|
|
18
|
+
</Row>
|
|
19
|
+
</Touchable>
|
|
20
|
+
|
|
21
|
+
// 自定义按下透明度
|
|
22
|
+
<Touchable onPress={handlePress} activeOpacity={0.5}>
|
|
23
|
+
<Text>更明显的按下效果</Text>
|
|
24
|
+
</Touchable>
|
|
25
|
+
|
|
26
|
+
// 长按
|
|
27
|
+
<Touchable onPress={handlePress} onLongPress={handleLongPress}>
|
|
28
|
+
<Text>支持长按</Text>
|
|
29
|
+
</Touchable>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## API
|
|
33
|
+
|
|
34
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
35
|
+
|------|------|------|--------|
|
|
36
|
+
| onPress | 点击回调 | `() => void` | - |
|
|
37
|
+
| onLongPress | 长按回调 | `() => void` | - |
|
|
38
|
+
| disabled | 禁用状态 | `boolean` | `false` |
|
|
39
|
+
| activeOpacity | 按下态透明度 | `number` | `0.7` |
|
|
40
|
+
| testID | 测试标识 | `string` | - |
|
|
41
|
+
|
|
42
|
+
> 继承所有 RN `ViewProps`
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 统一触摸反馈组件
|
|
3
|
+
*
|
|
4
|
+
* 基于 Pressable,替代 TouchableOpacity。
|
|
5
|
+
* 按下时透明度降低,支持 activeOpacity 自定义。
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React from 'react';
|
|
9
|
+
import { Pressable } from 'react-native';
|
|
10
|
+
import type { ViewProps, ViewStyle } from 'react-native';
|
|
11
|
+
import { disabledStyle } from './style';
|
|
12
|
+
|
|
13
|
+
export interface TouchableProps extends ViewProps {
|
|
14
|
+
onPress?: () => void;
|
|
15
|
+
onLongPress?: () => void;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
/** 按下态透明度,默认 0.7 */
|
|
18
|
+
activeOpacity?: number;
|
|
19
|
+
testID?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const Touchable: React.FC<TouchableProps> = ({
|
|
23
|
+
onPress,
|
|
24
|
+
onLongPress,
|
|
25
|
+
disabled,
|
|
26
|
+
activeOpacity = 0.7,
|
|
27
|
+
style,
|
|
28
|
+
testID,
|
|
29
|
+
...rest
|
|
30
|
+
}: TouchableProps) => (
|
|
31
|
+
<Pressable
|
|
32
|
+
onPress={onPress}
|
|
33
|
+
onLongPress={onLongPress}
|
|
34
|
+
disabled={disabled}
|
|
35
|
+
testID={testID}
|
|
36
|
+
style={({ pressed }) => [
|
|
37
|
+
style as ViewStyle,
|
|
38
|
+
pressed && { opacity: activeOpacity },
|
|
39
|
+
disabled && disabledStyle,
|
|
40
|
+
]}
|
|
41
|
+
{...rest}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
export default Touchable;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: WaveAnimation
|
|
3
|
+
nav:
|
|
4
|
+
title: 组件
|
|
5
|
+
order: 1
|
|
6
|
+
group:
|
|
7
|
+
title: 原子
|
|
8
|
+
order: 1
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# WaveAnimation 声波动画
|
|
12
|
+
|
|
13
|
+
柱状声波动画,适用于语音录制等场景的视觉反馈。
|
|
14
|
+
|
|
15
|
+
## 何时使用
|
|
16
|
+
|
|
17
|
+
- 语音录制时展示声波效果
|
|
18
|
+
- 需要节奏性动画反馈时
|
|
19
|
+
|
|
20
|
+
## 代码演示
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import { WaveAnimation } from '@unif/react-native-ui';
|
|
24
|
+
|
|
25
|
+
// 基本用法
|
|
26
|
+
<WaveAnimation active={isRecording} />
|
|
27
|
+
|
|
28
|
+
// 自定义参数
|
|
29
|
+
<WaveAnimation
|
|
30
|
+
active={true}
|
|
31
|
+
color="#EB6E00"
|
|
32
|
+
barCount={5}
|
|
33
|
+
barWidth={4}
|
|
34
|
+
minHeight={4}
|
|
35
|
+
maxHeight={24}
|
|
36
|
+
/>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## API
|
|
40
|
+
|
|
41
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
42
|
+
| --------- | ------------ | ---------- | ----------- |
|
|
43
|
+
| active | 控制动画启停 | `boolean` | - |
|
|
44
|
+
| color | 柱体颜色 | `string` | `'#FFFFFF'` |
|
|
45
|
+
| barCount | 柱数 | `number` | `4` |
|
|
46
|
+
| barWidth | 柱宽 | `number` | `3` |
|
|
47
|
+
| minHeight | 最小高度 | `number` | `6` |
|
|
48
|
+
| maxHeight | 最大高度 | `number` | `20` |
|
|
49
|
+
| style | 容器样式 | `ViewStyle`| - |
|
|
50
|
+
| testID | 测试标识 | `string` | - |
|