@seamapi/react 2.1.4 → 2.3.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/README.md +1 -1
- package/dist/elements.js +4590 -4441
- package/dist/elements.js.map +1 -1
- package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.js +14 -2
- package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.js.map +1 -1
- package/lib/seam/connect-webviews/use-create-connect-webview.js +10 -1
- package/lib/seam/connect-webviews/use-create-connect-webview.js.map +1 -1
- package/lib/seam/thermostats/use-update-fan-mode.js +2 -2
- package/lib/seam/thermostats/use-update-fan-mode.js.map +1 -1
- package/lib/set-point-bounds.d.ts +4 -0
- package/lib/set-point-bounds.js +24 -0
- package/lib/set-point-bounds.js.map +1 -0
- package/lib/temperature-bounds.d.ts +2 -2
- package/lib/temperature-bounds.js +4 -6
- package/lib/temperature-bounds.js.map +1 -1
- package/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormClimateSetting.js +11 -4
- package/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormClimateSetting.js.map +1 -1
- package/lib/ui/Snackbar/Snackbar.d.ts +2 -1
- package/lib/ui/Snackbar/Snackbar.js +14 -6
- package/lib/ui/Snackbar/Snackbar.js.map +1 -1
- package/lib/ui/thermostat/FanModeMenu.js +1 -1
- package/lib/ui/thermostat/FanModeMenu.js.map +1 -1
- package/lib/ui/thermostat/TemperatureControlGroup.js +4 -1
- package/lib/ui/thermostat/TemperatureControlGroup.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +1 -1
- package/src/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.tsx +34 -0
- package/src/lib/seam/connect-webviews/use-create-connect-webview.ts +10 -1
- package/src/lib/seam/thermostats/use-update-fan-mode.ts +2 -2
- package/src/lib/set-point-bounds.ts +39 -0
- package/src/lib/temperature-bounds.ts +4 -12
- package/src/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormClimateSetting.tsx +14 -2
- package/src/lib/ui/Snackbar/Snackbar.tsx +18 -5
- package/src/lib/ui/thermostat/FanModeMenu.tsx +1 -2
- package/src/lib/ui/thermostat/TemperatureControlGroup.tsx +8 -4
- package/src/lib/version.ts +1 -1
|
@@ -23,34 +23,26 @@ export const getHeatBounds = ({
|
|
|
23
23
|
mode,
|
|
24
24
|
minHeat,
|
|
25
25
|
maxHeat,
|
|
26
|
-
minCool,
|
|
27
26
|
maxCool,
|
|
28
27
|
delta,
|
|
29
|
-
}: ControlBounds): MinMax => {
|
|
28
|
+
}: Omit<ControlBounds, 'minCool'>): MinMax => {
|
|
30
29
|
const actualMaxHeat =
|
|
31
30
|
mode === 'heat_cool' ? Math.min(maxHeat - delta, maxCool - delta) : maxHeat
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
mode === 'heat_cool' ? Math.max(minHeat, minCool) : minHeat
|
|
35
|
-
|
|
36
|
-
return { min: actualMinHeat, max: actualMaxHeat }
|
|
32
|
+
return { min: minHeat, max: actualMaxHeat }
|
|
37
33
|
}
|
|
38
34
|
|
|
39
35
|
export const getCoolBounds = ({
|
|
40
36
|
mode,
|
|
41
37
|
minHeat,
|
|
42
|
-
maxHeat,
|
|
43
38
|
minCool,
|
|
44
39
|
maxCool,
|
|
45
40
|
delta,
|
|
46
|
-
}: ControlBounds): MinMax => {
|
|
47
|
-
const actualMaxCool =
|
|
48
|
-
mode === 'heat_cool' ? Math.min(maxCool, maxHeat) : maxCool
|
|
49
|
-
|
|
41
|
+
}: Omit<ControlBounds, 'maxHeat'>): MinMax => {
|
|
50
42
|
const actualMinCool =
|
|
51
43
|
mode === 'heat_cool' ? Math.max(minCool + delta, minHeat + delta) : minCool
|
|
52
44
|
|
|
53
|
-
return { min: actualMinCool, max:
|
|
45
|
+
return { min: actualMinCool, max: maxCool }
|
|
54
46
|
}
|
|
55
47
|
|
|
56
48
|
export const getTemperatureBounds = (
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type Control, Controller } from 'react-hook-form'
|
|
2
|
+
import { isThermostatDevice } from 'seamapi'
|
|
2
3
|
|
|
3
4
|
import { useDevice } from 'lib/seam/devices/use-device.js'
|
|
5
|
+
import { getSetPointBounds, type SetPointBounds } from 'lib/set-point-bounds.js'
|
|
4
6
|
import { Button } from 'lib/ui/Button.js'
|
|
5
7
|
import type { ClimateSettingScheduleFormFields } from 'lib/ui/ClimateSettingForm/ClimateSettingScheduleForm.js'
|
|
6
8
|
import { FormField } from 'lib/ui/FormField.js'
|
|
@@ -29,6 +31,11 @@ export function ClimateSettingScheduleFormClimateSetting({
|
|
|
29
31
|
device_id: deviceId,
|
|
30
32
|
})
|
|
31
33
|
|
|
34
|
+
if (device == null) return <></>
|
|
35
|
+
if (!isThermostatDevice(device)) return <></>
|
|
36
|
+
|
|
37
|
+
const setPointBounds = getSetPointBounds(device.properties)
|
|
38
|
+
|
|
32
39
|
return (
|
|
33
40
|
<>
|
|
34
41
|
<ContentHeader
|
|
@@ -43,7 +50,7 @@ export function ClimateSettingScheduleFormClimateSetting({
|
|
|
43
50
|
<InputLabel>{t.climateSetting}</InputLabel>
|
|
44
51
|
<span className='seam-label'>{t.climateSettingSubHeading}</span>
|
|
45
52
|
</div>
|
|
46
|
-
<FormContent control={control} />
|
|
53
|
+
<FormContent control={control} setPointBounds={setPointBounds} />
|
|
47
54
|
</div>
|
|
48
55
|
</div>
|
|
49
56
|
<div className='seam-actions'>
|
|
@@ -59,9 +66,13 @@ export function ClimateSettingScheduleFormClimateSetting({
|
|
|
59
66
|
|
|
60
67
|
interface FormContentProps {
|
|
61
68
|
control: Control<ClimateSettingScheduleFormFields>
|
|
69
|
+
setPointBounds: SetPointBounds
|
|
62
70
|
}
|
|
63
71
|
|
|
64
|
-
function FormContent({
|
|
72
|
+
function FormContent({
|
|
73
|
+
control,
|
|
74
|
+
setPointBounds,
|
|
75
|
+
}: FormContentProps): JSX.Element {
|
|
65
76
|
return (
|
|
66
77
|
<FormField>
|
|
67
78
|
<Controller
|
|
@@ -75,6 +86,7 @@ function FormContent({ control }: FormContentProps): JSX.Element {
|
|
|
75
86
|
}}
|
|
76
87
|
coolValue={value.coolingSetPoint}
|
|
77
88
|
heatValue={value.heatingSetPoint}
|
|
89
|
+
{...setPointBounds}
|
|
78
90
|
onCoolValueChange={(coolingSetPoint) => {
|
|
79
91
|
onChange({
|
|
80
92
|
...value,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import classNames from 'classnames'
|
|
2
|
-
import { useEffect } from 'react'
|
|
2
|
+
import { useCallback, useEffect, useState } from 'react'
|
|
3
3
|
|
|
4
4
|
import { CheckGreenIcon } from 'lib/icons/CheckGreen.js'
|
|
5
5
|
import { CloseWhiteIcon } from 'lib/icons/CloseWhite.js'
|
|
@@ -19,6 +19,7 @@ interface SnackbarProps {
|
|
|
19
19
|
autoDismiss?: boolean
|
|
20
20
|
dismissAfterMs?: number
|
|
21
21
|
disableCloseButton?: boolean
|
|
22
|
+
automaticVisibility?: boolean
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
export function Snackbar({
|
|
@@ -29,29 +30,41 @@ export function Snackbar({
|
|
|
29
30
|
autoDismiss = false,
|
|
30
31
|
dismissAfterMs = 5000,
|
|
31
32
|
disableCloseButton = false,
|
|
33
|
+
automaticVisibility = false,
|
|
32
34
|
onClose = () => {},
|
|
33
35
|
}: SnackbarProps): JSX.Element {
|
|
36
|
+
const [hidden, setHidden] = useState(visible)
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
setHidden(!visible)
|
|
40
|
+
}, [visible, setHidden])
|
|
41
|
+
|
|
34
42
|
const { label: actionLabel, onClick: handleActionClick } = action ?? {}
|
|
35
43
|
|
|
44
|
+
const handleClose = useCallback(() => {
|
|
45
|
+
setHidden(true)
|
|
46
|
+
onClose()
|
|
47
|
+
}, [onClose, setHidden])
|
|
48
|
+
|
|
36
49
|
useEffect(() => {
|
|
37
50
|
if (!autoDismiss) {
|
|
38
51
|
return () => {}
|
|
39
52
|
}
|
|
40
53
|
|
|
41
54
|
const timeout = globalThis.setTimeout(() => {
|
|
42
|
-
|
|
55
|
+
handleClose()
|
|
43
56
|
}, dismissAfterMs)
|
|
44
57
|
|
|
45
58
|
return () => {
|
|
46
59
|
globalThis.clearTimeout(timeout)
|
|
47
60
|
}
|
|
48
|
-
}, [autoDismiss, dismissAfterMs,
|
|
61
|
+
}, [autoDismiss, dismissAfterMs, handleClose])
|
|
49
62
|
|
|
50
63
|
return (
|
|
51
64
|
<div className='seam-snackbar-wrap'>
|
|
52
65
|
<div
|
|
53
66
|
className={classNames('seam-snackbar', {
|
|
54
|
-
'seam-snackbar-visible': visible,
|
|
67
|
+
'seam-snackbar-visible': automaticVisibility ? !hidden : visible,
|
|
55
68
|
})}
|
|
56
69
|
>
|
|
57
70
|
<SnackbarIcon variant={variant} />
|
|
@@ -71,7 +84,7 @@ export function Snackbar({
|
|
|
71
84
|
<button
|
|
72
85
|
className='seam-snackbar-close-button'
|
|
73
86
|
onClick={() => {
|
|
74
|
-
|
|
87
|
+
handleClose()
|
|
75
88
|
}}
|
|
76
89
|
>
|
|
77
90
|
<CloseWhiteIcon />
|
|
@@ -27,8 +27,7 @@ export function FanModeMenu({ mode, onChange }: FanModeMenuProps): JSX.Element {
|
|
|
27
27
|
<ChevronDownIcon />
|
|
28
28
|
</button>
|
|
29
29
|
)}
|
|
30
|
-
|
|
31
|
-
horizontalOffset={-32}
|
|
30
|
+
horizontalOffset={-20}
|
|
32
31
|
backgroundProps={{
|
|
33
32
|
className: 'seam-thermo-mode-menu',
|
|
34
33
|
}}
|
|
@@ -130,6 +130,10 @@ export function TemperatureControlGroup({
|
|
|
130
130
|
onCoolValueChange,
|
|
131
131
|
])
|
|
132
132
|
|
|
133
|
+
// This is done so that both sliders are operating on the same range of numbers
|
|
134
|
+
const heatCoolSliderMin = Math.min(minCool, minHeat)
|
|
135
|
+
const heatCoolSliderMax = Math.max(maxCool, maxHeat)
|
|
136
|
+
|
|
133
137
|
return (
|
|
134
138
|
<div className='seam-temperature-control-group'>
|
|
135
139
|
{showHeat && (
|
|
@@ -139,8 +143,8 @@ export function TemperatureControlGroup({
|
|
|
139
143
|
variant='heat'
|
|
140
144
|
value={heatValue}
|
|
141
145
|
onChange={adjustHeat}
|
|
142
|
-
min={minHeat}
|
|
143
|
-
max={maxHeat}
|
|
146
|
+
min={mode === 'heat_cool' ? heatCoolSliderMin : minHeat}
|
|
147
|
+
max={mode === 'heat_cool' ? heatCoolSliderMax : maxHeat}
|
|
144
148
|
/>
|
|
145
149
|
</div>
|
|
146
150
|
)}
|
|
@@ -152,8 +156,8 @@ export function TemperatureControlGroup({
|
|
|
152
156
|
variant='cool'
|
|
153
157
|
value={coolValue}
|
|
154
158
|
onChange={adjustCool}
|
|
155
|
-
min={minCool}
|
|
156
|
-
max={maxCool}
|
|
159
|
+
min={mode === 'heat_cool' ? heatCoolSliderMin : minCool}
|
|
160
|
+
max={mode === 'heat_cool' ? heatCoolSliderMax : maxCool}
|
|
157
161
|
/>
|
|
158
162
|
</div>
|
|
159
163
|
)}
|
package/src/lib/version.ts
CHANGED