@ledvance/base 1.3.108 → 1.3.110
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/localazy.json +2 -1
- package/package.json +1 -1
- package/src/components/AdvanceCard.tsx +6 -1
- package/src/components/AdvanceList.tsx +65 -44
- package/src/components/BallDirectionView.tsx +19 -17
- package/src/components/ColorAdjustView.tsx +44 -37
- package/src/components/ColorTempAdjustView.tsx +42 -41
- package/src/components/MoodColorsLine.tsx +33 -23
- package/src/components/ldvColorSlider.tsx +59 -45
- package/src/i18n/strings.ts +58 -28
- package/src/models/TuyaApi.ts +7 -6
- package/src/utils/index.ts +5 -4
- package/translateKey.txt +2 -1
package/localazy.json
CHANGED
|
@@ -1300,7 +1300,8 @@
|
|
|
1300
1300
|
"MATCH:country_BA",
|
|
1301
1301
|
"MATCH:country_north_macedonia",
|
|
1302
1302
|
"MATCH:country_werder_bremen",
|
|
1303
|
-
"MATCH:reset_energy"
|
|
1303
|
+
"MATCH:reset_energy",
|
|
1304
|
+
"MATCH:thermostat_infotempcurve"
|
|
1304
1305
|
],
|
|
1305
1306
|
"replacements": {
|
|
1306
1307
|
"REGEX:% %1\\$s.*?\\)%": "{0}",
|
package/package.json
CHANGED
|
@@ -44,15 +44,20 @@ export interface AdvanceCardProps extends PropsWithChildren<ViewProps> {
|
|
|
44
44
|
theme?: ThemeType
|
|
45
45
|
data: AdvancedData
|
|
46
46
|
onPress: () => void
|
|
47
|
+
width?: number
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
const AdvanceCard = (props: AdvanceCardProps) => {
|
|
50
51
|
const {statusColor} = props.data;
|
|
51
52
|
const subtitles = props.data.subtitles
|
|
52
53
|
const subtitleStyle = {...styles.subtitle, color: props.theme?.global.secondFontColor};
|
|
54
|
+
const containerStyle = [
|
|
55
|
+
styles.itemContainer,
|
|
56
|
+
props.width ? { width: props.width } : null
|
|
57
|
+
];
|
|
53
58
|
return (
|
|
54
59
|
<Card
|
|
55
|
-
style={
|
|
60
|
+
style={containerStyle}
|
|
56
61
|
containerStyle={styles.itemContent}
|
|
57
62
|
onPress={props.onPress}>
|
|
58
63
|
{!!statusColor && <View style={styles.dotBg}>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useIsPad } from '../models/modules/NativePropsSlice'
|
|
2
2
|
import { useNavigation } from '@react-navigation/core'
|
|
3
|
-
import React, { useCallback, useState } from 'react'
|
|
3
|
+
import React, { useCallback, useState } from 'react' // 移除 useMemo, Dimensions
|
|
4
4
|
import { FlatList, Image, StyleSheet, View } from 'react-native'
|
|
5
5
|
import { Utils } from 'tuya-panel-kit'
|
|
6
6
|
import { getMicrophoneAccess } from '../api/native'
|
|
@@ -8,8 +8,10 @@ import AdvanceCard, { AdvancedData } from './AdvanceCard'
|
|
|
8
8
|
import Spacer from './Spacer'
|
|
9
9
|
|
|
10
10
|
const { convertX: cx } = Utils.RatioUtils
|
|
11
|
+
// 移除 Dimensions 引用,不再需要获取屏幕宽度
|
|
11
12
|
|
|
12
13
|
const MusicRouterKey = ['ui_biz_music', 'group_ui_biz_music']
|
|
14
|
+
const CONTAINER_MARGIN = cx(14);
|
|
13
15
|
|
|
14
16
|
export interface AdvanceListProps {
|
|
15
17
|
advanceData?: AdvancedData[]
|
|
@@ -18,7 +20,7 @@ export interface AdvanceListProps {
|
|
|
18
20
|
function AdvanceList(props: AdvanceListProps) {
|
|
19
21
|
const navigation = useNavigation()
|
|
20
22
|
const isPad = useIsPad()
|
|
21
|
-
const [columns
|
|
23
|
+
const [columns] = useState(isPad ? 3 : 2)
|
|
22
24
|
|
|
23
25
|
const { advanceData = [] } = props
|
|
24
26
|
|
|
@@ -43,64 +45,57 @@ function AdvanceList(props: AdvanceListProps) {
|
|
|
43
45
|
)
|
|
44
46
|
|
|
45
47
|
const renderItem = useCallback(
|
|
46
|
-
({ item }: { item: AdvancedData; index: number }) =>
|
|
47
|
-
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
48
|
+
({ item }: { item: AdvancedData; index: number }) => {
|
|
49
|
+
return (
|
|
50
|
+
<View style={[
|
|
51
|
+
styles.itemWrapper,
|
|
52
|
+
{
|
|
53
|
+
// [核心逻辑]
|
|
54
|
+
// 1. 宽度设为百分比:2列就是 50%,3列就是 33.333%
|
|
55
|
+
width: `${100 / columns}%`
|
|
56
|
+
}
|
|
57
|
+
]}>
|
|
58
|
+
{/*
|
|
59
|
+
2. 传入 width="100%" 让卡片填满这个 Wrapper
|
|
60
|
+
Wrapper 的 paddingHorizontal 会自动把卡片往中间挤,形成边距
|
|
61
|
+
*/}
|
|
62
|
+
<AdvanceCard
|
|
63
|
+
data={item}
|
|
64
|
+
width="100%"
|
|
65
|
+
onPress={async () => {
|
|
66
|
+
await handleNavigate(item)
|
|
67
|
+
}}
|
|
68
|
+
>
|
|
69
|
+
{item.icons && (
|
|
70
|
+
<View style={styles.iconContainer} accessibilityLabel='AdvanceCard' accessibilityHint={item.title}>
|
|
71
|
+
<Image source={typeof item.icons === 'string' ? { uri: item.icons } : item.icons} style={styles.iconImage}/>
|
|
72
|
+
</View>
|
|
73
|
+
)}
|
|
74
|
+
</AdvanceCard>
|
|
75
|
+
</View>
|
|
76
|
+
)
|
|
77
|
+
},
|
|
78
|
+
[handleNavigate, columns] // 依赖 columns 变化
|
|
63
79
|
)
|
|
64
80
|
|
|
65
81
|
const keyExtractor = useCallback((item: AdvancedData, index: number) => {
|
|
66
82
|
return item.dp?.code ?? `key-${index}`
|
|
67
83
|
}, [])
|
|
68
84
|
|
|
69
|
-
// 改为普通函数组件提升性能
|
|
70
85
|
const Header = () => <Spacer height={cx(10)}/>
|
|
71
86
|
const Separator = () => <Spacer/>
|
|
87
|
+
// 注意:Separator 只控制行与行之间的垂直距离(如果 FlatList 支持的话),
|
|
88
|
+
// 但在多列布局中,最好直接在 itemWrapper 里控制 marginBottom
|
|
72
89
|
const Footer = () => <Spacer height={cx(30)}/>
|
|
73
90
|
|
|
74
|
-
const styles = StyleSheet.create({
|
|
75
|
-
container: {
|
|
76
|
-
marginHorizontal: cx(14),
|
|
77
|
-
},
|
|
78
|
-
columnContainer: {
|
|
79
|
-
justifyContent: 'space-between'
|
|
80
|
-
},
|
|
81
|
-
item: {
|
|
82
|
-
flex: 0,
|
|
83
|
-
marginHorizontal: cx(10),
|
|
84
|
-
alignItems: 'flex-start',
|
|
85
|
-
},
|
|
86
|
-
iconContainer: {
|
|
87
|
-
height: cx(80),
|
|
88
|
-
justifyContent: 'center' as const,
|
|
89
|
-
alignItems: 'center' as const,
|
|
90
|
-
},
|
|
91
|
-
iconImage: {
|
|
92
|
-
width: cx(50),
|
|
93
|
-
height: cx(50),
|
|
94
|
-
}
|
|
95
|
-
})
|
|
96
|
-
|
|
97
91
|
return (
|
|
98
92
|
<FlatList
|
|
99
93
|
key={`flatlist-columns-${columns}`}
|
|
100
94
|
scrollEnabled={false}
|
|
101
95
|
numColumns={columns}
|
|
102
96
|
style={styles.container}
|
|
103
|
-
columnWrapperStyle
|
|
97
|
+
// [修改] 移除 columnWrapperStyle 的 justifyContent
|
|
98
|
+
// 因为每个 item 都是精确的百分比宽度,它们会自动排满一行
|
|
104
99
|
data={advanceData}
|
|
105
100
|
renderItem={renderItem}
|
|
106
101
|
keyExtractor={keyExtractor}
|
|
@@ -111,5 +106,31 @@ function AdvanceList(props: AdvanceListProps) {
|
|
|
111
106
|
)
|
|
112
107
|
}
|
|
113
108
|
|
|
109
|
+
const styles = StyleSheet.create({
|
|
110
|
+
container: {
|
|
111
|
+
// 列表整体的左右边距 cx(14)
|
|
112
|
+
marginHorizontal: CONTAINER_MARGIN,
|
|
113
|
+
},
|
|
114
|
+
itemWrapper: {
|
|
115
|
+
// [关键] 使用 padding 代替 margin
|
|
116
|
+
// 这样 item 占据的空间依然是 50% 或 33%,但内容会向内缩进
|
|
117
|
+
paddingHorizontal: cx(10),
|
|
118
|
+
|
|
119
|
+
// 控制行间距
|
|
120
|
+
marginBottom: cx(12),
|
|
121
|
+
|
|
122
|
+
// 确保内容拉伸
|
|
123
|
+
alignItems: 'stretch',
|
|
124
|
+
},
|
|
125
|
+
iconContainer: {
|
|
126
|
+
height: cx(80),
|
|
127
|
+
justifyContent: 'center' as const,
|
|
128
|
+
alignItems: 'center' as const,
|
|
129
|
+
},
|
|
130
|
+
iconImage: {
|
|
131
|
+
width: cx(50),
|
|
132
|
+
height: cx(50),
|
|
133
|
+
}
|
|
134
|
+
})
|
|
114
135
|
|
|
115
136
|
export default AdvanceList
|
|
@@ -3,9 +3,10 @@ import React, { useEffect } from "react";
|
|
|
3
3
|
import { Image, StyleSheet, TouchableOpacity, View } from "react-native";
|
|
4
4
|
import res from "../res";
|
|
5
5
|
import { useReactive } from "ahooks";
|
|
6
|
-
import { hsv2Hex } from
|
|
6
|
+
import { hsv2Hex } from '@utils';
|
|
7
7
|
import { cctToColor } from "../utils/cctUtils";
|
|
8
8
|
import { AdjustType, HSV } from '../utils/interface'
|
|
9
|
+
import {useIsPad} from "../models/modules/NativePropsSlice"
|
|
9
10
|
|
|
10
11
|
const { withTheme } = Utils.ThemeUtils
|
|
11
12
|
const cx = Utils.RatioUtils.convertX;
|
|
@@ -29,6 +30,7 @@ interface BallDirectionProps {
|
|
|
29
30
|
|
|
30
31
|
const BallDirectionView = (props: BallDirectionProps) => {
|
|
31
32
|
const { theme, adjustType, paintMode, onPaintModeChanged, topColor, bottomColor, colorTemp, brightness } = props;
|
|
33
|
+
const isPad = useIsPad()
|
|
32
34
|
const state = useReactive({
|
|
33
35
|
adjustType: adjustType,
|
|
34
36
|
paintMode: paintMode,
|
|
@@ -116,30 +118,30 @@ const BallDirectionView = (props: BallDirectionProps) => {
|
|
|
116
118
|
width: '60%',
|
|
117
119
|
left: '20%',
|
|
118
120
|
right: '20%',
|
|
119
|
-
bottom: '11%',
|
|
121
|
+
bottom: isPad ? '16%' : '11%',
|
|
120
122
|
},
|
|
121
123
|
halfCircleUp: {
|
|
122
124
|
position: 'absolute',
|
|
123
125
|
width: '60%',
|
|
124
126
|
left: '20%',
|
|
125
127
|
right: '20%',
|
|
126
|
-
top: '11%',
|
|
128
|
+
top: isPad ? '16%' : '11%',
|
|
127
129
|
}
|
|
128
130
|
});
|
|
129
131
|
return (<View style={styles.root}>
|
|
130
132
|
<View style={styles.paintModeRoot}>
|
|
131
133
|
{state.adjustType === AdjustType.COLOUR &&
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
134
|
+
<TouchableOpacity
|
|
135
|
+
accessibilityLabel="HalfCircleButton"
|
|
136
|
+
accessibilityHint="HalfCircle"
|
|
137
|
+
accessibilityState={{ checked: [PaintMode.Top, PaintMode.Bottom].includes(state.paintMode) }}
|
|
138
|
+
style={{ width: cx(40), height: cx(40) }}
|
|
139
|
+
onPress={() => {
|
|
140
|
+
onPaintModeChanged(PaintMode.Top);
|
|
141
|
+
}}
|
|
142
|
+
>
|
|
143
|
+
<Image source={{ uri: res.half }} style={styles.paintModeHalf} />
|
|
144
|
+
</TouchableOpacity>}
|
|
143
145
|
<TouchableOpacity
|
|
144
146
|
accessibilityLabel="AllCircleButton"
|
|
145
147
|
accessibilityHint="AllCircle"
|
|
@@ -154,11 +156,11 @@ const BallDirectionView = (props: BallDirectionProps) => {
|
|
|
154
156
|
<View style={styles.circleLayout}>
|
|
155
157
|
<View style={styles.circleBorder} />
|
|
156
158
|
{state.paintMode === PaintMode.ALL &&
|
|
157
|
-
|
|
159
|
+
<Image source={{ uri: res.coloring }} style={styles.coloring} />}
|
|
158
160
|
{state.paintMode === PaintMode.Top &&
|
|
159
|
-
|
|
161
|
+
<Image source={{ uri: res.ringdown }} style={styles.ringUp} />}
|
|
160
162
|
{state.paintMode === PaintMode.Bottom &&
|
|
161
|
-
|
|
163
|
+
<Image source={{ uri: res.ringdown }} style={styles.ringDown} />}
|
|
162
164
|
<TouchableOpacity
|
|
163
165
|
accessibilityLabel="HalfCircle"
|
|
164
166
|
accessibilityHint="TopHalfCircle"
|
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { hex2Hsv, hsv2Hex } from '@utils'
|
|
2
|
+
import { useReactive, useUpdateEffect } from 'ahooks'
|
|
3
|
+
import React, { useCallback } from 'react'
|
|
4
|
+
import { StyleSheet, View } from 'react-native'
|
|
5
|
+
import { Utils } from 'tuya-panel-kit'
|
|
6
|
+
import I18n from '../i18n/index'
|
|
7
|
+
import { useNewPalette } from '../models/modules/NativePropsSlice'
|
|
8
|
+
import LdvColorBrightness from './ldvColorBrightness'
|
|
3
9
|
import LdvColorSlider from './ldvColorSlider'
|
|
4
|
-
import {hex2Hsv, hsv2Hex} from '@utils'
|
|
5
10
|
import LdvPresetView from './ldvPresetView'
|
|
6
11
|
import LdvSaturation from './ldvSaturation'
|
|
7
|
-
import LdvColorBrightness from './ldvColorBrightness'
|
|
8
|
-
import I18n from '../i18n/index'
|
|
9
12
|
import RectColorAndBrightPicker from './rect-color-and-bright-picker'
|
|
10
|
-
import
|
|
11
|
-
import {useReactive, useUpdateEffect} from "ahooks";
|
|
12
|
-
import {useNewPalette, useIsPad} from "../models/modules/NativePropsSlice";
|
|
13
|
+
import Spacer from './Spacer'
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
// 只引入 cx 用于尺寸转换
|
|
16
|
+
const { convertX: cx } = Utils.RatioUtils
|
|
15
17
|
const scaleUp = (value) => value * 10
|
|
16
18
|
const scaleDown = (value) => Math.round(value / 10)
|
|
17
19
|
|
|
18
20
|
export interface ColorAdjustViewProps {
|
|
19
|
-
h: number
|
|
20
|
-
s: number
|
|
21
|
-
v: number
|
|
22
|
-
minBrightness?: number
|
|
23
|
-
minSaturation?: number
|
|
24
|
-
reserveSV?: boolean
|
|
25
|
-
hideSat?: boolean
|
|
26
|
-
onHSVChange?: (h: number, s: number, v: number) => void
|
|
27
|
-
onHSVChangeComplete: (h: number, s: number, v: number) => void
|
|
21
|
+
h: number;
|
|
22
|
+
s: number;
|
|
23
|
+
v: number;
|
|
24
|
+
minBrightness?: number;
|
|
25
|
+
minSaturation?: number;
|
|
26
|
+
reserveSV?: boolean;
|
|
27
|
+
hideSat?: boolean;
|
|
28
|
+
onHSVChange?: (h: number, s: number, v: number) => void;
|
|
29
|
+
onHSVChangeComplete: (h: number, s: number, v: number) => void;
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
const NewColorPicker = React.memo((props: ColorAdjustViewProps) => {
|
|
31
33
|
const { h = 0, s = 100, v = 100, minBrightness, onHSVChange, onHSVChangeComplete } = props
|
|
32
|
-
|
|
33
|
-
const width = isPad ? cx(screenWidth - 10) : (screenWidth - 80)
|
|
34
|
+
|
|
34
35
|
const state = useReactive({
|
|
35
36
|
hue: h,
|
|
36
37
|
saturation: scaleUp(s),
|
|
37
38
|
value: scaleUp(v),
|
|
38
39
|
moving: false
|
|
39
40
|
})
|
|
40
|
-
|
|
41
41
|
useUpdateEffect(() => {
|
|
42
42
|
if (!state.moving) {
|
|
43
43
|
state.hue = h
|
|
@@ -45,33 +45,22 @@ const NewColorPicker = React.memo((props: ColorAdjustViewProps) => {
|
|
|
45
45
|
state.value = scaleUp(v)
|
|
46
46
|
}
|
|
47
47
|
}, [h, s, v])
|
|
48
|
-
|
|
49
48
|
const handleMove = useCallback((v) => {
|
|
50
49
|
onHSVChange?.(v.hue, scaleDown(v.saturation), scaleDown(v.value))
|
|
51
50
|
}, [onHSVChange])
|
|
52
|
-
|
|
53
51
|
const handleComplete = useCallback((v) => {
|
|
54
52
|
onHSVChangeComplete?.(v.hue, scaleDown(v.saturation), scaleDown(v.value))
|
|
55
53
|
state.moving = false
|
|
56
54
|
}, [onHSVChangeComplete])
|
|
57
|
-
|
|
58
|
-
const { hue, saturation, value }
|
|
59
|
-
const hsv = { hue, saturation, value };
|
|
55
|
+
const { hue, saturation, value } = state
|
|
56
|
+
const hsv = { hue, saturation, value }
|
|
60
57
|
const minBrightnessValue = minBrightness ?? 1
|
|
61
|
-
|
|
62
58
|
return (
|
|
63
|
-
<View style={
|
|
64
|
-
<View style={
|
|
65
|
-
width: width,
|
|
66
|
-
height: cx(200),
|
|
67
|
-
borderRadius: cx(10),
|
|
68
|
-
borderColor: '#eeeeef',
|
|
69
|
-
borderWidth: 1,
|
|
70
|
-
overflow: 'hidden'
|
|
71
|
-
}}>
|
|
59
|
+
<View style={styles.container}>
|
|
60
|
+
<View style={styles.pickerWrapper}>
|
|
72
61
|
<RectColorAndBrightPicker.ColourPicker
|
|
73
62
|
value={hsv}
|
|
74
|
-
brightOption={{min: scaleUp(minBrightnessValue), minPercent: minBrightnessValue ? minBrightnessValue : 0}}
|
|
63
|
+
brightOption={{ min: scaleUp(minBrightnessValue), minPercent: minBrightnessValue ? minBrightnessValue : 0 }}
|
|
75
64
|
onGrant={() => state.moving = true}
|
|
76
65
|
onMove={handleMove}
|
|
77
66
|
onRelease={handleComplete}
|
|
@@ -82,6 +71,23 @@ const NewColorPicker = React.memo((props: ColorAdjustViewProps) => {
|
|
|
82
71
|
)
|
|
83
72
|
})
|
|
84
73
|
|
|
74
|
+
const styles = StyleSheet.create({
|
|
75
|
+
container: {
|
|
76
|
+
// 为整个组件提供水平内边距,使其自适应
|
|
77
|
+
paddingHorizontal: cx(16),
|
|
78
|
+
},
|
|
79
|
+
pickerWrapper: {
|
|
80
|
+
// 高度保持不变
|
|
81
|
+
height: cx(200),
|
|
82
|
+
// 圆角、边框等样式保持不变
|
|
83
|
+
borderRadius: cx(10),
|
|
84
|
+
borderColor: '#eeeeef',
|
|
85
|
+
borderWidth: 1,
|
|
86
|
+
overflow: 'hidden',
|
|
87
|
+
// 这里不再需要 width 属性,它会自动填充父容器
|
|
88
|
+
},
|
|
89
|
+
})
|
|
90
|
+
|
|
85
91
|
const OldColorPicker = React.memo((props: ColorAdjustViewProps) => {
|
|
86
92
|
return (
|
|
87
93
|
<View>
|
|
@@ -96,6 +102,7 @@ const OldColorPicker = React.memo((props: ColorAdjustViewProps) => {
|
|
|
96
102
|
onSlidingComplete={hue => {
|
|
97
103
|
props.onHSVChangeComplete(hue, props.s, props.v)
|
|
98
104
|
}}/>
|
|
105
|
+
<Spacer height={cx(10)}/>
|
|
99
106
|
<LdvPresetView
|
|
100
107
|
type={'color'}
|
|
101
108
|
onPress={(item) => {
|
|
@@ -1,31 +1,30 @@
|
|
|
1
|
-
import {View} from 'react-native'
|
|
2
|
-
import React, {useCallback} from 'react'
|
|
1
|
+
import { StyleSheet, View } from 'react-native'
|
|
2
|
+
import React, { useCallback } from 'react'
|
|
3
3
|
import LdvColorSlider from './ldvColorSlider'
|
|
4
4
|
import Spacer from './Spacer'
|
|
5
5
|
import LdvPresetView from './ldvPresetView'
|
|
6
6
|
import LdvSlider from './ldvSlider'
|
|
7
|
-
import {Utils} from 'tuya-panel-kit'
|
|
7
|
+
import { Utils } from 'tuya-panel-kit'
|
|
8
8
|
import I18n from '../i18n/index'
|
|
9
|
-
import {cctToColor} from '../utils/cctUtils'
|
|
10
|
-
import RectColorAndBrightPicker from
|
|
11
|
-
import {useReactive, useUpdateEffect} from 'ahooks'
|
|
12
|
-
import { useNewPalette
|
|
9
|
+
import { cctToColor } from '../utils/cctUtils'
|
|
10
|
+
import RectColorAndBrightPicker from './rect-color-and-bright-picker'
|
|
11
|
+
import { useReactive, useUpdateEffect } from 'ahooks'
|
|
12
|
+
import { useNewPalette } from 'models/modules/NativePropsSlice'
|
|
13
13
|
|
|
14
|
-
const {convertX: cx
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
const scaleDown = (value: number) => Math.round(value / 10);
|
|
14
|
+
const { convertX: cx } = Utils.RatioUtils
|
|
15
|
+
const scaleUp = (value: number) => value * 10
|
|
16
|
+
const scaleDown = (value: number) => Math.round(value / 10)
|
|
18
17
|
|
|
19
18
|
export interface ColorTempAdjustViewProps {
|
|
20
|
-
colorTemp: number
|
|
21
|
-
brightness: number
|
|
22
|
-
minBrightness?: number
|
|
23
|
-
isSupportTemperature: boolean
|
|
24
|
-
isSupportBrightness: boolean
|
|
25
|
-
onCCTChange?: (cct: number) => void
|
|
26
|
-
onCCTChangeComplete: (cct: number) => void
|
|
27
|
-
onBrightnessChange?: (brightness: number) => void
|
|
28
|
-
onBrightnessChangeComplete: (brightness: number) => void
|
|
19
|
+
colorTemp: number;
|
|
20
|
+
brightness: number;
|
|
21
|
+
minBrightness?: number;
|
|
22
|
+
isSupportTemperature: boolean;
|
|
23
|
+
isSupportBrightness: boolean;
|
|
24
|
+
onCCTChange?: (cct: number) => void;
|
|
25
|
+
onCCTChangeComplete: (cct: number) => void;
|
|
26
|
+
onBrightnessChange?: (brightness: number) => void;
|
|
27
|
+
onBrightnessChangeComplete: (brightness: number) => void;
|
|
29
28
|
}
|
|
30
29
|
|
|
31
30
|
const NewColorTempPicker = React.memo((props: ColorTempAdjustViewProps) => {
|
|
@@ -40,18 +39,14 @@ const NewColorTempPicker = React.memo((props: ColorTempAdjustViewProps) => {
|
|
|
40
39
|
onBrightnessChange,
|
|
41
40
|
onBrightnessChangeComplete,
|
|
42
41
|
} = props
|
|
43
|
-
|
|
44
|
-
const width = isPad ? cx(screenWidth - 10) : (screenWidth - 80)
|
|
42
|
+
|
|
45
43
|
const state = useReactive({
|
|
46
44
|
temperature: scaleUp(colorTemp),
|
|
47
45
|
brightness: scaleUp(brightness),
|
|
48
|
-
moving: false
|
|
46
|
+
moving: false,
|
|
49
47
|
})
|
|
50
|
-
|
|
51
48
|
useUpdateEffect(() => {
|
|
52
49
|
if (!state.moving) {
|
|
53
|
-
// 外部props更新时同步内部状态
|
|
54
|
-
|
|
55
50
|
state.temperature = scaleUp(colorTemp)
|
|
56
51
|
state.brightness = scaleUp(brightness)
|
|
57
52
|
}
|
|
@@ -86,27 +81,21 @@ const NewColorTempPicker = React.memo((props: ColorTempAdjustViewProps) => {
|
|
|
86
81
|
const { temperature, brightness: stateBrightness } = state
|
|
87
82
|
const white = { temperature, brightness: stateBrightness }
|
|
88
83
|
const minBrightnessValue = minBrightness ?? 1
|
|
89
|
-
|
|
84
|
+
|
|
85
|
+
const height = cx(isSupportTemperature ? 200 : (isSupportBrightness ? 45 : 0))
|
|
90
86
|
const borderWidth = (isSupportTemperature || isSupportBrightness) ? 1 : 0
|
|
91
87
|
return (
|
|
92
|
-
<View style={
|
|
93
|
-
<View style={{
|
|
94
|
-
width: width,
|
|
95
|
-
height: height,
|
|
96
|
-
borderRadius: cx(10),
|
|
97
|
-
borderColor: '#eeeeef',
|
|
98
|
-
borderWidth: borderWidth,
|
|
99
|
-
overflow: 'hidden'
|
|
100
|
-
}}>
|
|
88
|
+
<View style={styles.container}>
|
|
89
|
+
<View style={[styles.pickerWrapper, { height, borderWidth }]}>
|
|
101
90
|
{
|
|
102
91
|
isSupportTemperature ? <RectColorAndBrightPicker.WhitePicker
|
|
103
92
|
value={white}
|
|
104
|
-
brightOption={{min: scaleUp(minBrightnessValue), minPercent: minBrightnessValue ? minBrightnessValue : 0}}
|
|
93
|
+
brightOption={{ min: scaleUp(minBrightnessValue), minPercent: minBrightnessValue ? minBrightnessValue : 0 }}
|
|
105
94
|
onGrant={() => state.moving = true}
|
|
106
95
|
onMove={handleMove}
|
|
107
96
|
onRelease={handleComplete}
|
|
108
97
|
onPress={handleComplete}
|
|
109
|
-
/> :
|
|
98
|
+
/> : isSupportBrightness ? <RectColorAndBrightPicker.BrightnessSlider
|
|
110
99
|
value={stateBrightness}
|
|
111
100
|
min={scaleUp(minBrightnessValue)}
|
|
112
101
|
minPercent={minBrightnessValue ? minBrightnessValue : 0}
|
|
@@ -115,14 +104,26 @@ const NewColorTempPicker = React.memo((props: ColorTempAdjustViewProps) => {
|
|
|
115
104
|
onMove={handleBrightnessMove}
|
|
116
105
|
onRelease={handleBrightnessComplete}
|
|
117
106
|
onPress={handleBrightnessComplete}
|
|
118
|
-
/> : <></>
|
|
107
|
+
/> : null // 使用 null 代替 <></> 更为标准
|
|
119
108
|
}
|
|
120
|
-
|
|
121
109
|
</View>
|
|
122
110
|
</View>
|
|
123
111
|
)
|
|
124
112
|
})
|
|
125
113
|
|
|
114
|
+
const styles = StyleSheet.create({
|
|
115
|
+
container: {
|
|
116
|
+
// 定义水平内边距,让组件自适应
|
|
117
|
+
paddingHorizontal: cx(16),
|
|
118
|
+
},
|
|
119
|
+
pickerWrapper: {
|
|
120
|
+
// 定义基础样式,移除 width
|
|
121
|
+
borderRadius: cx(10),
|
|
122
|
+
borderColor: '#eeeeef',
|
|
123
|
+
overflow: 'hidden',
|
|
124
|
+
},
|
|
125
|
+
})
|
|
126
|
+
|
|
126
127
|
const OldColorTempPicker = React.memo((props: ColorTempAdjustViewProps) => {
|
|
127
128
|
return (
|
|
128
129
|
<View>
|
|
@@ -138,7 +139,7 @@ const OldColorTempPicker = React.memo((props: ColorTempAdjustViewProps) => {
|
|
|
138
139
|
<Spacer height={cx(10)}/>
|
|
139
140
|
<LdvPresetView
|
|
140
141
|
type={'temperature'}
|
|
141
|
-
style={{height: cx(60)}}
|
|
142
|
+
style={{ height: cx(60) }}
|
|
142
143
|
onPress={item => {
|
|
143
144
|
props.onCCTChangeComplete(item.value)
|
|
144
145
|
}}/>
|
|
@@ -1,36 +1,46 @@
|
|
|
1
|
-
|
|
2
|
-
import React from 'react'
|
|
3
|
-
import {Utils} from 'tuya-panel-kit'
|
|
4
|
-
import {StyleProp, StyleSheet, ViewStyle} from 'react-native'
|
|
5
|
-
import ColorsLine from './ColorsLine'
|
|
6
|
-
import {useIsPad} from '../models/modules/NativePropsSlice'
|
|
1
|
+
// MoodColorsLine.tsx (接收显式 width 的版本)
|
|
7
2
|
|
|
8
|
-
|
|
3
|
+
import LinearGradientLine from './LinearGradientLine';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { Utils } from 'tuya-panel-kit';
|
|
6
|
+
import { StyleProp, StyleSheet, ViewStyle } from 'react-native';
|
|
7
|
+
import ColorsLine from './ColorsLine';
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
const { convertX: cx } = Utils.RatioUtils;
|
|
10
|
+
|
|
11
|
+
export type MoodColorsLineType = 'gradient' | 'separate';
|
|
11
12
|
|
|
12
13
|
interface MoodColorsLineProps {
|
|
13
|
-
width
|
|
14
|
-
height?: number
|
|
15
|
-
type: MoodColorsLineType
|
|
16
|
-
colors: string[]
|
|
17
|
-
nodeStyle?: StyleProp<ViewStyle
|
|
14
|
+
width: number; // 【关键】: 明确要求一个数字类型的 width
|
|
15
|
+
height?: number;
|
|
16
|
+
type: MoodColorsLineType;
|
|
17
|
+
colors: string[];
|
|
18
|
+
nodeStyle?: StyleProp<ViewStyle>;
|
|
19
|
+
style?: StyleProp<ViewStyle>; // style prop 仍然保留,以备不时之需
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
export default function MoodColorsLine(props: MoodColorsLineProps) {
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
const { width, type, colors, nodeStyle, style } = props;
|
|
24
|
+
const height = props.height || cx(24);
|
|
25
|
+
|
|
26
|
+
// 子组件现在使用明确传入的数字 width
|
|
27
|
+
if (type === 'separate' || colors.length < 2) {
|
|
28
|
+
return (
|
|
29
|
+
<ColorsLine
|
|
30
|
+
colors={colors}
|
|
31
|
+
style={[{ width, height }, style]} // 将数字 width 和 height 应用到 style
|
|
32
|
+
nodeStyle={nodeStyle}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
26
35
|
} else {
|
|
27
36
|
return (
|
|
28
37
|
<LinearGradientLine
|
|
29
|
-
width={width}
|
|
38
|
+
width={width} // 将数字 width 作为 prop 传递
|
|
30
39
|
height={height}
|
|
31
|
-
style={styles.gradient}
|
|
32
|
-
colors={
|
|
33
|
-
|
|
40
|
+
style={[styles.gradient, style]}
|
|
41
|
+
colors={colors}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
34
44
|
}
|
|
35
45
|
}
|
|
36
46
|
|
|
@@ -38,4 +48,4 @@ const styles = StyleSheet.create({
|
|
|
38
48
|
gradient: {
|
|
39
49
|
borderRadius: cx(8),
|
|
40
50
|
},
|
|
41
|
-
})
|
|
51
|
+
});
|