@seamapi/react 2.8.7 → 2.10.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 (65) hide show
  1. package/README.md +2 -2
  2. package/dist/elements.js +7998 -7317
  3. package/dist/elements.js.map +1 -1
  4. package/dist/index.css +31 -2
  5. package/dist/index.css.map +1 -1
  6. package/dist/index.min.css +1 -1
  7. package/dist/index.min.css.map +1 -1
  8. package/lib/debounce.d.ts +6 -0
  9. package/lib/debounce.js +20 -0
  10. package/lib/debounce.js.map +1 -0
  11. package/lib/seam/components/AccessCodeDetails/AccessCodeDetails.d.ts +1 -1
  12. package/lib/seam/components/AccessCodeDetails/AccessCodeDetails.js +2 -2
  13. package/lib/seam/components/AccessCodeDetails/AccessCodeDetails.js.map +1 -1
  14. package/lib/seam/components/AccessCodeTable/AccessCodeTable.d.ts +1 -1
  15. package/lib/seam/components/AccessCodeTable/AccessCodeTable.js +4 -4
  16. package/lib/seam/components/AccessCodeTable/AccessCodeTable.js.map +1 -1
  17. package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.d.ts +1 -1
  18. package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.js +2 -2
  19. package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.js.map +1 -1
  20. package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.d.ts +1 -1
  21. package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.js +2 -2
  22. package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.js.map +1 -1
  23. package/lib/seam/components/DeviceDetails/DeviceDetails.d.ts +1 -1
  24. package/lib/seam/components/DeviceDetails/DeviceDetails.js +2 -1
  25. package/lib/seam/components/DeviceDetails/DeviceDetails.js.map +1 -1
  26. package/lib/seam/components/DeviceDetails/LockDeviceDetails.js +2 -2
  27. package/lib/seam/components/DeviceDetails/LockDeviceDetails.js.map +1 -1
  28. package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.d.ts +1 -1
  29. package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.js +99 -5
  30. package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.js.map +1 -1
  31. package/lib/seam/components/DeviceTable/DeviceTable.d.ts +1 -1
  32. package/lib/seam/components/DeviceTable/DeviceTable.js +2 -2
  33. package/lib/seam/components/DeviceTable/DeviceTable.js.map +1 -1
  34. package/lib/seam/components/common-props.d.ts +1 -0
  35. package/lib/seam/components/common-props.js.map +1 -1
  36. package/lib/temperature-bounds.d.ts +2 -1
  37. package/lib/temperature-bounds.js +16 -0
  38. package/lib/temperature-bounds.js.map +1 -1
  39. package/lib/ui/layout/AccordionRow.d.ts +2 -1
  40. package/lib/ui/layout/AccordionRow.js +2 -2
  41. package/lib/ui/layout/AccordionRow.js.map +1 -1
  42. package/lib/ui/thermostat/ClimateModeMenu.d.ts +2 -1
  43. package/lib/ui/thermostat/ClimateModeMenu.js +2 -3
  44. package/lib/ui/thermostat/ClimateModeMenu.js.map +1 -1
  45. package/lib/version.d.ts +1 -1
  46. package/lib/version.js +1 -1
  47. package/lib/version.js.map +1 -1
  48. package/package.json +3 -3
  49. package/src/lib/debounce.ts +33 -0
  50. package/src/lib/element.tsx +1 -0
  51. package/src/lib/seam/components/AccessCodeDetails/AccessCodeDetails.tsx +2 -0
  52. package/src/lib/seam/components/AccessCodeTable/AccessCodeTable.tsx +4 -0
  53. package/src/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.tsx +2 -0
  54. package/src/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.tsx +2 -0
  55. package/src/lib/seam/components/DeviceDetails/DeviceDetails.tsx +3 -1
  56. package/src/lib/seam/components/DeviceDetails/LockDeviceDetails.tsx +2 -0
  57. package/src/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.tsx +222 -26
  58. package/src/lib/seam/components/DeviceTable/DeviceTable.tsx +2 -0
  59. package/src/lib/seam/components/common-props.tsx +1 -0
  60. package/src/lib/temperature-bounds.ts +23 -1
  61. package/src/lib/ui/layout/AccordionRow.tsx +6 -1
  62. package/src/lib/ui/thermostat/ClimateModeMenu.tsx +3 -3
  63. package/src/lib/version.ts +1 -1
  64. package/src/styles/_layout.scss +13 -2
  65. package/src/styles/_thermostat.scss +26 -0
@@ -1,4 +1,4 @@
1
- import type { HvacModeSetting } from 'seamapi';
1
+ import type { HvacModeSetting, ThermostatDevice } from 'seamapi';
2
2
  export interface ControlBounds {
3
3
  mode: Exclude<HvacModeSetting, 'off'>;
4
4
  minHeat: number;
@@ -18,4 +18,5 @@ interface TemperatureBounds {
18
18
  export declare const getHeatBounds: ({ mode, minHeat, maxHeat, maxCool, delta, }: Omit<ControlBounds, 'minCool'>) => MinMax;
19
19
  export declare const getCoolBounds: ({ mode, minHeat, minCool, maxCool, delta, }: Omit<ControlBounds, 'maxHeat'>) => MinMax;
20
20
  export declare const getTemperatureBounds: (controlBounds: ControlBounds) => TemperatureBounds;
21
+ export declare const getSupportedThermostatModes: (device: ThermostatDevice) => HvacModeSetting[];
21
22
  export {};
@@ -10,4 +10,20 @@ export const getTemperatureBounds = (controlBounds) => ({
10
10
  heat: getHeatBounds(controlBounds),
11
11
  cool: getCoolBounds(controlBounds),
12
12
  });
13
+ export const getSupportedThermostatModes = (device) => {
14
+ const allModes = ['heat', 'cool', 'heat_cool', 'off'];
15
+ return allModes.filter((mode) => {
16
+ switch (mode) {
17
+ case 'cool':
18
+ return device.properties.is_cooling_available;
19
+ case 'heat':
20
+ return device.properties.is_heating_available;
21
+ case 'heat_cool':
22
+ return (device.properties.is_heating_available &&
23
+ device.properties.is_cooling_available);
24
+ default:
25
+ return true;
26
+ }
27
+ });
28
+ };
13
29
  //# sourceMappingURL=temperature-bounds.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"temperature-bounds.js","sourceRoot":"","sources":["../src/lib/temperature-bounds.ts"],"names":[],"mappings":"AAqBA,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAC5B,IAAI,EACJ,OAAO,EACP,OAAO,EACP,OAAO,EACP,KAAK,GAC0B,EAAU,EAAE;IAC3C,MAAM,aAAa,GACjB,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,KAAK,EAAE,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;IAE7E,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,CAAA;AAC7C,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAC5B,IAAI,EACJ,OAAO,EACP,OAAO,EACP,OAAO,EACP,KAAK,GAC0B,EAAU,EAAE;IAC3C,MAAM,aAAa,GACjB,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,KAAK,EAAE,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;IAE7E,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,OAAO,EAAE,CAAA;AAC7C,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,aAA4B,EACT,EAAE,CAAC,CAAC;IACvB,IAAI,EAAE,aAAa,CAAC,aAAa,CAAC;IAClC,IAAI,EAAE,aAAa,CAAC,aAAa,CAAC;CACnC,CAAC,CAAA"}
1
+ {"version":3,"file":"temperature-bounds.js","sourceRoot":"","sources":["../src/lib/temperature-bounds.ts"],"names":[],"mappings":"AAqBA,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAC5B,IAAI,EACJ,OAAO,EACP,OAAO,EACP,OAAO,EACP,KAAK,GAC0B,EAAU,EAAE;IAC3C,MAAM,aAAa,GACjB,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,KAAK,EAAE,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;IAE7E,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,CAAA;AAC7C,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAC5B,IAAI,EACJ,OAAO,EACP,OAAO,EACP,OAAO,EACP,KAAK,GAC0B,EAAU,EAAE;IAC3C,MAAM,aAAa,GACjB,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,KAAK,EAAE,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;IAE7E,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,OAAO,EAAE,CAAA;AAC7C,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,aAA4B,EACT,EAAE,CAAC,CAAC;IACvB,IAAI,EAAE,aAAa,CAAC,aAAa,CAAC;IAClC,IAAI,EAAE,aAAa,CAAC,aAAa,CAAC;CACnC,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG,CACzC,MAAwB,EACL,EAAE;IACrB,MAAM,QAAQ,GAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,CAAA;IAExE,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;QAC9B,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,MAAM;gBACT,OAAO,MAAM,CAAC,UAAU,CAAC,oBAAoB,CAAA;YAC/C,KAAK,MAAM;gBACT,OAAO,MAAM,CAAC,UAAU,CAAC,oBAAoB,CAAA;YAC/C,KAAK,WAAW;gBACd,OAAO,CACL,MAAM,CAAC,UAAU,CAAC,oBAAoB;oBACtC,MAAM,CAAC,UAAU,CAAC,oBAAoB,CACvC,CAAA;YACH;gBACE,OAAO,IAAI,CAAA;QACf,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA"}
@@ -1,7 +1,8 @@
1
1
  import type { PropsWithChildren } from 'react';
2
2
  interface AccordionRowProps extends PropsWithChildren {
3
3
  label: string;
4
+ leftContent?: JSX.Element;
4
5
  rightCollapsedContent?: JSX.Element;
5
6
  }
6
- export declare function AccordionRow({ label, rightCollapsedContent, children, }: AccordionRowProps): JSX.Element;
7
+ export declare function AccordionRow({ label, leftContent, rightCollapsedContent, children, }: AccordionRowProps): JSX.Element;
7
8
  export {};
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ChevronWideIcon } from '../../../lib/icons/ChevronWide.js';
3
3
  import { useToggle } from '../../../lib/ui/use-toggle.js';
4
- export function AccordionRow({ label, rightCollapsedContent, children, }) {
4
+ export function AccordionRow({ label, leftContent, rightCollapsedContent, children, }) {
5
5
  const [isExpanded, toggle] = useToggle();
6
- return (_jsxs("div", { className: 'seam-accordion-row', "aria-expanded": isExpanded, children: [_jsxs("button", { className: 'seam-accordion-row-trigger', onClick: toggle, children: [_jsx("p", { className: 'seam-row-label', children: label }), _jsxs("div", { className: 'seam-row-inner-wrap', children: [_jsx("div", { className: 'seam-row-trigger-right-content', children: rightCollapsedContent }), _jsx("div", { className: 'seam-accordion-icon-wrap', children: _jsx(ChevronWideIcon, {}) })] })] }), _jsx("div", { className: 'seam-accordion-row-content', children: _jsx("div", { className: 'seam-accordion-row-inner-content', children: children }) })] }));
6
+ return (_jsxs("div", { className: 'seam-accordion-row', "aria-expanded": isExpanded, children: [_jsxs("button", { className: 'seam-accordion-row-trigger', onClick: toggle, children: [_jsxs("div", { className: 'seam-row-inner-wrap', children: [_jsx("p", { className: 'seam-row-label', children: label }), _jsx("div", { className: 'seam-row-trigger-left-content', children: leftContent })] }), _jsxs("div", { className: 'seam-row-inner-wrap', children: [_jsx("div", { className: 'seam-row-trigger-right-content', children: rightCollapsedContent }), _jsx("div", { className: 'seam-accordion-icon-wrap', children: _jsx(ChevronWideIcon, {}) })] })] }), _jsx("div", { className: 'seam-accordion-row-content', children: _jsx("div", { className: 'seam-accordion-row-inner-content', children: children }) })] }));
7
7
  }
8
8
  //# sourceMappingURL=AccordionRow.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AccordionRow.js","sourceRoot":"","sources":["../../../src/lib/ui/layout/AccordionRow.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAOhD,MAAM,UAAU,YAAY,CAAC,EAC3B,KAAK,EACL,qBAAqB,EACrB,QAAQ,GACU;IAClB,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG,SAAS,EAAE,CAAA;IAExC,OAAO,CACL,eAAK,SAAS,EAAC,oBAAoB,mBAAgB,UAAU,aAC3D,kBAAQ,SAAS,EAAC,4BAA4B,EAAC,OAAO,EAAE,MAAM,aAC5D,YAAG,SAAS,EAAC,gBAAgB,YAAE,KAAK,GAAK,EACzC,eAAK,SAAS,EAAC,qBAAqB,aAClC,cAAK,SAAS,EAAC,gCAAgC,YAC5C,qBAAqB,GAClB,EACN,cAAK,SAAS,EAAC,0BAA0B,YACvC,KAAC,eAAe,KAAG,GACf,IACF,IACC,EACT,cAAK,SAAS,EAAC,4BAA4B,YACzC,cAAK,SAAS,EAAC,kCAAkC,YAAE,QAAQ,GAAO,GAC9D,IACF,CACP,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"AccordionRow.js","sourceRoot":"","sources":["../../../src/lib/ui/layout/AccordionRow.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAQhD,MAAM,UAAU,YAAY,CAAC,EAC3B,KAAK,EACL,WAAW,EACX,qBAAqB,EACrB,QAAQ,GACU;IAClB,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG,SAAS,EAAE,CAAA;IAExC,OAAO,CACL,eAAK,SAAS,EAAC,oBAAoB,mBAAgB,UAAU,aAC3D,kBAAQ,SAAS,EAAC,4BAA4B,EAAC,OAAO,EAAE,MAAM,aAC5D,eAAK,SAAS,EAAC,qBAAqB,aAClC,YAAG,SAAS,EAAC,gBAAgB,YAAE,KAAK,GAAK,EACzC,cAAK,SAAS,EAAC,+BAA+B,YAAE,WAAW,GAAO,IAC9D,EACN,eAAK,SAAS,EAAC,qBAAqB,aAClC,cAAK,SAAS,EAAC,gCAAgC,YAC5C,qBAAqB,GAClB,EACN,cAAK,SAAS,EAAC,0BAA0B,YACvC,KAAC,eAAe,KAAG,GACf,IACF,IACC,EACT,cAAK,SAAS,EAAC,4BAA4B,YACzC,cAAK,SAAS,EAAC,kCAAkC,YAAE,QAAQ,GAAO,GAC9D,IACF,CACP,CAAA;AACH,CAAC"}
@@ -3,6 +3,7 @@ import type { HvacModeSetting } from 'seamapi';
3
3
  interface ClimateModeMenuProps {
4
4
  mode: HvacModeSetting;
5
5
  onChange: (mode: HvacModeSetting) => void;
6
+ supportedModes?: HvacModeSetting[];
6
7
  }
7
- export declare function ClimateModeMenu({ mode, onChange, }: ClimateModeMenuProps): JSX.Element;
8
+ export declare function ClimateModeMenu({ mode, onChange, supportedModes, }: ClimateModeMenuProps): JSX.Element;
8
9
  export {};
@@ -6,11 +6,10 @@ import { ThermostatHeatIcon } from '../../../lib/icons/ThermostatHeat.js';
6
6
  import { ThermostatHeatCoolIcon } from '../../../lib/icons/ThermostatHeatCool.js';
7
7
  import { Menu } from '../../../lib/ui/Menu/Menu.js';
8
8
  import { ThermoModeMenuOption } from '../../../lib/ui/thermostat/ThermoModeMenuOption.js';
9
- const modes = ['heat', 'cool', 'heat_cool', 'off'];
10
- export function ClimateModeMenu({ mode, onChange, }) {
9
+ export function ClimateModeMenu({ mode, onChange, supportedModes = ['heat', 'cool', 'heat_cool', 'off'], }) {
11
10
  return (_jsx(Menu, { renderButton: ({ onOpen }) => (_jsxs("button", { onClick: onOpen, className: 'seam-climate-mode-menu-button', children: [_jsx("div", { className: 'seam-climate-mode-menu-button-icon', children: _jsx(ModeIcon, { mode: mode }) }), _jsx(ChevronDownIcon, {})] })), verticalOffset: -180, horizontalOffset: -32, backgroundProps: {
12
11
  className: 'seam-thermo-mode-menu',
13
- }, children: modes.map((m) => (_jsx(ThermoModeMenuOption, { label: t[m], icon: _jsx(ModeIcon, { mode: m }), isSelected: mode === m, onClick: () => {
12
+ }, children: supportedModes.map((m) => (_jsx(ThermoModeMenuOption, { label: t[m], icon: _jsx(ModeIcon, { mode: m }), isSelected: mode === m, onClick: () => {
14
13
  onChange(m);
15
14
  } }, m))) }));
16
15
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ClimateModeMenu.js","sourceRoot":"","sources":["../../../src/lib/ui/thermostat/ClimateModeMenu.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAA;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAEhF,MAAM,KAAK,GAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,CAAA;AAOrE,MAAM,UAAU,eAAe,CAAC,EAC9B,IAAI,EACJ,QAAQ,GACa;IACrB,OAAO,CACL,KAAC,IAAI,IACH,YAAY,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAC5B,kBAAQ,OAAO,EAAE,MAAM,EAAE,SAAS,EAAC,+BAA+B,aAChE,cAAK,SAAS,EAAC,oCAAoC,YACjD,KAAC,QAAQ,IAAC,IAAI,EAAE,IAAI,GAAI,GACpB,EACN,KAAC,eAAe,KAAG,IACZ,CACV,EACD,cAAc,EAAE,CAAC,GAAG,EACpB,gBAAgB,EAAE,CAAC,EAAE,EACrB,eAAe,EAAE;YACf,SAAS,EAAE,uBAAuB;SACnC,YAEA,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAChB,KAAC,oBAAoB,IAEnB,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EACX,IAAI,EAAE,KAAC,QAAQ,IAAC,IAAI,EAAE,CAAC,GAAI,EAC3B,UAAU,EAAE,IAAI,KAAK,CAAC,EACtB,OAAO,EAAE,GAAG,EAAE;gBACZ,QAAQ,CAAC,CAAC,CAAC,CAAA;YACb,CAAC,IANI,CAAC,CAON,CACH,CAAC,GACG,CACR,CAAA;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,KAAgC;IAChD,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,MAAM;YACT,OAAO,KAAC,kBAAkB,KAAG,CAAA;QAC/B,KAAK,MAAM;YACT,OAAO,KAAC,kBAAkB,KAAG,CAAA;QAC/B,KAAK,WAAW;YACd,OAAO,KAAC,sBAAsB,KAAG,CAAA;QACnC,KAAK,KAAK;YACR,OAAO,KAAC,OAAO,KAAG,CAAA;IACtB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,GAAG;IACR,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;IACZ,SAAS,EAAE,aAAa;IACxB,GAAG,EAAE,KAAK;CACX,CAAA"}
1
+ {"version":3,"file":"ClimateModeMenu.js","sourceRoot":"","sources":["../../../src/lib/ui/thermostat/ClimateModeMenu.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAA;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAQhF,MAAM,UAAU,eAAe,CAAC,EAC9B,IAAI,EACJ,QAAQ,EACR,cAAc,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,GAChC;IACrB,OAAO,CACL,KAAC,IAAI,IACH,YAAY,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAC5B,kBAAQ,OAAO,EAAE,MAAM,EAAE,SAAS,EAAC,+BAA+B,aAChE,cAAK,SAAS,EAAC,oCAAoC,YACjD,KAAC,QAAQ,IAAC,IAAI,EAAE,IAAI,GAAI,GACpB,EACN,KAAC,eAAe,KAAG,IACZ,CACV,EACD,cAAc,EAAE,CAAC,GAAG,EACpB,gBAAgB,EAAE,CAAC,EAAE,EACrB,eAAe,EAAE;YACf,SAAS,EAAE,uBAAuB;SACnC,YAEA,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CACzB,KAAC,oBAAoB,IAEnB,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EACX,IAAI,EAAE,KAAC,QAAQ,IAAC,IAAI,EAAE,CAAC,GAAI,EAC3B,UAAU,EAAE,IAAI,KAAK,CAAC,EACtB,OAAO,EAAE,GAAG,EAAE;gBACZ,QAAQ,CAAC,CAAC,CAAC,CAAA;YACb,CAAC,IANI,CAAC,CAON,CACH,CAAC,GACG,CACR,CAAA;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,KAAgC;IAChD,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,MAAM;YACT,OAAO,KAAC,kBAAkB,KAAG,CAAA;QAC/B,KAAK,MAAM;YACT,OAAO,KAAC,kBAAkB,KAAG,CAAA;QAC/B,KAAK,WAAW;YACd,OAAO,KAAC,sBAAsB,KAAG,CAAA;QACnC,KAAK,KAAK;YACR,OAAO,KAAC,OAAO,KAAG,CAAA;IACtB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,GAAG;IACR,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;IACZ,SAAS,EAAE,aAAa;IACxB,GAAG,EAAE,KAAK;CACX,CAAA"}
package/lib/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- declare const seamapiReactVersion = "2.8.7";
1
+ declare const seamapiReactVersion = "2.10.0";
2
2
  export default seamapiReactVersion;
package/lib/version.js CHANGED
@@ -1,3 +1,3 @@
1
- const seamapiReactVersion = '2.8.7';
1
+ const seamapiReactVersion = '2.10.0';
2
2
  export default seamapiReactVersion;
3
3
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/lib/version.ts"],"names":[],"mappings":"AAAA,MAAM,mBAAmB,GAAG,OAAO,CAAA;AAEnC,eAAe,mBAAmB,CAAA"}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/lib/version.ts"],"names":[],"mappings":"AAAA,MAAM,mBAAmB,GAAG,QAAQ,CAAA;AAEpC,eAAe,mBAAmB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seamapi/react",
3
- "version": "2.8.7",
3
+ "version": "2.10.0",
4
4
  "description": "Seam Components.",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -132,7 +132,7 @@
132
132
  "luxon": "^3.3.0",
133
133
  "queue": "^7.0.0",
134
134
  "react-hook-form": "^7.46.1",
135
- "seamapi": "^8.19.0",
135
+ "seamapi": "^8.21.0",
136
136
  "uuid": "^9.0.0"
137
137
  },
138
138
  "devDependencies": {
@@ -141,7 +141,7 @@
141
141
  "@mui/material": "^5.12.2",
142
142
  "@rxfork/r2wc-react-to-web-component": "^2.4.0",
143
143
  "@seamapi/fake-devicedb": "^1.6.0",
144
- "@seamapi/fake-seam-connect": "^1.44.3",
144
+ "@seamapi/fake-seam-connect": "^1.60.2",
145
145
  "@seamapi/http": "^0.19.0",
146
146
  "@seamapi/types": "^1.122.0",
147
147
  "@storybook/addon-designs": "^7.0.1",
@@ -0,0 +1,33 @@
1
+ type Procedure = (...args: any[]) => void
2
+
3
+ export function debounce<F extends Procedure>(
4
+ func: F,
5
+ waitMilliseconds: number
6
+ ): {
7
+ (this: ThisParameterType<F>, ...args: Parameters<F>): void
8
+ cancel: () => void
9
+ } {
10
+ let timeoutId: ReturnType<typeof globalThis.setTimeout> | null = null
11
+
12
+ const debouncedFunction = function (
13
+ this: ThisParameterType<F>,
14
+ ...args: Parameters<F>
15
+ ): void {
16
+ if (timeoutId !== null) {
17
+ globalThis.clearTimeout(timeoutId)
18
+ }
19
+ timeoutId = globalThis.setTimeout(() => {
20
+ timeoutId = null
21
+ func.apply(this, args)
22
+ }, waitMilliseconds)
23
+ }
24
+
25
+ debouncedFunction.cancel = (): void => {
26
+ if (timeoutId !== null) {
27
+ globalThis.clearTimeout(timeoutId)
28
+ timeoutId = null
29
+ }
30
+ }
31
+
32
+ return debouncedFunction
33
+ }
@@ -46,6 +46,7 @@ const commonProps: R2wcProps<CommonProps> = {
46
46
  disableEditAccessCode: 'boolean',
47
47
  disableDeleteAccessCode: 'boolean',
48
48
  disableResourceIds: 'boolean',
49
+ disableClimateSettingSchedules: 'boolean',
49
50
  onBack: 'object',
50
51
  className: 'string',
51
52
  }
@@ -43,6 +43,7 @@ export function AccessCodeDetails({
43
43
  disableLockUnlock = false,
44
44
  disableDeleteAccessCode = false,
45
45
  disableResourceIds = false,
46
+ disableClimateSettingSchedules,
46
47
  onBack,
47
48
  className,
48
49
  }: AccessCodeDetailsProps): JSX.Element | null {
@@ -69,6 +70,7 @@ export function AccessCodeDetails({
69
70
  disableEditAccessCode={disableEditAccessCode}
70
71
  disableDeleteAccessCode={disableDeleteAccessCode}
71
72
  disableResourceIds={disableResourceIds}
73
+ disableClimateSettingSchedules={disableClimateSettingSchedules}
72
74
  onBack={() => {
73
75
  selectDevice(null)
74
76
  }}
@@ -84,6 +84,7 @@ export function AccessCodeTable({
84
84
  disableLockUnlock = false,
85
85
  disableDeleteAccessCode = false,
86
86
  disableResourceIds = false,
87
+ disableClimateSettingSchedules,
87
88
  }: AccessCodeTableProps): JSX.Element {
88
89
  useComponentTelemetry('AccessCodeTable')
89
90
 
@@ -147,6 +148,7 @@ export function AccessCodeTable({
147
148
  disableEditAccessCode={disableEditAccessCode}
148
149
  disableDeleteAccessCode={disableDeleteAccessCode}
149
150
  disableResourceIds={disableResourceIds}
151
+ disableClimateSettingSchedules={disableClimateSettingSchedules}
150
152
  onBack={() => {
151
153
  setSelectedEditAccessCodeId(null)
152
154
  }}
@@ -182,6 +184,7 @@ export function AccessCodeTable({
182
184
  disableEditAccessCode={disableEditAccessCode}
183
185
  disableDeleteAccessCode={disableDeleteAccessCode}
184
186
  disableResourceIds={disableResourceIds}
187
+ disableClimateSettingSchedules={disableClimateSettingSchedules}
185
188
  onBack={() => {
186
189
  setSelectedViewAccessCodeId(null)
187
190
  }}
@@ -202,6 +205,7 @@ export function AccessCodeTable({
202
205
  disableEditAccessCode={disableEditAccessCode}
203
206
  disableDeleteAccessCode={disableDeleteAccessCode}
204
207
  disableResourceIds={disableResourceIds}
208
+ disableClimateSettingSchedules={disableClimateSettingSchedules}
205
209
  onBack={toggleAddAccessCodeForm}
206
210
  className={className}
207
211
  onSuccess={() => {
@@ -38,6 +38,7 @@ export function ClimateSettingScheduleDetails({
38
38
  disableCreateAccessCode,
39
39
  disableEditAccessCode,
40
40
  disableResourceIds = false,
41
+ disableClimateSettingSchedules,
41
42
  }: ClimateSettingScheduleDetailsProps): JSX.Element | null {
42
43
  useComponentTelemetry('ClimateSettingScheduleDetails')
43
44
 
@@ -65,6 +66,7 @@ export function ClimateSettingScheduleDetails({
65
66
  disableEditAccessCode={disableEditAccessCode}
66
67
  disableDeleteAccessCode={disableDeleteAccessCode}
67
68
  disableResourceIds={disableResourceIds}
69
+ disableClimateSettingSchedules={disableClimateSettingSchedules}
68
70
  onBack={() => {
69
71
  selectDevice(null)
70
72
  }}
@@ -72,6 +72,7 @@ export function ClimateSettingScheduleTable({
72
72
  disableCreateAccessCode,
73
73
  disableEditAccessCode,
74
74
  disableResourceIds = false,
75
+ disableClimateSettingSchedules,
75
76
  }: ClimateSettingScheduleTableProps): JSX.Element {
76
77
  useComponentTelemetry('ClimateSettingScheduleTable')
77
78
 
@@ -125,6 +126,7 @@ export function ClimateSettingScheduleTable({
125
126
  disableEditAccessCode={disableEditAccessCode}
126
127
  disableDeleteAccessCode={disableDeleteAccessCode}
127
128
  disableResourceIds={disableResourceIds}
129
+ disableClimateSettingSchedules={disableClimateSettingSchedules}
128
130
  onBack={() => {
129
131
  setSelectedViewClimateSettingScheduleId(null)
130
132
  }}
@@ -23,6 +23,7 @@ export function DeviceDetails({
23
23
  disableResourceIds = false,
24
24
  disableCreateAccessCode = false,
25
25
  disableEditAccessCode = false,
26
+ disableClimateSettingSchedules = false,
26
27
  onBack,
27
28
  className,
28
29
  }: DeviceDetailsProps): JSX.Element | null {
@@ -36,12 +37,13 @@ export function DeviceDetails({
36
37
  return null
37
38
  }
38
39
 
39
- const props = {
40
+ const props: Omit<DeviceDetailsProps, 'deviceId'> = {
40
41
  disableLockUnlock,
41
42
  disableDeleteAccessCode,
42
43
  disableResourceIds,
43
44
  disableCreateAccessCode,
44
45
  disableEditAccessCode,
46
+ disableClimateSettingSchedules,
45
47
  onBack,
46
48
  className,
47
49
  }
@@ -32,6 +32,7 @@ export function LockDeviceDetails(
32
32
  disableEditAccessCode,
33
33
  disableDeleteAccessCode,
34
34
  disableResourceIds,
35
+ disableClimateSettingSchedules,
35
36
  onBack,
36
37
  className,
37
38
  } = props
@@ -62,6 +63,7 @@ export function LockDeviceDetails(
62
63
  disableEditAccessCode={disableEditAccessCode}
63
64
  disableDeleteAccessCode={disableDeleteAccessCode}
64
65
  disableResourceIds={disableResourceIds}
66
+ disableClimateSettingSchedules={disableClimateSettingSchedules}
65
67
  onBack={toggleAccessCodesOpen}
66
68
  className={className}
67
69
  />
@@ -1,23 +1,33 @@
1
1
  import classNames from 'classnames'
2
- import { useState } from 'react'
3
- import type { ThermostatDevice } from 'seamapi'
2
+ import { useEffect, useState } from 'react'
3
+ import type { HvacModeSetting, ThermostatDevice } from 'seamapi'
4
4
 
5
+ import { debounce } from 'lib/debounce.js'
5
6
  import { BeeIcon } from 'lib/icons/Bee.js'
7
+ import { CheckBlackIcon } from 'lib/icons/CheckBlack.js'
6
8
  import { ChevronWideIcon } from 'lib/icons/ChevronWide.js'
7
9
  import { NestedClimateSettingScheduleTable } from 'lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.js'
8
10
  import type { CommonProps } from 'lib/seam/components/common-props.js'
9
11
  import { useConnectedAccount } from 'lib/seam/connected-accounts/use-connected-account.js'
10
12
  import { useClimateSettingSchedules } from 'lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedules.js'
13
+ import { useCoolThermostat } from 'lib/seam/thermostats/use-cool-thermostat.js'
14
+ import { useHeatCoolThermostat } from 'lib/seam/thermostats/use-heat-cool-thermostat.js'
15
+ import { useHeatThermostat } from 'lib/seam/thermostats/use-heat-thermostat.js'
16
+ import { useSetThermostatOff } from 'lib/seam/thermostats/use-set-thermostat-off.js'
11
17
  import { useUpdateFanMode } from 'lib/seam/thermostats/use-update-fan-mode.js'
12
18
  import { useUpdateThermostat } from 'lib/seam/thermostats/use-update-thermostat.js'
19
+ import { getSupportedThermostatModes } from 'lib/temperature-bounds.js'
20
+ import { AccordionRow } from 'lib/ui/layout/AccordionRow.js'
13
21
  import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
14
22
  import { DetailRow } from 'lib/ui/layout/DetailRow.js'
15
23
  import { DetailSection } from 'lib/ui/layout/DetailSection.js'
16
24
  import { DetailSectionGroup } from 'lib/ui/layout/DetailSectionGroup.js'
17
25
  import { Snackbar } from 'lib/ui/Snackbar/Snackbar.js'
18
26
  import { Switch } from 'lib/ui/Switch/Switch.js'
27
+ import { ClimateModeMenu } from 'lib/ui/thermostat/ClimateModeMenu.js'
19
28
  import { ClimateSettingStatus } from 'lib/ui/thermostat/ClimateSettingStatus.js'
20
29
  import { FanModeMenu } from 'lib/ui/thermostat/FanModeMenu.js'
30
+ import { TemperatureControlGroup } from 'lib/ui/thermostat/TemperatureControlGroup.js'
21
31
  import { ThermostatCard } from 'lib/ui/thermostat/ThermostatCard.js'
22
32
 
23
33
  interface ThermostatDeviceDetailsProps extends CommonProps {
@@ -35,6 +45,7 @@ export function ThermostatDeviceDetails({
35
45
  disableEditAccessCode,
36
46
  disableDeleteAccessCode,
37
47
  disableResourceIds = false,
48
+ disableClimateSettingSchedules = false,
38
49
  }: ThermostatDeviceDetailsProps): JSX.Element | null {
39
50
  const [climateSettingsOpen, setClimateSettingsOpen] = useState(false)
40
51
 
@@ -55,6 +66,7 @@ export function ThermostatDeviceDetails({
55
66
  disableEditAccessCode={disableEditAccessCode}
56
67
  disableDeleteAccessCode={disableDeleteAccessCode}
57
68
  disableResourceIds={disableResourceIds}
69
+ disableClimateSettingSchedules={disableClimateSettingSchedules}
58
70
  onBack={() => {
59
71
  setClimateSettingsOpen(false)
60
72
  }}
@@ -81,36 +93,33 @@ export function ThermostatDeviceDetails({
81
93
 
82
94
  <div className='seam-thermostat-device-details'>
83
95
  <DetailSectionGroup>
84
- <DetailSection
85
- label={t.scheduledClimates}
86
- tooltipContent={t.scheduledClimatesTooltip}
87
- >
88
- <DetailRow
89
- label={
90
- climateSettingSchedules == null
91
- ? t.viewingClimateSchedules
92
- : `${climateSettingSchedules.length} ${climateSettingSchedulesLabel}`
93
- }
94
- onClick={() => {
95
- setClimateSettingsOpen(true)
96
- }}
96
+ {!disableClimateSettingSchedules && (
97
+ <DetailSection
98
+ label={t.scheduledClimates}
99
+ tooltipContent={t.scheduledClimatesTooltip}
97
100
  >
98
- <div className='seam-detail-row-rotated-icon'>
99
- <ChevronWideIcon />
100
- </div>
101
- </DetailRow>
102
- </DetailSection>
101
+ <DetailRow
102
+ label={
103
+ climateSettingSchedules == null
104
+ ? t.viewingClimateSchedules
105
+ : `${climateSettingSchedules.length} ${climateSettingSchedulesLabel}`
106
+ }
107
+ onClick={() => {
108
+ setClimateSettingsOpen(true)
109
+ }}
110
+ >
111
+ <div className='seam-detail-row-rotated-icon'>
112
+ <ChevronWideIcon />
113
+ </div>
114
+ </DetailRow>
115
+ </DetailSection>
116
+ )}
103
117
 
104
118
  <DetailSection
105
119
  label={t.currentSettings}
106
120
  tooltipContent={t.currentSettingsTooltip}
107
121
  >
108
- <DetailRow label={t.climate}>
109
- <ClimateSettingStatus
110
- climateSetting={device.properties.current_climate_setting}
111
- temperatureUnit='fahrenheit'
112
- />
113
- </DetailRow>
122
+ <ClimateSettingRow device={device} />
114
123
  <FanModeRow device={device} />
115
124
  </DetailSection>
116
125
 
@@ -239,6 +248,191 @@ function FanModeRow({ device }: { device: ThermostatDevice }): JSX.Element {
239
248
  )
240
249
  }
241
250
 
251
+ function ClimateSettingRow({
252
+ device,
253
+ }: {
254
+ device: ThermostatDevice
255
+ }): JSX.Element {
256
+ const deviceHeatValue =
257
+ device.properties.current_climate_setting.heating_set_point_fahrenheit
258
+ const deviceCoolValue =
259
+ device.properties.current_climate_setting.cooling_set_point_fahrenheit
260
+
261
+ const supportedModes = getSupportedThermostatModes(device)
262
+
263
+ const [showSuccess, setShowSuccess] = useState(false)
264
+ const [mode, setMode] = useState<HvacModeSetting>(
265
+ (supportedModes.includes('heat_cool') ? 'heat_cool' : supportedModes[0]) ??
266
+ 'off'
267
+ )
268
+
269
+ const [heatValue, setHeatValue] = useState(
270
+ device.properties.current_climate_setting.heating_set_point_fahrenheit ?? 0
271
+ )
272
+
273
+ const [coolValue, setCoolValue] = useState(
274
+ device.properties.current_climate_setting.cooling_set_point_fahrenheit ?? 0
275
+ )
276
+
277
+ const {
278
+ mutate: heatCoolThermostat,
279
+ isSuccess: isHeatCoolSuccess,
280
+ isError: isHeatCoolError,
281
+ } = useHeatCoolThermostat()
282
+
283
+ const {
284
+ mutate: heatThermostat,
285
+ isSuccess: isHeatSuccess,
286
+ isError: isHeatError,
287
+ } = useHeatThermostat()
288
+
289
+ const {
290
+ mutate: coolThermostat,
291
+ isSuccess: isCoolSuccess,
292
+ isError: isCoolError,
293
+ } = useCoolThermostat()
294
+
295
+ const {
296
+ mutate: setThermostatOff,
297
+ isSuccess: isSetOffSuccess,
298
+ isError: isSetOffError,
299
+ } = useSetThermostatOff()
300
+
301
+ useEffect(() => {
302
+ const handler = debounce(() => {
303
+ switch (mode) {
304
+ case 'heat_cool':
305
+ heatCoolThermostat({
306
+ device_id: device.device_id,
307
+ heating_set_point_fahrenheit: heatValue,
308
+ cooling_set_point_fahrenheit: coolValue,
309
+ })
310
+ break
311
+ case 'heat':
312
+ heatThermostat({
313
+ device_id: device.device_id,
314
+ heating_set_point_fahrenheit: heatValue,
315
+ })
316
+ break
317
+ case 'cool':
318
+ coolThermostat({
319
+ device_id: device.device_id,
320
+ cooling_set_point_fahrenheit: coolValue,
321
+ })
322
+ break
323
+ case 'off':
324
+ setThermostatOff({
325
+ device_id: device.device_id,
326
+ })
327
+ break
328
+ }
329
+ }, 2000)
330
+
331
+ if (
332
+ heatValue !== deviceHeatValue ||
333
+ coolValue !== deviceCoolValue ||
334
+ mode === 'off'
335
+ ) {
336
+ handler()
337
+ }
338
+
339
+ return () => {
340
+ handler.cancel()
341
+ }
342
+ }, [
343
+ heatValue,
344
+ coolValue,
345
+ mode,
346
+ deviceHeatValue,
347
+ deviceCoolValue,
348
+ device,
349
+ heatThermostat,
350
+ coolThermostat,
351
+ heatCoolThermostat,
352
+ setThermostatOff,
353
+ ])
354
+
355
+ useEffect(() => {
356
+ if (
357
+ isHeatCoolSuccess ||
358
+ isHeatSuccess ||
359
+ isCoolSuccess ||
360
+ isSetOffSuccess
361
+ ) {
362
+ setShowSuccess(true)
363
+
364
+ const timeout = globalThis.setTimeout(() => {
365
+ setShowSuccess(false)
366
+ }, 3000)
367
+
368
+ return () => {
369
+ globalThis.clearTimeout(timeout)
370
+ }
371
+ }
372
+
373
+ return () => {}
374
+ }, [isHeatCoolSuccess, isHeatSuccess, isCoolSuccess, isSetOffSuccess])
375
+
376
+ return (
377
+ <>
378
+ <AccordionRow
379
+ label={t.climate}
380
+ leftContent={
381
+ <div
382
+ className={classNames('seam-thermostat-mutation-status', {
383
+ 'is-visible': showSuccess,
384
+ })}
385
+ >
386
+ <div className='seam-thermostat-mutation-status-icon'>
387
+ <CheckBlackIcon />
388
+ </div>
389
+ <div className='seam-thermostat-mutation-status-label'>
390
+ {t.saved}
391
+ </div>
392
+ </div>
393
+ }
394
+ rightCollapsedContent={
395
+ <ClimateSettingStatus
396
+ climateSetting={device.properties.current_climate_setting}
397
+ temperatureUnit='fahrenheit'
398
+ />
399
+ }
400
+ >
401
+ <div className='seam-detail-row-end-alignment'>
402
+ {mode !== 'off' && (
403
+ <TemperatureControlGroup
404
+ mode={mode}
405
+ heatValue={heatValue}
406
+ coolValue={coolValue}
407
+ onHeatValueChange={setHeatValue}
408
+ onCoolValueChange={setCoolValue}
409
+ delta={
410
+ Number(
411
+ 'min_heating_cooling_delta_fahrenheit' in device.properties &&
412
+ device.properties.min_heating_cooling_delta_fahrenheit
413
+ ) ?? 0
414
+ }
415
+ />
416
+ )}
417
+
418
+ <ClimateModeMenu
419
+ mode={mode}
420
+ onChange={setMode}
421
+ supportedModes={supportedModes}
422
+ />
423
+ </div>
424
+ </AccordionRow>
425
+
426
+ <Snackbar
427
+ message={t.climateSettingError}
428
+ variant='error'
429
+ visible={isHeatCoolError || isHeatError || isCoolError || isSetOffError}
430
+ automaticVisibility
431
+ />
432
+ </>
433
+ )
434
+ }
435
+
242
436
  const t = {
243
437
  thermostat: 'Thermostat',
244
438
  climateSchedule: 'scheduled climate',
@@ -266,4 +460,6 @@ const t = {
266
460
  fanModeError: 'Error updating fan mode. Please try again.',
267
461
  manualOverrideSuccess: 'Successfully updated manual override!',
268
462
  manualOverrideError: 'Error updating manual override. Please try again.',
463
+ climateSettingError: 'Error updating climate setting. Please try again.',
464
+ saved: 'Saved',
269
465
  }
@@ -70,6 +70,7 @@ export function DeviceTable({
70
70
  disableEditAccessCode = false,
71
71
  disableDeleteAccessCode = false,
72
72
  disableResourceIds = false,
73
+ disableClimateSettingSchedules = false,
73
74
  onBack,
74
75
  className,
75
76
  }: DeviceTableProps = {}): JSX.Element {
@@ -112,6 +113,7 @@ export function DeviceTable({
112
113
  disableEditAccessCode={disableEditAccessCode}
113
114
  disableDeleteAccessCode={disableDeleteAccessCode}
114
115
  disableResourceIds={disableResourceIds}
116
+ disableClimateSettingSchedules={disableClimateSettingSchedules}
115
117
  onBack={() => {
116
118
  setSelectedDeviceId(null)
117
119
  }}
@@ -18,6 +18,7 @@ export interface RequiredCommonProps {
18
18
  disableEditAccessCode: boolean | undefined
19
19
  disableLockUnlock: boolean | undefined
20
20
  disableResourceIds: boolean | undefined
21
+ disableClimateSettingSchedules: boolean | undefined
21
22
  }
22
23
 
23
24
  export type CommonProps = Partial<RequiredCommonProps>