@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.
Files changed (37) hide show
  1. package/README.md +1 -1
  2. package/dist/elements.js +4590 -4441
  3. package/dist/elements.js.map +1 -1
  4. package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.js +14 -2
  5. package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.js.map +1 -1
  6. package/lib/seam/connect-webviews/use-create-connect-webview.js +10 -1
  7. package/lib/seam/connect-webviews/use-create-connect-webview.js.map +1 -1
  8. package/lib/seam/thermostats/use-update-fan-mode.js +2 -2
  9. package/lib/seam/thermostats/use-update-fan-mode.js.map +1 -1
  10. package/lib/set-point-bounds.d.ts +4 -0
  11. package/lib/set-point-bounds.js +24 -0
  12. package/lib/set-point-bounds.js.map +1 -0
  13. package/lib/temperature-bounds.d.ts +2 -2
  14. package/lib/temperature-bounds.js +4 -6
  15. package/lib/temperature-bounds.js.map +1 -1
  16. package/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormClimateSetting.js +11 -4
  17. package/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormClimateSetting.js.map +1 -1
  18. package/lib/ui/Snackbar/Snackbar.d.ts +2 -1
  19. package/lib/ui/Snackbar/Snackbar.js +14 -6
  20. package/lib/ui/Snackbar/Snackbar.js.map +1 -1
  21. package/lib/ui/thermostat/FanModeMenu.js +1 -1
  22. package/lib/ui/thermostat/FanModeMenu.js.map +1 -1
  23. package/lib/ui/thermostat/TemperatureControlGroup.js +4 -1
  24. package/lib/ui/thermostat/TemperatureControlGroup.js.map +1 -1
  25. package/lib/version.d.ts +1 -1
  26. package/lib/version.js +1 -1
  27. package/package.json +1 -1
  28. package/src/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.tsx +34 -0
  29. package/src/lib/seam/connect-webviews/use-create-connect-webview.ts +10 -1
  30. package/src/lib/seam/thermostats/use-update-fan-mode.ts +2 -2
  31. package/src/lib/set-point-bounds.ts +39 -0
  32. package/src/lib/temperature-bounds.ts +4 -12
  33. package/src/lib/ui/ClimateSettingForm/ClimateSettingScheduleFormClimateSetting.tsx +14 -2
  34. package/src/lib/ui/Snackbar/Snackbar.tsx +18 -5
  35. package/src/lib/ui/thermostat/FanModeMenu.tsx +1 -2
  36. package/src/lib/ui/thermostat/TemperatureControlGroup.tsx +8 -4
  37. 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
- const actualMinHeat =
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: actualMaxCool }
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({ control }: FormContentProps): JSX.Element {
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
- onClose()
55
+ handleClose()
43
56
  }, dismissAfterMs)
44
57
 
45
58
  return () => {
46
59
  globalThis.clearTimeout(timeout)
47
60
  }
48
- }, [autoDismiss, dismissAfterMs, onClose])
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
- onClose()
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
- verticalOffset={-180}
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
  )}
@@ -1,3 +1,3 @@
1
- const seamapiReactVersion = '2.1.4'
1
+ const seamapiReactVersion = '2.3.0'
2
2
 
3
3
  export default seamapiReactVersion