@beppla/tapas-ui 1.5.2 → 1.5.7
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/commonjs/Alert/README.md +75 -0
- package/commonjs/BarChart/README.md +172 -0
- package/commonjs/Button/README.md +108 -0
- package/commonjs/Calendar/Calendar.base.js +1 -1
- package/commonjs/Calendar/Calendar.base.js.map +1 -1
- package/commonjs/Calendar/README.md +410 -0
- package/commonjs/Card/README.md +126 -0
- package/commonjs/CheckBox/README.md +147 -0
- package/commonjs/CircularProgress/README.md +70 -0
- package/commonjs/Collapsible/README.md +140 -0
- package/commonjs/ComboChart/README.md +124 -0
- package/commonjs/DashboardCard/README.md +120 -0
- package/commonjs/DataTable/README.md +159 -0
- package/commonjs/DeviceSelectionModal/README.md +124 -0
- package/commonjs/DraggableFlatList/README.md +35 -0
- package/commonjs/Drawer/README.md +175 -0
- package/commonjs/Dropdown/Dropdown.js +60 -30
- package/commonjs/Dropdown/Dropdown.js.map +1 -1
- package/commonjs/Dropdown/README.md +230 -0
- package/commonjs/ExternalLink/README.md +81 -0
- package/commonjs/Gantt/README.md +155 -0
- package/commonjs/Grid/README.md +197 -0
- package/commonjs/Header/README.md +109 -0
- package/commonjs/HelloWave/README.md +28 -0
- package/commonjs/Hoverable/Hoverable.js.map +1 -1
- package/commonjs/IconText/README.md +99 -0
- package/commonjs/Image/PreviewImg/README.md +100 -0
- package/commonjs/Image/README.md +88 -0
- package/commonjs/Input/Input.js +60 -4
- package/commonjs/Input/Input.js.map +1 -1
- package/commonjs/Layout/README.md +174 -0
- package/commonjs/LineChart/README.md +181 -0
- package/commonjs/ListItem/README.md +122 -0
- package/commonjs/MessageBox/MessageBox.js +7 -1
- package/commonjs/MessageBox/MessageBox.js.map +1 -1
- package/commonjs/MessageBox/README.md +120 -0
- package/commonjs/Navigation/README.md +197 -0
- package/commonjs/NumericInput/README.md +95 -0
- package/commonjs/Overlay/README.md +84 -0
- package/commonjs/Pagination/README.md +106 -0
- package/commonjs/PieChart/README.md +212 -0
- package/commonjs/Popover/README.md +82 -0
- package/commonjs/Progress/README.md +106 -0
- package/commonjs/RadioButton/README.md +85 -0
- package/commonjs/ScanButton/README.md +72 -0
- package/commonjs/SearchInput/SearchInput.js.map +1 -1
- package/commonjs/SheetTitle/README.md +89 -0
- package/commonjs/Shell/README.md +152 -0
- package/commonjs/Shell/Shell.js.map +1 -1
- package/commonjs/StatisticCard/README.md +129 -0
- package/commonjs/Status/README.md +75 -0
- package/commonjs/Steps/README.md +76 -0
- package/commonjs/Switch/Switch.js +101 -0
- package/commonjs/Switch/Switch.js.map +1 -0
- package/commonjs/Tab/README.md +161 -0
- package/commonjs/Tag/README.md +93 -0
- package/commonjs/Task/README.md +110 -0
- package/commonjs/Text/README.md +97 -0
- package/commonjs/TextArea/README.md +127 -0
- package/commonjs/TextArea/TextArea.js +4 -2
- package/commonjs/TextArea/TextArea.js.map +1 -1
- package/commonjs/Theme/README.md +161 -0
- package/commonjs/Theme/makeStyles.js +30 -0
- package/commonjs/Theme/makeStyles.js.map +1 -0
- package/commonjs/Theme/withTheme.js +91 -0
- package/commonjs/Theme/withTheme.js.map +1 -0
- package/commonjs/Timeline/README.md +111 -0
- package/commonjs/Toast/README.md +96 -0
- package/commonjs/Upload/Upload.js +126 -0
- package/commonjs/Upload/Upload.js.map +1 -0
- package/commonjs/index.js +24 -4
- package/commonjs/index.js.map +1 -1
- package/module/Alert/README.md +75 -0
- package/module/BarChart/README.md +172 -0
- package/module/Button/README.md +108 -0
- package/module/Calendar/Calendar.base.js +1 -1
- package/module/Calendar/Calendar.base.js.map +1 -1
- package/module/Calendar/README.md +410 -0
- package/module/Card/README.md +126 -0
- package/module/CheckBox/README.md +147 -0
- package/module/CircularProgress/README.md +70 -0
- package/module/Collapsible/README.md +140 -0
- package/module/ComboChart/README.md +124 -0
- package/module/DashboardCard/README.md +120 -0
- package/module/DataTable/README.md +159 -0
- package/module/DeviceSelectionModal/README.md +124 -0
- package/module/DraggableFlatList/README.md +35 -0
- package/module/Drawer/README.md +175 -0
- package/module/Dropdown/Dropdown.js +60 -30
- package/module/Dropdown/Dropdown.js.map +1 -1
- package/module/Dropdown/README.md +230 -0
- package/module/ExternalLink/README.md +81 -0
- package/module/Gantt/README.md +155 -0
- package/module/Grid/README.md +197 -0
- package/module/Header/README.md +109 -0
- package/module/HelloWave/README.md +28 -0
- package/module/Hoverable/Hoverable.js.map +1 -1
- package/module/IconText/README.md +99 -0
- package/module/Image/PreviewImg/README.md +100 -0
- package/module/Image/README.md +88 -0
- package/module/Input/Input.js +60 -4
- package/module/Input/Input.js.map +1 -1
- package/module/Layout/README.md +174 -0
- package/module/LineChart/README.md +181 -0
- package/module/ListItem/README.md +122 -0
- package/module/MessageBox/MessageBox.js +8 -2
- package/module/MessageBox/MessageBox.js.map +1 -1
- package/module/MessageBox/README.md +120 -0
- package/module/Navigation/README.md +197 -0
- package/module/NumericInput/README.md +95 -0
- package/module/Overlay/README.md +84 -0
- package/module/Pagination/README.md +106 -0
- package/module/PieChart/README.md +212 -0
- package/module/Popover/README.md +82 -0
- package/module/Progress/README.md +106 -0
- package/module/RadioButton/README.md +85 -0
- package/module/ScanButton/README.md +72 -0
- package/module/SearchInput/SearchInput.js.map +1 -1
- package/module/SheetTitle/README.md +89 -0
- package/module/Shell/README.md +152 -0
- package/module/Shell/Shell.js.map +1 -1
- package/module/StatisticCard/README.md +129 -0
- package/module/Status/README.md +75 -0
- package/module/Steps/README.md +76 -0
- package/module/Switch/Switch.js +96 -0
- package/module/Switch/Switch.js.map +1 -0
- package/module/Tab/README.md +161 -0
- package/module/Tag/README.md +93 -0
- package/module/Task/README.md +110 -0
- package/module/Text/README.md +97 -0
- package/module/TextArea/README.md +127 -0
- package/module/TextArea/TextArea.js +4 -2
- package/module/TextArea/TextArea.js.map +1 -1
- package/module/Theme/README.md +161 -0
- package/module/Theme/makeStyles.js +24 -0
- package/module/Theme/makeStyles.js.map +1 -0
- package/module/Theme/withTheme.js +82 -0
- package/module/Theme/withTheme.js.map +1 -0
- package/module/Timeline/README.md +111 -0
- package/module/Toast/README.md +96 -0
- package/module/Upload/Upload.js +121 -0
- package/module/Upload/Upload.js.map +1 -0
- package/module/index.js +11 -3
- package/module/index.js.map +1 -1
- package/package.json +1 -1
- package/typescript/Dropdown/Dropdown.d.ts +20 -0
- package/typescript/Dropdown/Dropdown.d.ts.map +1 -1
- package/typescript/Grid/FixedSizeGrid.d.ts +1 -3
- package/typescript/Grid/FixedSizeGrid.d.ts.map +1 -1
- package/typescript/Grid/Grid.base.d.ts +1 -3
- package/typescript/Grid/Grid.base.d.ts.map +1 -1
- package/typescript/Grid/VariableSizeGrid.d.ts +1 -3
- package/typescript/Grid/VariableSizeGrid.d.ts.map +1 -1
- package/typescript/Input/Input.d.ts +5 -0
- package/typescript/Input/Input.d.ts.map +1 -1
- package/typescript/MessageBox/MessageBox.d.ts.map +1 -1
- package/typescript/SearchInput/SearchInput.d.ts +4 -0
- package/typescript/SearchInput/SearchInput.d.ts.map +1 -1
- package/typescript/Switch/Switch.d.ts +15 -0
- package/typescript/Switch/Switch.d.ts.map +1 -0
- package/typescript/TextArea/TextArea.d.ts +2 -0
- package/typescript/TextArea/TextArea.d.ts.map +1 -1
- package/typescript/Theme/makeStyles.d.ts +11 -0
- package/typescript/Theme/makeStyles.d.ts.map +1 -0
- package/typescript/Theme/withTheme.d.ts +12 -0
- package/typescript/Theme/withTheme.d.ts.map +1 -0
- package/typescript/Upload/Upload.d.ts +25 -0
- package/typescript/Upload/Upload.d.ts.map +1 -0
- package/typescript/WebViewBridge/useWebViewBridge.d.ts +1 -1
- package/typescript/WebViewBridge/useWebViewBridge.d.ts.map +1 -1
- package/typescript/common/hooks/useBridgelessFix.d.ts +1 -1
- package/typescript/index.d.ts +8 -2
- package/typescript/index.d.ts.map +1 -1
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# DeviceSelectionModal
|
|
2
|
+
|
|
3
|
+
设备选择模态对话框组件,用于从设备列表中选择一个设备。支持加载状态、错误处理、重试机制和文本国际化,适合打印机选择、终端绑定等硬件设备关联场景。
|
|
4
|
+
|
|
5
|
+
## 功能特性
|
|
6
|
+
|
|
7
|
+
- ✅ 单选设备列表(Radio Button 样式)
|
|
8
|
+
- ✅ 加载中状态展示(ActivityIndicator)
|
|
9
|
+
- ✅ 错误状态展示 + 重试按钮
|
|
10
|
+
- ✅ 空列表提示
|
|
11
|
+
- ✅ 设备描述信息展示
|
|
12
|
+
- ✅ 未选择时确认按钮自动禁用
|
|
13
|
+
- ✅ 关闭时恢复原始选中状态
|
|
14
|
+
- ✅ 全部文本支持国际化(i18n props)
|
|
15
|
+
- ✅ 淡入淡出动画
|
|
16
|
+
- ✅ 主题色适配
|
|
17
|
+
|
|
18
|
+
## 安装使用
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { DeviceSelectionModal } from '@beppla/tapas-ui';
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Props
|
|
25
|
+
|
|
26
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
27
|
+
|------|------|--------|------|
|
|
28
|
+
| visible | `boolean` | - | 是否显示(必填) |
|
|
29
|
+
| devices | `Device[]` | - | 设备列表(必填) |
|
|
30
|
+
| selectedDeviceId | `string` | - | 当前选中的设备 ID |
|
|
31
|
+
| onClose | `() => void` | - | 关闭回调(必填) |
|
|
32
|
+
| onConfirm | `(deviceId: string) => void` | - | 确认选择回调(必填) |
|
|
33
|
+
| title | `string` | - | 对话框标题 |
|
|
34
|
+
| isLoading | `boolean` | `false` | 是否加载中 |
|
|
35
|
+
| error | `string \| null` | `null` | 错误信息 |
|
|
36
|
+
| onRetry | `() => void` | - | 重试按钮回调 |
|
|
37
|
+
| selectDeviceText | `string` | `'Select Device'` | 标题文本 |
|
|
38
|
+
| pleaseSelectDeviceText | `string` | `'Please select a device'` | 副标题文本 |
|
|
39
|
+
| loadingDevicesText | `string` | `'Loading devices...'` | 加载中文本 |
|
|
40
|
+
| noDevicesAvailableText | `string` | `'No devices available'` | 空列表文本 |
|
|
41
|
+
| closeText | `string` | `'Close'` | 关闭按钮文本 |
|
|
42
|
+
| confirmText | `string` | `'Confirm'` | 确认按钮文本 |
|
|
43
|
+
| retryText | `string` | `'Retry'` | 重试按钮文本 |
|
|
44
|
+
| testID | `string` | - | 测试标识 |
|
|
45
|
+
|
|
46
|
+
### Device 接口
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
interface Device {
|
|
50
|
+
id: string;
|
|
51
|
+
name: string;
|
|
52
|
+
description?: string;
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 使用示例
|
|
57
|
+
|
|
58
|
+
### 基础用法
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
const [visible, setVisible] = useState(false);
|
|
62
|
+
const devices = [
|
|
63
|
+
{ id: '1', name: 'Printer A', description: 'Kitchen printer' },
|
|
64
|
+
{ id: '2', name: 'Printer B', description: 'Receipt printer' },
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
<DeviceSelectionModal
|
|
68
|
+
visible={visible}
|
|
69
|
+
devices={devices}
|
|
70
|
+
onClose={() => setVisible(false)}
|
|
71
|
+
onConfirm={(deviceId) => {
|
|
72
|
+
console.log('Selected:', deviceId);
|
|
73
|
+
setVisible(false);
|
|
74
|
+
}}
|
|
75
|
+
/>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 加载状态
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
<DeviceSelectionModal
|
|
82
|
+
visible={true}
|
|
83
|
+
devices={[]}
|
|
84
|
+
isLoading={true}
|
|
85
|
+
onClose={() => setVisible(false)}
|
|
86
|
+
onConfirm={() => {}}
|
|
87
|
+
/>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 错误状态 + 重试
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
<DeviceSelectionModal
|
|
94
|
+
visible={true}
|
|
95
|
+
devices={[]}
|
|
96
|
+
error="Failed to load devices"
|
|
97
|
+
onRetry={() => fetchDevices()}
|
|
98
|
+
onClose={() => setVisible(false)}
|
|
99
|
+
onConfirm={() => {}}
|
|
100
|
+
/>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 国际化
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
<DeviceSelectionModal
|
|
107
|
+
visible={true}
|
|
108
|
+
devices={devices}
|
|
109
|
+
selectDeviceText="Select Printer"
|
|
110
|
+
pleaseSelectDeviceText="Choose a printer for this station"
|
|
111
|
+
confirmText="Bind"
|
|
112
|
+
closeText="Cancel"
|
|
113
|
+
onClose={() => setVisible(false)}
|
|
114
|
+
onConfirm={handleConfirm}
|
|
115
|
+
/>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## 注意事项
|
|
119
|
+
|
|
120
|
+
- 关闭对话框时会将内部选中状态恢复为 `selectedDeviceId`(即取消未确认的选择)
|
|
121
|
+
- 未选中设备时确认按钮禁用(灰色样式)
|
|
122
|
+
- 对话框最大宽度 400px,设备列表最大高度 300px
|
|
123
|
+
- `title` 和 `selectDeviceText` 同时存在时,`title` 优先
|
|
124
|
+
- 需在 `ThemeProvider` 内使用
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# DraggableFlatList
|
|
2
|
+
|
|
3
|
+
可拖拽列表组件占位符。当前为空实现,预留用于后续开发支持拖拽排序的列表功能。
|
|
4
|
+
|
|
5
|
+
## 功能特性
|
|
6
|
+
|
|
7
|
+
- ✅ 组件骨架已搭建,导出可用
|
|
8
|
+
- (待开发) 拖拽排序
|
|
9
|
+
- (待开发) 拖拽动画
|
|
10
|
+
- (待开发) 自定义渲染
|
|
11
|
+
|
|
12
|
+
## 安装使用
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import { DraggableFlatList } from '@beppla/tapas-ui';
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Props
|
|
19
|
+
|
|
20
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
21
|
+
|------|------|--------|------|
|
|
22
|
+
| testID | `string` | - | 测试标识 |
|
|
23
|
+
|
|
24
|
+
## 使用示例
|
|
25
|
+
|
|
26
|
+
### 基础用法
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
<DraggableFlatList testID="draggable-list" />
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 注意事项
|
|
33
|
+
|
|
34
|
+
- 当前为空 View 占位实现,无实际拖拽功能
|
|
35
|
+
- 后续计划集成 `react-native-draggable-flatlist` 或自定义实现
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# Drawer
|
|
2
|
+
|
|
3
|
+
抽屉面板组件,从屏幕右侧滑出的浮层面板,支持自定义头部、内容区域和页脚,常用于筛选、详情展示等场景。
|
|
4
|
+
|
|
5
|
+
## 功能特性
|
|
6
|
+
|
|
7
|
+
- 从右侧滑出的 Overlay 抽屉面板
|
|
8
|
+
- 响应式宽度(桌面端 55%,移动端 100%)
|
|
9
|
+
- 可自定义标题、标题图标和状态标签(Status 组件)
|
|
10
|
+
- 支持 showHeader / showFooter 控制头部和页脚显示
|
|
11
|
+
- 支持自定义 headerComponent 和 footerComponent 完全替换
|
|
12
|
+
- 点击背景遮罩自动关闭(onBackdropPress)
|
|
13
|
+
- 内容区域自动 ScrollView 滚动
|
|
14
|
+
- 移动端自动适配 Safe Area(useSafeAreaInsets)
|
|
15
|
+
- 页脚包含左侧文本按钮和右侧主按钮
|
|
16
|
+
|
|
17
|
+
## 安装使用
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import { Drawer } from '@beppla/tapas-ui';
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Props
|
|
24
|
+
|
|
25
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
26
|
+
|------|------|--------|------|
|
|
27
|
+
| visible | `boolean` | `false` | 抽屉是否可见 |
|
|
28
|
+
| title | `string` | - | 抽屉标题 |
|
|
29
|
+
| titleIcon | `string` | - | 标题左侧图标名称 |
|
|
30
|
+
| titleIconOnPress | `() => void` | - | 标题图标点击回调 |
|
|
31
|
+
| titleStatus | `string` | - | 状态标签文本 |
|
|
32
|
+
| statusType | `STATUS_TYPE` | `'unavailable'` | 状态类型(success/warning/unavailable 等) |
|
|
33
|
+
| showHeader | `boolean` | `true` | 是否显示头部 |
|
|
34
|
+
| showFooter | `boolean` | `false` | 是否显示页脚 |
|
|
35
|
+
| onClose | `() => void` | - | 关闭回调(背景遮罩点击时触发) |
|
|
36
|
+
| onClear | `() => void` | - | 清空按钮回调(未设时回退到 onClose) |
|
|
37
|
+
| clearText | `string` | - | 清空按钮文本 |
|
|
38
|
+
| clearDisable | `boolean` | `true` | 清空按钮是否禁用 |
|
|
39
|
+
| overlayStyle | `StyleProp<ViewStyle>` | - | 抽屉覆盖层自定义样式 |
|
|
40
|
+
| middleSectionStyle | `StyleProp<ViewStyle>` | - | 内容区域自定义样式 |
|
|
41
|
+
| leftButtonText | `string` | - | 页脚左侧按钮文本 |
|
|
42
|
+
| leftButtonTextStyle | `StyleProp<ViewStyle>` | - | 页脚左侧按钮文本样式 |
|
|
43
|
+
| leftButtonOnPress | `() => void` | - | 页脚左侧按钮回调 |
|
|
44
|
+
| rightButtonText | `string` | - | 页脚右侧按钮文本 |
|
|
45
|
+
| rightButtonStyle | `StyleProp<ViewStyle>` | - | 页脚右侧按钮样式 |
|
|
46
|
+
| rightButtonOnPress | `() => void` | - | 页脚右侧按钮回调 |
|
|
47
|
+
| component | `React.ReactNode` | - | 内容组件(渲染在 children 之前) |
|
|
48
|
+
| children | `React.ReactNode` | - | 内容子组件 |
|
|
49
|
+
| headerComponent | `React.ReactNode` | - | 自定义头部组件(替换默认头部) |
|
|
50
|
+
| footerComponent | `React.ReactNode` | - | 自定义页脚组件(额外渲染在 showFooter 之后) |
|
|
51
|
+
| testID | `string` | - | 测试 ID |
|
|
52
|
+
|
|
53
|
+
## 使用示例
|
|
54
|
+
|
|
55
|
+
### 基础用法
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
import { Drawer } from '@beppla/tapas-ui';
|
|
59
|
+
import { useState } from 'react';
|
|
60
|
+
import { Text, Button } from 'react-native';
|
|
61
|
+
|
|
62
|
+
export default function App() {
|
|
63
|
+
const [visible, setVisible] = useState(false);
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<>
|
|
67
|
+
<Button title="Open Drawer" onPress={() => setVisible(true)} />
|
|
68
|
+
<Drawer
|
|
69
|
+
visible={visible}
|
|
70
|
+
title="Filters"
|
|
71
|
+
onClose={() => setVisible(false)}
|
|
72
|
+
>
|
|
73
|
+
<Text>Drawer content here</Text>
|
|
74
|
+
</Drawer>
|
|
75
|
+
</>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 带状态标签和图标
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
<Drawer
|
|
84
|
+
visible={visible}
|
|
85
|
+
title="Order Details"
|
|
86
|
+
titleIcon="back"
|
|
87
|
+
titleIconOnPress={() => setVisible(false)}
|
|
88
|
+
titleStatus="Active"
|
|
89
|
+
statusType="success"
|
|
90
|
+
onClose={() => setVisible(false)}
|
|
91
|
+
>
|
|
92
|
+
<Text>Order information</Text>
|
|
93
|
+
</Drawer>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 完整功能(头部 + 内容 + 页脚)
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
<Drawer
|
|
100
|
+
visible={visible}
|
|
101
|
+
title="Filters"
|
|
102
|
+
titleIcon="back"
|
|
103
|
+
titleIconOnPress={() => setVisible(false)}
|
|
104
|
+
clearText="Clear"
|
|
105
|
+
clearDisable={false}
|
|
106
|
+
onClear={() => resetFilters()}
|
|
107
|
+
onClose={() => setVisible(false)}
|
|
108
|
+
showFooter={true}
|
|
109
|
+
leftButtonText="Close"
|
|
110
|
+
leftButtonOnPress={() => setVisible(false)}
|
|
111
|
+
rightButtonText="Show all results"
|
|
112
|
+
rightButtonOnPress={() => applyFilters()}
|
|
113
|
+
>
|
|
114
|
+
<Text>Filter options here</Text>
|
|
115
|
+
</Drawer>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 自定义头部和页脚
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
<Drawer
|
|
122
|
+
visible={visible}
|
|
123
|
+
headerComponent={
|
|
124
|
+
<View style={{ flexDirection: 'row', justifyContent: 'space-between', padding: 16 }}>
|
|
125
|
+
<Text style={{ fontSize: 18, fontWeight: 'bold' }}>Custom Header</Text>
|
|
126
|
+
<Button title="X" onPress={() => setVisible(false)} />
|
|
127
|
+
</View>
|
|
128
|
+
}
|
|
129
|
+
footerComponent={
|
|
130
|
+
<View style={{ flexDirection: 'row', justifyContent: 'flex-end', gap: 8 }}>
|
|
131
|
+
<Button title="Cancel" onPress={() => setVisible(false)} />
|
|
132
|
+
<Button title="Save" onPress={() => handleSave()} />
|
|
133
|
+
</View>
|
|
134
|
+
}
|
|
135
|
+
onClose={() => setVisible(false)}
|
|
136
|
+
>
|
|
137
|
+
<Text>Content with custom header and footer</Text>
|
|
138
|
+
</Drawer>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### 通过 DrawerContext 使用
|
|
142
|
+
|
|
143
|
+
```tsx
|
|
144
|
+
import { useContext } from 'react';
|
|
145
|
+
import { DrawerContext } from '@beppla/tapas-ui/components/Layout/DrawerContext';
|
|
146
|
+
|
|
147
|
+
function MyComponent() {
|
|
148
|
+
const { open, close } = useContext(DrawerContext);
|
|
149
|
+
|
|
150
|
+
const showDrawer = () => {
|
|
151
|
+
open({
|
|
152
|
+
title: 'Dynamic Drawer',
|
|
153
|
+
component: <Text>Dynamic content</Text>,
|
|
154
|
+
showFooter: true,
|
|
155
|
+
rightButtonText: 'Confirm',
|
|
156
|
+
rightButtonOnPress: () => {
|
|
157
|
+
handleConfirm();
|
|
158
|
+
close();
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
return <Button title="Open" onPress={showDrawer} />;
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## 注意事项
|
|
168
|
+
|
|
169
|
+
- 桌面端抽屉宽度为屏幕的 55%,移动端为 100%
|
|
170
|
+
- `clearDisable` 默认为 `true`(禁用状态),需显式设为 `false` 才能启用清空按钮
|
|
171
|
+
- `onClear` 未设置时,清空按钮会回退使用 `onClose` 回调
|
|
172
|
+
- `showFooter` 默认为 `false`,需显式设为 `true` 以显示页脚按钮区域
|
|
173
|
+
- `footerComponent` 独立于 `showFooter`,即使 `showFooter=false`,`footerComponent` 仍会渲染
|
|
174
|
+
- 内容区域使用 ScrollView 包裹,`contentContainerStyle` 设置了 `flexGrow: 1`
|
|
175
|
+
- 移动端会通过 `useSafeAreaInsets` 自动添加顶部安全区域间距
|
|
@@ -235,6 +235,7 @@ const Dropdown = ({
|
|
|
235
235
|
dropdownType = "clear",
|
|
236
236
|
arrowIcon: _arrowIcon = false,
|
|
237
237
|
onSelect,
|
|
238
|
+
attachSelect,
|
|
238
239
|
backgroundColor,
|
|
239
240
|
labelColor,
|
|
240
241
|
state = "normal",
|
|
@@ -246,17 +247,34 @@ const Dropdown = ({
|
|
|
246
247
|
extendBtnIcon,
|
|
247
248
|
emptyText,
|
|
248
249
|
onExtendBtnPress,
|
|
250
|
+
attachExtendBtn,
|
|
249
251
|
noLabelAnim = false,
|
|
250
252
|
radius = 12,
|
|
251
253
|
modalVisible,
|
|
252
254
|
customPopoverContent,
|
|
253
255
|
setModalVisible,
|
|
256
|
+
visible,
|
|
257
|
+
setVisible,
|
|
258
|
+
dropdownSubWidth,
|
|
259
|
+
dropdownSubHeight,
|
|
260
|
+
empytText,
|
|
261
|
+
leftIcon,
|
|
262
|
+
marginTopOffset = 0,
|
|
263
|
+
height,
|
|
254
264
|
iconStyle,
|
|
255
265
|
label,
|
|
256
266
|
required,
|
|
257
267
|
testID,
|
|
258
268
|
...props
|
|
259
269
|
}) => {
|
|
270
|
+
// 向下兼容:deprecated props 优先级低于新 props
|
|
271
|
+
const resolvedOnSelect = onSelect ?? attachSelect;
|
|
272
|
+
const resolvedOnExtendBtnPress = onExtendBtnPress ?? attachExtendBtn;
|
|
273
|
+
const resolvedModalVisible = modalVisible ?? visible;
|
|
274
|
+
const resolvedSetModalVisible = setModalVisible ?? setVisible;
|
|
275
|
+
const resolvedSubWidth = subWidth ?? dropdownSubWidth;
|
|
276
|
+
const resolvedSubHeight = subHeight ?? dropdownSubHeight;
|
|
277
|
+
const resolvedEmptyText = emptyText ?? empytText;
|
|
260
278
|
const styles = useStyles(props);
|
|
261
279
|
const theme = (0, _themed.useTheme)();
|
|
262
280
|
const [selected_old, selectedItem] = _react.default.useState(value);
|
|
@@ -269,7 +287,7 @@ const Dropdown = ({
|
|
|
269
287
|
top: 0,
|
|
270
288
|
left: 0
|
|
271
289
|
});
|
|
272
|
-
const [dropdownWidthCalc, setDropdownWidthCalc] = (0, _react.useState)(
|
|
290
|
+
const [dropdownWidthCalc, setDropdownWidthCalc] = (0, _react.useState)(resolvedSubWidth ?? 151);
|
|
273
291
|
const [selectedItemKey, setSelectedItemKey] = (0, _react.useState)(selected ?? "");
|
|
274
292
|
const [top, setTop] = (0, _react.useState)(18);
|
|
275
293
|
const [optionListHeight, setOptionListHeight] = (0, _react.useState)(0);
|
|
@@ -286,17 +304,17 @@ const Dropdown = ({
|
|
|
286
304
|
setSelectedItemKey(selected ?? "");
|
|
287
305
|
}, [selected]);
|
|
288
306
|
(0, _react.useEffect)(() => {
|
|
289
|
-
if (typeof
|
|
290
|
-
setInternalModalVisible(
|
|
307
|
+
if (typeof resolvedModalVisible === "boolean" && resolvedModalVisible !== undefined) {
|
|
308
|
+
setInternalModalVisible(resolvedModalVisible);
|
|
291
309
|
}
|
|
292
|
-
}, [
|
|
310
|
+
}, [resolvedModalVisible]);
|
|
293
311
|
|
|
294
312
|
// 动态更新下拉容器宽度(支持运行时宽度变化)
|
|
295
313
|
(0, _react.useEffect)(() => {
|
|
296
|
-
if (
|
|
297
|
-
setDropdownWidthCalc(
|
|
314
|
+
if (resolvedSubWidth && internalModalVisible) {
|
|
315
|
+
setDropdownWidthCalc(resolvedSubWidth);
|
|
298
316
|
}
|
|
299
|
-
}, [
|
|
317
|
+
}, [resolvedSubWidth, internalModalVisible]);
|
|
300
318
|
|
|
301
319
|
// 标签动画效果
|
|
302
320
|
(0, _react.useEffect)(() => {
|
|
@@ -326,8 +344,8 @@ const Dropdown = ({
|
|
|
326
344
|
if (buttonRef.current) {
|
|
327
345
|
buttonRef.current.measure((_fx, _fy, width, height, px, py) => {
|
|
328
346
|
const window = _reactNative.Dimensions.get("window");
|
|
329
|
-
const dropdownHeight =
|
|
330
|
-
const dropdownWidth = Math.max(width,
|
|
347
|
+
const dropdownHeight = resolvedSubHeight ?? Math.min(40 * dropdownItems.length + 24, 224);
|
|
348
|
+
const dropdownWidth = Math.max(width, resolvedSubWidth ?? 151);
|
|
331
349
|
setDropdownWidthCalc(dropdownWidth);
|
|
332
350
|
|
|
333
351
|
// 计算显示位置
|
|
@@ -341,8 +359,8 @@ const Dropdown = ({
|
|
|
341
359
|
top,
|
|
342
360
|
left
|
|
343
361
|
});
|
|
344
|
-
if (
|
|
345
|
-
|
|
362
|
+
if (resolvedSetModalVisible) {
|
|
363
|
+
resolvedSetModalVisible(true);
|
|
346
364
|
} else {
|
|
347
365
|
setInternalModalVisible(true);
|
|
348
366
|
}
|
|
@@ -350,8 +368,8 @@ const Dropdown = ({
|
|
|
350
368
|
}
|
|
351
369
|
};
|
|
352
370
|
const closeModal = () => {
|
|
353
|
-
if (
|
|
354
|
-
|
|
371
|
+
if (resolvedSetModalVisible) {
|
|
372
|
+
resolvedSetModalVisible(false);
|
|
355
373
|
} else {
|
|
356
374
|
setInternalModalVisible(false);
|
|
357
375
|
}
|
|
@@ -369,8 +387,10 @@ const Dropdown = ({
|
|
|
369
387
|
style: [styles.modalContainer, width ? {
|
|
370
388
|
width: width
|
|
371
389
|
} : null, {
|
|
372
|
-
minHeight: 40 + (label ? 7 : 0) + (showStateMsg ? 15 : 0)
|
|
373
|
-
}
|
|
390
|
+
minHeight: (height || 40) + (label ? 7 : 0) + (showStateMsg ? 15 : 0)
|
|
391
|
+
}, height ? {
|
|
392
|
+
maxHeight: height + (label ? 7 : 0) + (showStateMsg ? 15 : 0)
|
|
393
|
+
} : null],
|
|
374
394
|
children: [label && !noLabelAnim && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Animated.View, {
|
|
375
395
|
style: [styles.labelCon, {
|
|
376
396
|
top: topAnim
|
|
@@ -402,22 +422,32 @@ const Dropdown = ({
|
|
|
402
422
|
borderRadius: radius
|
|
403
423
|
} : null,
|
|
404
424
|
// 统一主体容器的位置,无论是否使用 customPopoverContent
|
|
405
|
-
label
|
|
406
|
-
marginTop: 7
|
|
425
|
+
label ? {
|
|
426
|
+
marginTop: 7 + marginTopOffset
|
|
407
427
|
} : null, noLabelAnim && label && backgroundColor ? {
|
|
408
428
|
backgroundColor
|
|
409
429
|
} : null, state === "error" ? {
|
|
410
430
|
borderColor: theme.theme.colors.error
|
|
411
431
|
} : null, props.disabled ? {
|
|
412
432
|
borderColor: theme.theme.colors.grey3
|
|
413
|
-
} : null,
|
|
433
|
+
} : null, leftIcon && {
|
|
434
|
+
gap: 8,
|
|
435
|
+
paddingLeft: 8,
|
|
436
|
+
paddingRight: 12
|
|
437
|
+
},
|
|
414
438
|
// 确保主体容器始终有统一的垂直对齐
|
|
415
439
|
{
|
|
416
440
|
alignItems: "center"
|
|
417
441
|
}],
|
|
418
442
|
disabled: props.disabled,
|
|
419
443
|
onPress: openDropdown,
|
|
420
|
-
children: [
|
|
444
|
+
children: [leftIcon && /*#__PURE__*/(0, _jsxRuntime.jsx)(_TapasIcon.default, {
|
|
445
|
+
size: 20,
|
|
446
|
+
style: [styles.alignCenter, styles.modalIcon, props.disabled && {
|
|
447
|
+
color: theme.theme.colors.grey3
|
|
448
|
+
}],
|
|
449
|
+
name: leftIcon
|
|
450
|
+
}), showSelectedValue ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
421
451
|
style: [styles.alignCenter, {
|
|
422
452
|
flexGrow: 1,
|
|
423
453
|
marginRight: 12
|
|
@@ -471,8 +501,8 @@ const Dropdown = ({
|
|
|
471
501
|
top: dropdownPosition.top,
|
|
472
502
|
left: dropdownPosition.left,
|
|
473
503
|
width: dropdownWidthCalc
|
|
474
|
-
},
|
|
475
|
-
maxHeight:
|
|
504
|
+
}, resolvedSubHeight ? {
|
|
505
|
+
maxHeight: resolvedSubHeight
|
|
476
506
|
} : null],
|
|
477
507
|
onLayout: handleConLayout,
|
|
478
508
|
children: customPopoverContent ? customPopoverContent : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
|
|
@@ -506,8 +536,8 @@ const Dropdown = ({
|
|
|
506
536
|
} : null],
|
|
507
537
|
onPress: () => {
|
|
508
538
|
closeModal();
|
|
509
|
-
if (
|
|
510
|
-
|
|
539
|
+
if (resolvedOnSelect) {
|
|
540
|
+
resolvedOnSelect(item);
|
|
511
541
|
} else {
|
|
512
542
|
setSelectedItemKey(item.key);
|
|
513
543
|
}
|
|
@@ -553,7 +583,7 @@ const Dropdown = ({
|
|
|
553
583
|
numberOfLines: 1,
|
|
554
584
|
ellipsizeMode: "tail",
|
|
555
585
|
style: [styles.modalOptionText, styles.modalNoOptions],
|
|
556
|
-
children:
|
|
586
|
+
children: resolvedEmptyText || "No options"
|
|
557
587
|
})
|
|
558
588
|
})
|
|
559
589
|
})
|
|
@@ -561,7 +591,7 @@ const Dropdown = ({
|
|
|
561
591
|
onPress: () => {
|
|
562
592
|
closeModal();
|
|
563
593
|
setTimeout(() => {
|
|
564
|
-
|
|
594
|
+
resolvedOnExtendBtnPress?.();
|
|
565
595
|
}, 300);
|
|
566
596
|
},
|
|
567
597
|
style: [styles.extendBtnCon, {
|
|
@@ -590,8 +620,8 @@ const Dropdown = ({
|
|
|
590
620
|
value: `${prefix}${selected_old?.name}`,
|
|
591
621
|
isVisible: isVisible,
|
|
592
622
|
width: width,
|
|
593
|
-
subWidth:
|
|
594
|
-
subHeight:
|
|
623
|
+
subWidth: resolvedSubWidth,
|
|
624
|
+
subHeight: resolvedSubHeight,
|
|
595
625
|
testID: testID,
|
|
596
626
|
...props,
|
|
597
627
|
onClose: () => {
|
|
@@ -615,7 +645,7 @@ const Dropdown = ({
|
|
|
615
645
|
borderEndWidth: 1,
|
|
616
646
|
borderTopWidth: 0,
|
|
617
647
|
borderRightWidth: 0,
|
|
618
|
-
width:
|
|
648
|
+
width: resolvedSubWidth
|
|
619
649
|
},
|
|
620
650
|
inputContainerStyle: styles.inputContainer,
|
|
621
651
|
placeholder: props.placeholder,
|
|
@@ -645,8 +675,8 @@ const Dropdown = ({
|
|
|
645
675
|
})
|
|
646
676
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
|
|
647
677
|
style: {
|
|
648
|
-
width:
|
|
649
|
-
height:
|
|
678
|
+
width: resolvedSubWidth,
|
|
679
|
+
height: resolvedSubHeight
|
|
650
680
|
},
|
|
651
681
|
keyboardShouldPersistTaps: "handled",
|
|
652
682
|
keyboardDismissMode: "none",
|