@miot-rn/car-component 1.0.1

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 (242) hide show
  1. package/README.md +325 -0
  2. package/dist/assets/i18n/ar.d.ts +55 -0
  3. package/dist/assets/i18n/ar.js +55 -0
  4. package/dist/assets/i18n/bo.d.ts +55 -0
  5. package/dist/assets/i18n/bo.js +55 -0
  6. package/dist/assets/i18n/cs.d.ts +55 -0
  7. package/dist/assets/i18n/cs.js +55 -0
  8. package/dist/assets/i18n/de.d.ts +55 -0
  9. package/dist/assets/i18n/de.js +55 -0
  10. package/dist/assets/i18n/el.d.ts +55 -0
  11. package/dist/assets/i18n/el.js +55 -0
  12. package/dist/assets/i18n/en.d.ts +55 -0
  13. package/dist/assets/i18n/en.js +55 -0
  14. package/dist/assets/i18n/es.d.ts +55 -0
  15. package/dist/assets/i18n/es.js +55 -0
  16. package/dist/assets/i18n/es_us.d.ts +55 -0
  17. package/dist/assets/i18n/es_us.js +55 -0
  18. package/dist/assets/i18n/fi.d.ts +55 -0
  19. package/dist/assets/i18n/fi.js +55 -0
  20. package/dist/assets/i18n/fr.d.ts +55 -0
  21. package/dist/assets/i18n/fr.js +55 -0
  22. package/dist/assets/i18n/he.d.ts +55 -0
  23. package/dist/assets/i18n/he.js +55 -0
  24. package/dist/assets/i18n/hu.d.ts +55 -0
  25. package/dist/assets/i18n/hu.js +55 -0
  26. package/dist/assets/i18n/id.d.ts +55 -0
  27. package/dist/assets/i18n/id.js +55 -0
  28. package/dist/assets/i18n/it.d.ts +55 -0
  29. package/dist/assets/i18n/it.js +55 -0
  30. package/dist/assets/i18n/ja.d.ts +55 -0
  31. package/dist/assets/i18n/ja.js +55 -0
  32. package/dist/assets/i18n/ko.d.ts +55 -0
  33. package/dist/assets/i18n/ko.js +55 -0
  34. package/dist/assets/i18n/nb.d.ts +55 -0
  35. package/dist/assets/i18n/nb.js +55 -0
  36. package/dist/assets/i18n/nl.d.ts +55 -0
  37. package/dist/assets/i18n/nl.js +55 -0
  38. package/dist/assets/i18n/pl.d.ts +55 -0
  39. package/dist/assets/i18n/pl.js +55 -0
  40. package/dist/assets/i18n/pt.d.ts +55 -0
  41. package/dist/assets/i18n/pt.js +55 -0
  42. package/dist/assets/i18n/pt_pt.d.ts +55 -0
  43. package/dist/assets/i18n/pt_pt.js +55 -0
  44. package/dist/assets/i18n/ro.d.ts +55 -0
  45. package/dist/assets/i18n/ro.js +55 -0
  46. package/dist/assets/i18n/ru.d.ts +55 -0
  47. package/dist/assets/i18n/ru.js +55 -0
  48. package/dist/assets/i18n/sk.d.ts +55 -0
  49. package/dist/assets/i18n/sk.js +55 -0
  50. package/dist/assets/i18n/sv.d.ts +55 -0
  51. package/dist/assets/i18n/sv.js +55 -0
  52. package/dist/assets/i18n/th.d.ts +55 -0
  53. package/dist/assets/i18n/th.js +55 -0
  54. package/dist/assets/i18n/tr.d.ts +55 -0
  55. package/dist/assets/i18n/tr.js +55 -0
  56. package/dist/assets/i18n/uk.d.ts +55 -0
  57. package/dist/assets/i18n/uk.js +55 -0
  58. package/dist/assets/i18n/vi.d.ts +55 -0
  59. package/dist/assets/i18n/vi.js +55 -0
  60. package/dist/assets/i18n/zh.d.ts +55 -0
  61. package/dist/assets/i18n/zh.js +55 -0
  62. package/dist/assets/i18n/zh_hk.d.ts +55 -0
  63. package/dist/assets/i18n/zh_hk.js +55 -0
  64. package/dist/assets/i18n/zh_tw.d.ts +55 -0
  65. package/dist/assets/i18n/zh_tw.js +55 -0
  66. package/dist/assets/image/dark/car_background_dark.png +0 -0
  67. package/dist/assets/image/default/car_background.png +0 -0
  68. package/dist/components/airConditioningCard/index.d.ts +24 -0
  69. package/dist/components/airConditioningCard/index.js +103 -0
  70. package/dist/components/carInfoHeader/carImage.d.ts +8 -0
  71. package/dist/components/carInfoHeader/carImage.js +42 -0
  72. package/dist/components/carInfoHeader/dualRangeIndicator.d.ts +15 -0
  73. package/dist/components/carInfoHeader/dualRangeIndicator.js +124 -0
  74. package/dist/components/carInfoHeader/index.d.ts +37 -0
  75. package/dist/components/carInfoHeader/index.js +118 -0
  76. package/dist/components/carInfoHeader/parkingStatus.d.ts +12 -0
  77. package/dist/components/carInfoHeader/parkingStatus.js +100 -0
  78. package/dist/components/carInfoHeader/rangeProgressBar.d.ts +14 -0
  79. package/dist/components/carInfoHeader/rangeProgressBar.js +77 -0
  80. package/dist/components/carInfoHeader/singleRangeIndicator.d.ts +11 -0
  81. package/dist/components/carInfoHeader/singleRangeIndicator.js +58 -0
  82. package/dist/components/cardContainer/index.d.ts +8 -0
  83. package/dist/components/cardContainer/index.js +22 -0
  84. package/dist/components/containerWithGap/gapWrap.d.ts +8 -0
  85. package/dist/components/containerWithGap/gapWrap.js +31 -0
  86. package/dist/components/containerWithGap/index.d.ts +12 -0
  87. package/dist/components/containerWithGap/index.js +43 -0
  88. package/dist/components/flatSelect/FlatOption.d.ts +18 -0
  89. package/dist/components/flatSelect/FlatOption.js +117 -0
  90. package/dist/components/flatSelect/FlatSelect.d.ts +14 -0
  91. package/dist/components/flatSelect/FlatSelect.js +112 -0
  92. package/dist/components/flatSelect/index.d.ts +2 -0
  93. package/dist/components/flatSelect/index.js +2 -0
  94. package/dist/components/flatSelect/index.zh-CN.md +89 -0
  95. package/dist/components/groupContainer/index.d.ts +9 -0
  96. package/dist/components/groupContainer/index.js +48 -0
  97. package/dist/components/otherSettingCard/index.d.ts +8 -0
  98. package/dist/components/otherSettingCard/index.js +40 -0
  99. package/dist/components/pageBackground/index.d.ts +7 -0
  100. package/dist/components/pageBackground/index.js +22 -0
  101. package/dist/components/seatControl/index.d.ts +34 -0
  102. package/dist/components/seatControl/index.js +98 -0
  103. package/dist/components/seatControl/seatCard.d.ts +11 -0
  104. package/dist/components/seatControl/seatCard.js +24 -0
  105. package/dist/components/seatControl/seatCardRow.d.ts +29 -0
  106. package/dist/components/seatControl/seatCardRow.js +48 -0
  107. package/dist/components/seatControlGroup/index.d.ts +40 -0
  108. package/dist/components/seatControlGroup/index.js +51 -0
  109. package/dist/components/steeringWheelHotCard/index.d.ts +17 -0
  110. package/dist/components/steeringWheelHotCard/index.js +66 -0
  111. package/dist/components/titleContainer/TitleContainer.d.ts +4 -0
  112. package/dist/components/titleContainer/TitleContainer.js +148 -0
  113. package/dist/components/titleContainer/TitleContainer.zh-CN.md +62 -0
  114. package/dist/components/titleContainer/index.d.ts +1 -0
  115. package/dist/components/titleContainer/index.js +1 -0
  116. package/dist/components/titleContainer/interface.d.ts +48 -0
  117. package/dist/components/titleContainer/interface.js +21 -0
  118. package/dist/components/warningForRunningCard/index.d.ts +6 -0
  119. package/dist/components/warningForRunningCard/index.js +20 -0
  120. package/dist/config/ConnectStatus.d.ts +7 -0
  121. package/dist/config/ConnectStatus.js +8 -0
  122. package/dist/config/index.d.ts +16 -0
  123. package/dist/config/index.js +16 -0
  124. package/dist/config/seatFunctionType.d.ts +7 -0
  125. package/dist/config/seatFunctionType.js +24 -0
  126. package/dist/config/seatGearLevel.d.ts +21 -0
  127. package/dist/config/seatGearLevel.js +19 -0
  128. package/dist/config/seatI18nKeys.d.ts +9 -0
  129. package/dist/config/seatI18nKeys.js +9 -0
  130. package/dist/config/seatPosition.d.ts +8 -0
  131. package/dist/config/seatPosition.js +8 -0
  132. package/dist/config/seatRowConfig.d.ts +6 -0
  133. package/dist/config/seatRowConfig.js +6 -0
  134. package/dist/global.d.js +0 -0
  135. package/dist/hooks/CONNECT_STATUS.d.ts +6 -0
  136. package/dist/hooks/CONNECT_STATUS.js +5 -0
  137. package/dist/hooks/index.d.ts +6 -0
  138. package/dist/hooks/index.js +7 -0
  139. package/dist/hooks/useAirConditionData.d.ts +29 -0
  140. package/dist/hooks/useAirConditionData.js +89 -0
  141. package/dist/hooks/useDualRangeData.d.ts +18 -0
  142. package/dist/hooks/useDualRangeData.js +82 -0
  143. package/dist/hooks/useParkingStatusData.d.ts +19 -0
  144. package/dist/hooks/useParkingStatusData.js +100 -0
  145. package/dist/hooks/useSeatControlData.d.ts +94 -0
  146. package/dist/hooks/useSeatControlData.js +251 -0
  147. package/dist/hooks/useSingleRangeData.d.ts +15 -0
  148. package/dist/hooks/useSingleRangeData.js +97 -0
  149. package/dist/hooks/useSteeringWheelData.d.ts +11 -0
  150. package/dist/hooks/useSteeringWheelData.js +56 -0
  151. package/dist/icons/CarInUsed.d.ts +4 -0
  152. package/dist/icons/CarInUsed.js +13 -0
  153. package/dist/icons/DeviceManage.d.ts +4 -0
  154. package/dist/icons/DeviceManage.js +13 -0
  155. package/dist/icons/ElectricPower.d.ts +4 -0
  156. package/dist/icons/ElectricPower.js +13 -0
  157. package/dist/icons/ErrorStatus.d.ts +4 -0
  158. package/dist/icons/ErrorStatus.js +13 -0
  159. package/dist/icons/FuelPower.d.ts +4 -0
  160. package/dist/icons/FuelPower.js +18 -0
  161. package/dist/icons/Loading.d.ts +4 -0
  162. package/dist/icons/Loading.js +16 -0
  163. package/dist/icons/MijiaLogo.d.ts +4 -0
  164. package/dist/icons/MijiaLogo.js +16 -0
  165. package/dist/icons/Minus.d.ts +4 -0
  166. package/dist/icons/Minus.js +15 -0
  167. package/dist/icons/ParkingStatus.d.ts +4 -0
  168. package/dist/icons/ParkingStatus.js +15 -0
  169. package/dist/icons/SeatGearHeatingLevelOne.d.ts +4 -0
  170. package/dist/icons/SeatGearHeatingLevelOne.js +22 -0
  171. package/dist/icons/SeatGearHeatingLevelThree.d.ts +4 -0
  172. package/dist/icons/SeatGearHeatingLevelThree.js +18 -0
  173. package/dist/icons/SeatGearHeatingLevelTwo.d.ts +4 -0
  174. package/dist/icons/SeatGearHeatingLevelTwo.js +22 -0
  175. package/dist/icons/SeatGearHeatingOff.d.ts +4 -0
  176. package/dist/icons/SeatGearHeatingOff.js +18 -0
  177. package/dist/icons/SeatGearVentilationLevelOne.d.ts +4 -0
  178. package/dist/icons/SeatGearVentilationLevelOne.js +17 -0
  179. package/dist/icons/SeatGearVentilationLevelThree.d.ts +4 -0
  180. package/dist/icons/SeatGearVentilationLevelThree.js +13 -0
  181. package/dist/icons/SeatGearVentilationLevelTwo.d.ts +4 -0
  182. package/dist/icons/SeatGearVentilationLevelTwo.js +17 -0
  183. package/dist/icons/SeatGearVentilationOff.d.ts +4 -0
  184. package/dist/icons/SeatGearVentilationOff.js +16 -0
  185. package/dist/icons/SentryMode.d.ts +4 -0
  186. package/dist/icons/SentryMode.js +13 -0
  187. package/dist/icons/SmartScene.d.ts +4 -0
  188. package/dist/icons/SmartScene.js +13 -0
  189. package/dist/icons/SteeringWheelFirstGear.d.ts +4 -0
  190. package/dist/icons/SteeringWheelFirstGear.js +13 -0
  191. package/dist/icons/SteeringWheelHot.d.ts +4 -0
  192. package/dist/icons/SteeringWheelHot.js +13 -0
  193. package/dist/icons/SteeringWheelSecondGear.d.ts +4 -0
  194. package/dist/icons/SteeringWheelSecondGear.js +13 -0
  195. package/dist/icons/SteeringWheelThirdGear.d.ts +4 -0
  196. package/dist/icons/SteeringWheelThirdGear.js +13 -0
  197. package/dist/icons/Warning.d.ts +4 -0
  198. package/dist/icons/Warning.js +13 -0
  199. package/dist/icons/index.d.ts +24 -0
  200. package/dist/icons/index.js +27 -0
  201. package/dist/index.d.ts +21 -0
  202. package/dist/index.js +20 -0
  203. package/dist/modules/MODULES.md +245 -0
  204. package/dist/modules/airconditionModule/README.md +262 -0
  205. package/dist/modules/airconditionModule/index.d.ts +17 -0
  206. package/dist/modules/airconditionModule/index.js +63 -0
  207. package/dist/modules/carInfoModule/README.md +418 -0
  208. package/dist/modules/carInfoModule/index.d.ts +26 -0
  209. package/dist/modules/carInfoModule/index.js +67 -0
  210. package/dist/modules/index.d.ts +2 -0
  211. package/dist/modules/index.js +2 -0
  212. package/dist/modules/seatModule/README.md +345 -0
  213. package/dist/modules/seatModule/index.d.ts +15 -0
  214. package/dist/modules/seatModule/index.js +40 -0
  215. package/dist/modules/steeringWheelModule/README.md +216 -0
  216. package/dist/modules/steeringWheelModule/index.d.ts +13 -0
  217. package/dist/modules/steeringWheelModule/index.js +31 -0
  218. package/dist/resources/i18n.d.ts +1730 -0
  219. package/dist/resources/i18n.js +84 -0
  220. package/dist/resources/images.d.ts +1 -0
  221. package/dist/resources/images.js +45 -0
  222. package/dist/spec/index.d.ts +494 -0
  223. package/dist/spec/index.js +911 -0
  224. package/dist/types.d.ts +63 -0
  225. package/dist/types.js +1 -0
  226. package/dist/utils/checkSameValue.d.ts +1 -0
  227. package/dist/utils/checkSameValue.js +11 -0
  228. package/dist/utils/fns.d.ts +5 -0
  229. package/dist/utils/fns.js +167 -0
  230. package/dist/utils/get-value-or-default.d.ts +1 -0
  231. package/dist/utils/get-value-or-default.js +4 -0
  232. package/dist/utils/getLocalI18n.d.ts +1 -0
  233. package/dist/utils/getLocalI18n.js +9 -0
  234. package/dist/utils/i18n.d.ts +1 -0
  235. package/dist/utils/i18n.js +141 -0
  236. package/dist/utils/objects.d.ts +2 -0
  237. package/dist/utils/objects.js +222 -0
  238. package/dist/utils/spec.d.ts +8 -0
  239. package/dist/utils/spec.js +171 -0
  240. package/dist/utils/types.d.ts +3 -0
  241. package/dist/utils/types.js +25 -0
  242. package/package.json +27 -0
@@ -0,0 +1,345 @@
1
+ # SeatModule — 座椅控制模块
2
+
3
+ ## 概述
4
+
5
+ 座椅加热/通风控制模块,支持前排 2 座 + 后排 3 座的加热和通风档位切换。根据传入的 specs 动态生成座椅布局,无座椅 spec 时自动隐藏。
6
+
7
+ ## 引用方式
8
+
9
+ 本模块支持三种引用粒度,开发者可根据需要选择:
10
+
11
+ | 引用方式 | 说明 | 适用场景 |
12
+ |---------|------|---------|
13
+ | **Module(推荐)** | 完整模块,内含数据层 + UI 层 | 标准业务场景,开箱即用 |
14
+ | **Hook** | 仅数据层(`useSeatControlData`) | 需要自定义 UI,复用座椅数据逻辑 |
15
+ | **Component** | 仅 UI 层(`SeatControlGroup`) | 已有数据源,仅需渲染 UI |
16
+
17
+ ## 文件
18
+
19
+ ```
20
+ seatModule/
21
+ └── index.tsx
22
+ ```
23
+
24
+ ---
25
+
26
+ ## 1. Module 用法(完整模块)
27
+
28
+ ### Props
29
+
30
+ ```typescript
31
+ interface SeatModuleProps {
32
+ specs: SeatSpecs;
33
+ disabled?: boolean; // 默认 false,禁用所有座椅控制
34
+ onSeatChange?: (params: {
35
+ propType: string; // 'heating' | 'ventilation'
36
+ previousValue: number;
37
+ currentValue: number;
38
+ }) => void;
39
+ style?: StyleProp<ViewStyle>;
40
+ }
41
+ ```
42
+
43
+ ### Specs 定义
44
+
45
+ #### 第一排座椅
46
+
47
+ | Spec | 用途 | 必填 |
48
+ |------|------|------|
49
+ | `specSeatRow1LeftPropertiesHeating` | 主驾加热 | 否 |
50
+ | `specSeatRow1LeftPropertiesSeatVentilation` | 主驾通风 | 否 |
51
+ | `specSeatRow1RightPropertiesHeating` | 副驾加热 | 否 |
52
+ | `specSeatRow1RightPropertiesSeatVentilation` | 副驾通风 | 否 |
53
+
54
+ #### 第二排座椅
55
+
56
+ | Spec | 用途 | 必填 |
57
+ |------|------|------|
58
+ | `specSeatRow2LeftPropertiesHeating` | 后排左座加热 | 否 |
59
+ | `specSeatRow2LeftPropertiesSeatVentilation` | 后排左座通风 | 否 |
60
+ | `specSeatRow2MiddlePropertiesHeating` | 后排中座加热 | 否 |
61
+ | `specSeatRow2MiddlePropertiesSeatVentilation` | 后排中座通风 | 否 |
62
+ | `specSeatRow2RightPropertiesHeating` | 后排右座加热 | 否 |
63
+ | `specSeatRow2RightPropertiesSeatVentilation` | 后排右座通风 | 否 |
64
+
65
+ ### 核心逻辑
66
+
67
+ - 每个座位根据是否传入 heating/ventilation spec 决定是否显示
68
+ - 整行无座椅 spec 时该行不渲染
69
+ - 所有座椅 spec 均未传入时 `hasSeats = false`,整个模块不渲染
70
+
71
+ ### 示例
72
+
73
+ ```tsx
74
+ import { SeatModule } from '@miot-rn/car-component/dist/modules';
75
+
76
+ <SeatModule
77
+ specs={{
78
+ specSeatRow1LeftPropertiesHeating: row1LeftHeatingSpec,
79
+ specSeatRow1LeftPropertiesSeatVentilation: row1LeftVentSpec,
80
+ specSeatRow1RightPropertiesHeating: row1RightHeatingSpec,
81
+ }}
82
+ disabled={!isConnected}
83
+ onSeatChange={({ propType, previousValue, currentValue }) => {
84
+ console.log(`${propType}: ${previousValue} → ${currentValue}`);
85
+ }}
86
+ />
87
+ ```
88
+
89
+ ---
90
+
91
+ ## 2. Hook 用法(`useSeatControlData`)
92
+
93
+ 适用于需要**自定义 UI** 但复用座椅数据逻辑的场景。
94
+
95
+ ### 引入
96
+
97
+ ```typescript
98
+ import { useSeatControlData } from '@miot-rn/car-component/dist/hooks/useSeatControlData';
99
+ ```
100
+
101
+ ### 入参
102
+
103
+ ```typescript
104
+ interface SeatControlDataProps {
105
+ specs: SeatSpecs;
106
+ disabled?: boolean; // 默认 false
107
+ onSeatChange?: (params: {
108
+ propType: string;
109
+ previousValue: number;
110
+ currentValue: number;
111
+ }) => void;
112
+ }
113
+ ```
114
+
115
+ ### 返回值
116
+
117
+ | 字段 | 类型 | 说明 |
118
+ |------|------|------|
119
+ | `seatRows` | `SeatRowData[][]` | 二维座椅数据,按行列组织 |
120
+ | `seatTitles` | `SeatTitles` | 各座椅位置 i18n 标题 |
121
+ | `handleSeatChange` | `(params) => void` | 档位变更处理(内部调用 `setSpec` + 触发 `onSeatChange`) |
122
+ | `hasSeats` | `boolean` | 是否有可用座椅(`false` 时应隐藏 UI) |
123
+
124
+ **`seatRows` 结构:**
125
+
126
+ ```typescript
127
+ // seatRows[rowIndex][seatIndex]
128
+ {
129
+ serviceType: string; // 座椅服务标识
130
+ title: string; // 座椅位置标题(i18n)
131
+ disabled: boolean; // 是否禁用
132
+ buttons: Array<{
133
+ spec: Spec; // 原始 spec 引用
134
+ propType: 'heating' | 'ventilation';
135
+ states: Array<{
136
+ value: string; // 档位值
137
+ backgroundColor: string; // 背景色
138
+ icon: ReactElement; // 档位图标
139
+ }>;
140
+ currentStateIndex: number; // 当前档位索引
141
+ disabled: boolean;
142
+ }>;
143
+ }
144
+ ```
145
+
146
+ **`seatTitles` 结构:**
147
+
148
+ ```typescript
149
+ {
150
+ groupTitle: string; // 分组标题
151
+ frontLeft: string; // 主驾
152
+ frontRight: string; // 副驾
153
+ rearLeft: string; // 后排左座
154
+ rearCenter: string; // 后排中座
155
+ rearRight: string; // 后排右座
156
+ }
157
+ ```
158
+
159
+ ### 档位状态与图标
160
+
161
+ **加热档位(橙色):**
162
+
163
+ | 档位 | 图标 | 背景色 |
164
+ |------|------|--------|
165
+ | Off | `SeatGearHeatingOff` | `mj_color_gray_fill_2` |
166
+ | Level 1 | `SeatGearHeatingLevelOne` | `mjcard_color_orange_1` |
167
+ | Level 2 | `SeatGearHeatingLevelTwo` | `mjcard_color_orange_1` |
168
+ | Level 3 | `SeatGearHeatingLevelThree` | `mjcard_color_orange_1` |
169
+
170
+ **通风档位(蓝色):**
171
+
172
+ | 档位 | 图标 | 背景色 |
173
+ |------|------|--------|
174
+ | Off | `SeatGearVentilationOff` | `mj_color_gray_fill_2` |
175
+ | Level 1 | `SeatGearVentilationLevelOne` | `mjcard_color_blue_1` |
176
+ | Level 2 | `SeatGearVentilationLevelTwo` | `mjcard_color_blue_1` |
177
+ | Level 3 | `SeatGearVentilationLevelThree` | `mjcard_color_blue_1` |
178
+
179
+ ### 导出的工具函数
180
+
181
+ Hook 文件同时导出以下工具,供高级自定义场景使用:
182
+
183
+ ```typescript
184
+ // 生成档位图标映射
185
+ export const LEVEL_ICONS: (colorToken: any) => LevelIcons;
186
+
187
+ // 生成加热/通风状态配置(排序、颜色、图标)
188
+ export const TYPE_CONFIG: (colorToken: any, levelIcons: LevelIcons) => Record<string, StateConfig>;
189
+
190
+ // 座椅标题 i18n 集合
191
+ export const SEAT_TITLES: { groupTitle, frontLeft, frontRight, rearLeft, rearCenter, rearRight };
192
+ ```
193
+
194
+ ### 示例
195
+
196
+ ```tsx
197
+ import { useSeatControlData } from '@miot-rn/car-component/dist/hooks/useSeatControlData';
198
+
199
+ const MyCustomSeatControl = ({ specs, disabled }) => {
200
+ const { seatRows, seatTitles, handleSeatChange, hasSeats } = useSeatControlData({
201
+ specs,
202
+ disabled,
203
+ onSeatChange: ({ propType, previousValue, currentValue }) => {
204
+ console.log(`${propType}: ${previousValue} → ${currentValue}`);
205
+ },
206
+ });
207
+
208
+ if (!hasSeats) return null;
209
+
210
+ return (
211
+ <View>
212
+ <Text>{seatTitles.groupTitle}</Text>
213
+ {seatRows.map((row, rowIdx) => (
214
+ <View key={rowIdx} style={{ flexDirection: 'row' }}>
215
+ {row.map((seat) => (
216
+ <View key={seat.serviceType}>
217
+ <Text>{seat.title}</Text>
218
+ {seat.buttons.map((btn) => (
219
+ <TouchableOpacity
220
+ key={btn.propType}
221
+ disabled={btn.disabled}
222
+ onPress={() => {
223
+ const nextIndex = (btn.currentStateIndex + 1) % btn.states.length;
224
+ handleSeatChange({
225
+ propType: btn.propType,
226
+ spec: btn.spec,
227
+ previousValue: btn.states[btn.currentStateIndex].value,
228
+ currentValue: btn.states[nextIndex].value,
229
+ });
230
+ }}
231
+ style={{ backgroundColor: btn.states[btn.currentStateIndex].backgroundColor }}
232
+ >
233
+ {btn.states[btn.currentStateIndex].icon}
234
+ </TouchableOpacity>
235
+ ))}
236
+ </View>
237
+ ))}
238
+ </View>
239
+ ))}
240
+ </View>
241
+ );
242
+ };
243
+ ```
244
+
245
+ ---
246
+
247
+ ## 3. Component 用法(`SeatControlGroup`)
248
+
249
+ 适用于已有数据源,仅需渲染座椅控制 UI 的场景。
250
+
251
+ ### 引入
252
+
253
+ ```typescript
254
+ import { SeatControlGroup } from '@miot-rn/car-component/dist/components/seatControlGroup';
255
+ ```
256
+
257
+ ### Props
258
+
259
+ ```typescript
260
+ interface SeatControlGroupProps {
261
+ seatRows: SeatConfig[][]; // 二维座椅配置
262
+ title?: string; // 分组标题
263
+ onSeatChange?: (params: OnButtonPressParams) => void;
264
+ disabled?: boolean; // 默认 false
265
+ style?: StyleProp<ViewStyle>;
266
+ }
267
+
268
+ type SeatConfig = {
269
+ serviceType: string; // 座椅标识
270
+ title: string; // 座椅标题
271
+ buttons: ControlButtonConfig[]; // 控制按钮列表
272
+ disabled?: boolean; // 单座椅禁用
273
+ };
274
+
275
+ type ControlButtonConfig = {
276
+ propType: string; // 'heating' | 'ventilation'
277
+ spec?: string; // spec 标识
278
+ title?: string;
279
+ states: ButtonStateConfig[]; // 档位状态列表
280
+ currentStateIndex: number; // 当前档位索引
281
+ disabled?: boolean;
282
+ };
283
+
284
+ type ButtonStateConfig = {
285
+ value: string; // 档位值
286
+ backgroundColor: string; // 背景色
287
+ disabledBackgroundColor: string; // 禁用背景色
288
+ icon: React.ReactElement; // 档位图标
289
+ iconColor: string; // 图标颜色
290
+ };
291
+
292
+ type OnButtonPressParams = {
293
+ propType: string;
294
+ spec?: string;
295
+ previousStateIndex: number;
296
+ currentStateIndex: number;
297
+ previousValue: string;
298
+ currentValue: string;
299
+ action: 'switch';
300
+ };
301
+ ```
302
+
303
+ ### 渲染结构
304
+
305
+ ```
306
+ GroupContainer (带标题)
307
+ └── ContainerWithGap (每行, horizontal, gap=8)
308
+ └── SeatCard (每个座椅)
309
+ └── CardContainer > SeatControl
310
+ ├── 座椅标题
311
+ └── 圆形档位切换按钮(点击循环切换)
312
+ ```
313
+
314
+ ### 示例
315
+
316
+ ```tsx
317
+ import { SeatControlGroup } from '@miot-rn/car-component/dist/components/seatControlGroup';
318
+
319
+ <SeatControlGroup
320
+ title="座椅"
321
+ disabled={false}
322
+ seatRows={[
323
+ [
324
+ {
325
+ serviceType: 'front-left',
326
+ title: '主驾',
327
+ buttons: [
328
+ {
329
+ propType: 'heating',
330
+ states: [
331
+ { value: '0', backgroundColor: '#gray', icon: <OffIcon /> },
332
+ { value: '1', backgroundColor: '#orange', icon: <Level1Icon /> },
333
+ ],
334
+ currentStateIndex: 0,
335
+ disabled: false,
336
+ },
337
+ ],
338
+ },
339
+ ],
340
+ ]}
341
+ onSeatChange={(params) => {
342
+ console.log('座椅操作:', params);
343
+ }}
344
+ />
345
+ ```
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import { StyleProp, ViewStyle } from 'react-native';
3
+ import type { SeatSpecs } from '../../hooks/useSeatControlData';
4
+ export interface SeatModuleProps {
5
+ specs: SeatSpecs;
6
+ disabled?: boolean;
7
+ onSeatChange?: (params: {
8
+ propType: string;
9
+ previousValue: number;
10
+ currentValue: number;
11
+ }) => void;
12
+ style?: StyleProp<ViewStyle>;
13
+ }
14
+ export declare const SeatModule: ({ specs, disabled, onSeatChange, style }: SeatModuleProps) => React.JSX.Element | null;
15
+ export default SeatModule;
@@ -0,0 +1,40 @@
1
+ /* eslint-disable no-console */
2
+ import React from 'react';
3
+ import { SeatControlGroup } from "../../components/seatControlGroup";
4
+ import { useSeatControlData } from "../../hooks";
5
+ export const SeatModule = ({
6
+ specs,
7
+ disabled = false,
8
+ onSeatChange,
9
+ style
10
+ }) => {
11
+ const {
12
+ seatRows,
13
+ seatTitles,
14
+ handleSeatChange: handleSeatChangeFromHook,
15
+ hasSeats
16
+ } = useSeatControlData({
17
+ specs,
18
+ disabled,
19
+ onSeatChange
20
+ });
21
+ if (!hasSeats) {
22
+ return null;
23
+ }
24
+ return /*#__PURE__*/React.createElement(SeatControlGroup, {
25
+ seatRows: seatRows,
26
+ title: seatTitles.groupTitle,
27
+ onSeatChange: params => {
28
+ // Convert from SeatControlGroup format to useSeatControlData format
29
+ handleSeatChangeFromHook({
30
+ propType: params.propType,
31
+ spec: params.spec,
32
+ previousValue: params.previousValue,
33
+ currentValue: params.currentValue
34
+ });
35
+ },
36
+ disabled: disabled,
37
+ style: style
38
+ });
39
+ };
40
+ export default SeatModule;
@@ -0,0 +1,216 @@
1
+ # SteeringWheelModule — 方向盘加热模块
2
+
3
+ ## 概述
4
+
5
+ 方向盘加热控制模块,提供 Off / Level1 / Level2 / Level3 四档加热选择。
6
+
7
+ > ⚠️ 当前未从 `modules/index.ts` 导出,需直接引用子路径。
8
+
9
+ ## 引用方式
10
+
11
+ 本模块支持三种引用粒度,开发者可根据需要选择:
12
+
13
+ | 引用方式 | 说明 | 适用场景 |
14
+ |---------|------|---------|
15
+ | **Module(推荐)** | 完整模块,内含数据层 + UI 层 | 标准业务场景,开箱即用 |
16
+ | **Hook** | 仅数据层(`useSteeringWheelData`) | 需要自定义 UI,复用数据逻辑 |
17
+ | **Component** | 仅 UI 层(`SteeringWheelHotCard`) | 已有数据源,仅需渲染 UI |
18
+
19
+ ## 文件
20
+
21
+ ```
22
+ steeringWheelModule/
23
+ └── index.tsx
24
+ ```
25
+
26
+ ---
27
+
28
+ ## 1. Module 用法(完整模块)
29
+
30
+ ### Props
31
+
32
+ ```typescript
33
+ interface SteeringWheelModuleProps {
34
+ specs: SteeringWheelSpecs;
35
+ connectStatus?: ConnectStatusValue; // 默认 ConnectStatus.CONNECTING
36
+ isCarRunning: boolean; // 车辆是否行驶中
37
+ }
38
+
39
+ interface SteeringWheelSpecs {
40
+ specBodySteeringWheelPropertiesSteeringWheelHeating: Spec;
41
+ }
42
+ ```
43
+
44
+ ### Specs 定义
45
+
46
+ | Spec | 用途 | 必填 |
47
+ |------|------|------|
48
+ | `specBodySteeringWheelPropertiesSteeringWheelHeating` | 方向盘加热档位 | 是 |
49
+
50
+ ### 禁用条件
51
+
52
+ ```
53
+ disabled = connectStatus !== ConnectStatus.CONNECTED || isCarRunning
54
+ ```
55
+
56
+ ### 示例
57
+
58
+ ```tsx
59
+ import { SteeringWheelModule } from '@miot-rn/car-component/dist/modules/steeringWheelModule';
60
+ import { ConnectStatus } from '@miot-rn/car-component/dist/config';
61
+
62
+ <SteeringWheelModule
63
+ specs={{
64
+ specBodySteeringWheelPropertiesSteeringWheelHeating: steeringWheelSpec,
65
+ }}
66
+ connectStatus={ConnectStatus.CONNECTED}
67
+ isCarRunning={false}
68
+ />
69
+ ```
70
+
71
+ ---
72
+
73
+ ## 2. Hook 用法(`useSteeringWheelData`)
74
+
75
+ 适用于需要**自定义 UI** 但复用方向盘加热数据逻辑的场景。
76
+
77
+ ### 引入
78
+
79
+ ```typescript
80
+ import { useSteeringWheelData } from '@miot-rn/car-component/dist/hooks/useSteeringWheelData';
81
+ ```
82
+
83
+ ### 入参
84
+
85
+ ```typescript
86
+ interface UseSteeringWheelDataProps {
87
+ specBodySteeringWheelPropertiesSteeringWheelHeating: Spec;
88
+ }
89
+ ```
90
+
91
+ ### 返回值
92
+
93
+ | 字段 | 类型 | 说明 |
94
+ |------|------|------|
95
+ | `steeringWheelTitle` | `string` | 标题文案(i18n `car_steering_wheel_hot`) |
96
+ | `steeringWheelHeatState` | `any` | 当前加热档位 spec 原始值(string 类型) |
97
+ | `onSteeringWheelHotChange` | `(val: any) => void` | 档位切换回调,内部调用 `setSpec` 写入设备 |
98
+ | `steeringWheelOptions` | `Array<OptionItem>` | 档位选项列表,从 spec `value-list` 动态生成 |
99
+
100
+ **`steeringWheelOptions` 每项结构:**
101
+
102
+ | 字段 | 类型 | 说明 |
103
+ |------|------|------|
104
+ | `value` | `string \| number` | spec value-list 中的 value |
105
+ | `label` | `string` | 根据 description 映射的 i18n 文案 |
106
+ | `colorType` | `'orange' \| undefined` | 非 OFF 档位为 `'orange'`,OFF 为 `undefined` |
107
+ | `description` | `string` | spec 原始 description |
108
+
109
+ ### i18n 文案映射
110
+
111
+ | 档位 Description | i18n Key | 含义 |
112
+ |-----------------|----------|------|
113
+ | OFF / Off | `car_steering_wheel_hot_close` | 关闭 |
114
+ | Level1 / Level 1 | `car_steering_wheel_hot_first` | 一档 |
115
+ | Level2 / Level 2 | `car_steering_wheel_hot_second` | 二档 |
116
+ | Level3 / Level 3 | `car_steering_wheel_hot_third` | 三档 |
117
+
118
+ ### 示例
119
+
120
+ ```tsx
121
+ import { useSteeringWheelData } from '@miot-rn/car-component/dist/hooks/useSteeringWheelData';
122
+
123
+ const MyCustomSteeringWheel = ({ spec }: { spec: Spec }) => {
124
+ const {
125
+ steeringWheelTitle,
126
+ steeringWheelHeatState,
127
+ onSteeringWheelHotChange,
128
+ steeringWheelOptions,
129
+ } = useSteeringWheelData({
130
+ specBodySteeringWheelPropertiesSteeringWheelHeating: spec,
131
+ });
132
+
133
+ return (
134
+ <View>
135
+ <Text>{steeringWheelTitle}</Text>
136
+ {steeringWheelOptions.map(option => (
137
+ <TouchableOpacity
138
+ key={option.value}
139
+ onPress={() => onSteeringWheelHotChange(option.value)}
140
+ style={{
141
+ backgroundColor:
142
+ String(steeringWheelHeatState) === String(option.value)
143
+ ? 'orange' : 'gray',
144
+ }}
145
+ >
146
+ <Text>{option.label}</Text>
147
+ </TouchableOpacity>
148
+ ))}
149
+ </View>
150
+ );
151
+ };
152
+ ```
153
+
154
+ ---
155
+
156
+ ## 3. Component 用法(`SteeringWheelHotCard`)
157
+
158
+ 适用于已有数据源(如自行管理 spec 状态),仅需渲染方向盘加热 UI 的场景。
159
+
160
+ ### 引入
161
+
162
+ ```typescript
163
+ import { SteeringWheelHotCard } from '@miot-rn/car-component/dist/components/steeringWheelHotCard';
164
+ ```
165
+
166
+ ### Props
167
+
168
+ ```typescript
169
+ interface SteeringWheelHotCardProps {
170
+ value: string | number; // 当前选中档位值
171
+ onChange: (value: string | number) => void; // 档位变更回调
172
+ options?: OptionItem[]; // 档位选项列表,默认 []
173
+ disabled?: boolean; // 禁用状态,默认 false
174
+ steeringWheelTitle: string; // 标题文案
175
+ }
176
+
177
+ interface OptionItem {
178
+ value: string | number; // 档位值
179
+ colorType?: ColorType; // 选中态颜色类型,非 OFF 用 'orange'
180
+ label?: string; // 档位文案
181
+ description: string; // 档位描述(用于匹配图标)
182
+ }
183
+ ```
184
+
185
+ ### 渲染逻辑
186
+
187
+ - `options` 为空数组时返回 `null`(不渲染)
188
+ - 每个 option 根据 `description` 匹配方向盘加热图标(`SteeringWheelHot` / `FirstGear` / `SecondGear` / `ThirdGear`)
189
+ - 内部使用 `GroupContainer` > `CardContainer` > `FlatSelect` > `FlatOption` 结构
190
+ - 组件使用 `React.memo` 优化
191
+
192
+ ### 示例
193
+
194
+ ```tsx
195
+ import { SteeringWheelHotCard } from '@miot-rn/car-component/dist/components/steeringWheelHotCard';
196
+
197
+ <SteeringWheelHotCard
198
+ value={currentGear}
199
+ onChange={(val) => handleGearChange(val)}
200
+ steeringWheelTitle="方向盘加热"
201
+ disabled={false}
202
+ options={[
203
+ { value: 0, label: '关闭', description: 'OFF' },
204
+ { value: 1, label: '一档', description: 'Level1', colorType: 'orange' },
205
+ { value: 2, label: '二档', description: 'Level2', colorType: 'orange' },
206
+ { value: 3, label: '三档', description: 'Level3', colorType: 'orange' },
207
+ ]}
208
+ />
209
+ ```
210
+
211
+ ---
212
+
213
+ ## 已知问题
214
+
215
+ - Module 中存在 `@ts-ignore`:`steeringWheelOptions` 的类型与 `SteeringWheelHotCard` 的 `options` prop 类型不完全匹配。
216
+ - `steeringWheelHeatState` 为 string 类型,Module 中传入组件前需 `parseInt` 转换。
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import { type ConnectStatusValue } from '../../config/ConnectStatus';
3
+ import { Spec } from '../../types';
4
+ export interface SteeringWheelSpecs {
5
+ specBodySteeringWheelPropertiesSteeringWheelHeating?: Spec;
6
+ }
7
+ export interface SteeringWheelModuleProps {
8
+ specs: SteeringWheelSpecs;
9
+ connectStatus?: ConnectStatusValue;
10
+ isCarRunning: boolean;
11
+ }
12
+ export declare const SteeringWheelModule: ({ specs, connectStatus, isCarRunning }: SteeringWheelModuleProps) => React.JSX.Element;
13
+ export default SteeringWheelModule;
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+ import { SteeringWheelHotCard } from "../../components/steeringWheelHotCard";
3
+ import { useSteeringWheelData } from "../../hooks/useSteeringWheelData";
4
+ import { ConnectStatus } from "../../hooks";
5
+ export const SteeringWheelModule = ({
6
+ specs,
7
+ connectStatus,
8
+ isCarRunning
9
+ }) => {
10
+ const {
11
+ specBodySteeringWheelPropertiesSteeringWheelHeating
12
+ } = specs;
13
+ const {
14
+ steeringWheelTitle,
15
+ steeringWheelHeatState,
16
+ onSteeringWheelHotChange,
17
+ steeringWheelOptions
18
+ } = useSteeringWheelData({
19
+ specBodySteeringWheelPropertiesSteeringWheelHeating: specBodySteeringWheelPropertiesSteeringWheelHeating
20
+ });
21
+ return /*#__PURE__*/React.createElement(SteeringWheelHotCard, {
22
+ steeringWheelTitle: steeringWheelTitle,
23
+ disabled: connectStatus !== ConnectStatus.CONNECTED || isCarRunning,
24
+ value: Number.parseInt(steeringWheelHeatState, 10)
25
+ // @ts-ignore
26
+ ,
27
+ options: steeringWheelOptions,
28
+ onChange: onSteeringWheelHotChange
29
+ });
30
+ };
31
+ export default SteeringWheelModule;