@seamapi/react 1.64.0 → 1.65.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 (78) hide show
  1. package/README.md +16 -4
  2. package/dist/elements.js +6684 -6581
  3. package/dist/elements.js.map +1 -1
  4. package/dist/index.css +2 -4
  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/seam/components/AccessCodeDetails/AccessCodeDetails.d.ts +1 -1
  9. package/lib/seam/components/AccessCodeDetails/AccessCodeDetails.js +11 -13
  10. package/lib/seam/components/AccessCodeDetails/AccessCodeDetails.js.map +1 -1
  11. package/lib/seam/components/AccessCodeTable/AccessCodeHealthBar.d.ts +4 -1
  12. package/lib/seam/components/AccessCodeTable/AccessCodeHealthBar.js +3 -2
  13. package/lib/seam/components/AccessCodeTable/AccessCodeHealthBar.js.map +1 -1
  14. package/lib/seam/components/AccessCodeTable/AccessCodeTable.d.ts +1 -1
  15. package/lib/seam/components/AccessCodeTable/AccessCodeTable.js +15 -11
  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 +12 -7
  22. package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.js.map +1 -1
  23. package/lib/seam/components/DeviceDetails/LockDeviceDetails.js +11 -4
  24. package/lib/seam/components/DeviceDetails/LockDeviceDetails.js.map +1 -1
  25. package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.d.ts +1 -1
  26. package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.js +2 -2
  27. package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.js.map +1 -1
  28. package/lib/seam/components/DeviceTable/DeviceHealthBar.d.ts +3 -1
  29. package/lib/seam/components/DeviceTable/DeviceHealthBar.js +4 -3
  30. package/lib/seam/components/DeviceTable/DeviceHealthBar.js.map +1 -1
  31. package/lib/seam/components/DeviceTable/DeviceTable.d.ts +1 -1
  32. package/lib/seam/components/DeviceTable/DeviceTable.js +14 -9
  33. package/lib/seam/components/DeviceTable/DeviceTable.js.map +1 -1
  34. package/lib/seam/components/SupportedDeviceTable/use-device-model.d.ts +7 -0
  35. package/lib/seam/components/SupportedDeviceTable/use-device-model.js +18 -0
  36. package/lib/seam/components/SupportedDeviceTable/use-device-model.js.map +1 -0
  37. package/lib/seam/components/SupportedDeviceTable/use-device-models.d.ts +7 -0
  38. package/lib/seam/components/SupportedDeviceTable/use-device-models.js +17 -0
  39. package/lib/seam/components/SupportedDeviceTable/use-device-models.js.map +1 -0
  40. package/lib/seam/components/SupportedDeviceTable/use-manufacturer.d.ts +7 -0
  41. package/lib/seam/components/SupportedDeviceTable/use-manufacturer.js +18 -0
  42. package/lib/seam/components/SupportedDeviceTable/use-manufacturer.js.map +1 -0
  43. package/lib/seam/components/SupportedDeviceTable/use-manufacturers.d.ts +7 -0
  44. package/lib/seam/components/SupportedDeviceTable/use-manufacturers.js +17 -0
  45. package/lib/seam/components/SupportedDeviceTable/use-manufacturers.js.map +1 -0
  46. package/lib/seam/components/common-props.d.ts +3 -0
  47. package/lib/seam/components/common-props.js.map +1 -1
  48. package/lib/seam/filters.d.ts +8 -0
  49. package/lib/seam/filters.js +16 -0
  50. package/lib/seam/filters.js.map +1 -0
  51. package/lib/telemetry/client.js.map +1 -1
  52. package/lib/ui/Snackbar/Snackbar.d.ts +1 -1
  53. package/lib/ui/Snackbar/Snackbar.js +1 -1
  54. package/lib/ui/Snackbar/Snackbar.js.map +1 -1
  55. package/lib/version.d.ts +1 -1
  56. package/lib/version.js +1 -1
  57. package/package.json +14 -4
  58. package/src/lib/element.tsx +2 -0
  59. package/src/lib/seam/components/AccessCodeDetails/AccessCodeDetails.tsx +24 -30
  60. package/src/lib/seam/components/AccessCodeTable/AccessCodeHealthBar.tsx +9 -1
  61. package/src/lib/seam/components/AccessCodeTable/AccessCodeTable.tsx +32 -5
  62. package/src/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.tsx +4 -0
  63. package/src/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.tsx +21 -5
  64. package/src/lib/seam/components/DeviceDetails/LockDeviceDetails.tsx +19 -8
  65. package/src/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.tsx +4 -0
  66. package/src/lib/seam/components/DeviceTable/DeviceHealthBar.tsx +10 -2
  67. package/src/lib/seam/components/DeviceTable/DeviceTable.tsx +29 -7
  68. package/src/lib/seam/components/SupportedDeviceTable/use-device-model.ts +45 -0
  69. package/src/lib/seam/components/SupportedDeviceTable/use-device-models.ts +43 -0
  70. package/src/lib/seam/components/SupportedDeviceTable/use-manufacturer.ts +45 -0
  71. package/src/lib/seam/components/SupportedDeviceTable/use-manufacturers.ts +43 -0
  72. package/src/lib/seam/components/common-props.tsx +10 -0
  73. package/src/lib/seam/filters.ts +32 -0
  74. package/src/lib/telemetry/client.ts +3 -3
  75. package/src/lib/ui/Snackbar/Snackbar.tsx +2 -2
  76. package/src/lib/version.ts +1 -1
  77. package/src/styles/_device-details.scss +1 -2
  78. package/src/styles/_thermostat.scss +1 -2
@@ -7,6 +7,7 @@ import { NestedAccessCodeTable } from 'lib/seam/components/AccessCodeTable/Acces
7
7
  import type { CommonProps } from 'lib/seam/components/common-props.js'
8
8
  import { DeviceModel } from 'lib/seam/components/DeviceDetails/DeviceModel.js'
9
9
  import { useToggleLock } from 'lib/seam/devices/use-toggle-lock.js'
10
+ import { deviceErrorFilter, deviceWarningFilter } from 'lib/seam/filters.js'
10
11
  import { Alerts } from 'lib/ui/Alert/Alerts.js'
11
12
  import { Button } from 'lib/ui/Button.js'
12
13
  import { BatteryStatus } from 'lib/ui/device/BatteryStatus.js'
@@ -24,6 +25,8 @@ export function LockDeviceDetails(
24
25
  ): JSX.Element | null {
25
26
  const {
26
27
  device,
28
+ errorFilter = () => true,
29
+ warningFilter = () => true,
27
30
  disableLockUnlock,
28
31
  disableCreateAccessCode,
29
32
  disableEditAccessCode,
@@ -52,6 +55,8 @@ export function LockDeviceDetails(
52
55
  return (
53
56
  <NestedAccessCodeTable
54
57
  deviceId={device.device_id}
58
+ errorFilter={errorFilter}
59
+ warningFilter={warningFilter}
55
60
  disableLockUnlock={disableLockUnlock}
56
61
  disableCreateAccessCode={disableCreateAccessCode}
57
62
  disableEditAccessCode={disableEditAccessCode}
@@ -64,14 +69,20 @@ export function LockDeviceDetails(
64
69
  }
65
70
 
66
71
  const alerts = [
67
- ...device.errors.map((error) => ({
68
- variant: 'error' as const,
69
- message: error.message,
70
- })),
71
- ...device.warnings.map((warning) => ({
72
- variant: 'warning' as const,
73
- message: warning.message,
74
- })),
72
+ ...device.errors
73
+ .filter(deviceErrorFilter)
74
+ .filter(errorFilter)
75
+ .map((error) => ({
76
+ variant: 'error' as const,
77
+ message: error.message,
78
+ })),
79
+ ...device.warnings
80
+ .filter(deviceWarningFilter)
81
+ .filter(warningFilter)
82
+ .map((warning) => ({
83
+ variant: 'warning' as const,
84
+ message: warning.message,
85
+ })),
75
86
  ]
76
87
 
77
88
  return (
@@ -23,6 +23,8 @@ export function ThermostatDeviceDetails({
23
23
  device,
24
24
  onBack,
25
25
  className,
26
+ errorFilter = () => true,
27
+ warningFilter = () => true,
26
28
  disableLockUnlock,
27
29
  disableCreateAccessCode,
28
30
  disableEditAccessCode,
@@ -41,6 +43,8 @@ export function ThermostatDeviceDetails({
41
43
  return (
42
44
  <NestedClimateSettingScheduleTable
43
45
  deviceId={device.device_id}
46
+ errorFilter={errorFilter}
47
+ warningFilter={warningFilter}
44
48
  disableLockUnlock={disableLockUnlock}
45
49
  disableCreateAccessCode={disableCreateAccessCode}
46
50
  disableEditAccessCode={disableEditAccessCode}
@@ -1,7 +1,13 @@
1
+ import type { ConnectedAccountError, DeviceError } from 'seamapi'
2
+
1
3
  import { CheckIcon } from 'lib/icons/Check.js'
2
4
  import { ExclamationCircleOutlineIcon } from 'lib/icons/ExclamationCircleOutline.js'
3
5
  import { OnlineStatusAccountOfflineIcon } from 'lib/icons/OnlineStatusAccountOffline.js'
4
6
  import type { UseDevicesData } from 'lib/seam/devices/use-devices.js'
7
+ import {
8
+ connectedAccountErrorFilter,
9
+ deviceErrorFilter,
10
+ } from 'lib/seam/filters.js'
5
11
  import { TableFilterBar } from 'lib/ui/Table/TableFilterBar/TableFilterBar.js'
6
12
  import { TableFilterItem } from 'lib/ui/Table/TableFilterBar/TableFilterItem.js'
7
13
 
@@ -12,22 +18,24 @@ interface DeviceHealthBarProps {
12
18
  devices: Array<UseDevicesData[number]>
13
19
  filter: AccountFilter | DeviceFilter | null
14
20
  onFilterSelect: (filter: AccountFilter | DeviceFilter | null) => void
21
+ errorFilter: (error: DeviceError | ConnectedAccountError) => boolean
15
22
  }
16
23
 
17
24
  export function DeviceHealthBar({
18
25
  devices,
19
26
  filter,
20
27
  onFilterSelect,
28
+ errorFilter,
21
29
  }: DeviceHealthBarProps): JSX.Element {
22
30
  const erroredAccounts = devices.filter((device) => {
23
31
  return (
24
- device.errors.filter((error) => 'is_connected_account_error' in error)
32
+ device.errors.filter(errorFilter).filter(connectedAccountErrorFilter)
25
33
  .length > 0
26
34
  )
27
35
  })
28
36
  const erroredDevices = devices.filter((device) => {
29
37
  return (
30
- device.errors.filter((error) => 'is_device_error' in error).length > 0
38
+ device.errors.filter(errorFilter).filter(deviceErrorFilter).length > 0
31
39
  )
32
40
  })
33
41
  const accountIssueCount = erroredAccounts.length
@@ -22,6 +22,7 @@ import {
22
22
  } from 'lib/seam/devices/use-devices.js'
23
23
  import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
24
24
  import { LoadingToast } from 'lib/ui/LoadingToast/LoadingToast.js'
25
+ import { Snackbar } from 'lib/ui/Snackbar/Snackbar.js'
25
26
  import { EmptyPlaceholder } from 'lib/ui/Table/EmptyPlaceholder.js'
26
27
  import { TableBody } from 'lib/ui/Table/TableBody.js'
27
28
  import { TableHeader } from 'lib/ui/Table/TableHeader.js'
@@ -67,6 +68,8 @@ export function DeviceTable({
67
68
  deviceComparator = compareByCreatedAtDesc,
68
69
  heading = t.devices,
69
70
  title = t.devices,
71
+ errorFilter = () => true,
72
+ warningFilter = () => true,
70
73
  disableLockUnlock = false,
71
74
  disableCreateAccessCode = false,
72
75
  disableEditAccessCode = false,
@@ -77,7 +80,7 @@ export function DeviceTable({
77
80
  }: DeviceTableProps = {}): JSX.Element {
78
81
  useComponentTelemetry('DeviceTable')
79
82
 
80
- const { devices, isInitialLoading, isError, error } = useDevices({
83
+ const { devices, isInitialLoading, isError, refetch } = useDevices({
81
84
  device_ids: deviceIds,
82
85
  connected_account_ids: connectedAccountIds,
83
86
  })
@@ -107,6 +110,8 @@ export function DeviceTable({
107
110
  return (
108
111
  <NestedDeviceDetails
109
112
  deviceId={selectedDeviceId}
113
+ errorFilter={errorFilter}
114
+ warningFilter={warningFilter}
110
115
  disableLockUnlock={disableLockUnlock}
111
116
  disableCreateAccessCode={disableCreateAccessCode}
112
117
  disableEditAccessCode={disableEditAccessCode}
@@ -120,10 +125,6 @@ export function DeviceTable({
120
125
  )
121
126
  }
122
127
 
123
- if (isError) {
124
- return <p className={className}>{error?.message}</p>
125
- }
126
-
127
128
  return (
128
129
  <div className={classNames('seam-device-table', className)}>
129
130
  <ContentHeader onBack={onBack} />
@@ -152,8 +153,25 @@ export function DeviceTable({
152
153
  )}
153
154
  </TableHeader>
154
155
  <TableBody>
155
- <Content devices={filteredDevices} onDeviceClick={handleDeviceClick} />
156
+ <Content
157
+ devices={filteredDevices}
158
+ onDeviceClick={handleDeviceClick}
159
+ errorFilter={errorFilter}
160
+ />
156
161
  </TableBody>
162
+
163
+ <Snackbar
164
+ variant='error'
165
+ visible={isError}
166
+ message={t.fallbackErrorMessage}
167
+ action={{
168
+ label: t.tryAgain,
169
+ onClick: () => {
170
+ void refetch()
171
+ },
172
+ }}
173
+ disableCloseButton
174
+ />
157
175
  </div>
158
176
  )
159
177
  }
@@ -161,8 +179,9 @@ export function DeviceTable({
161
179
  function Content(props: {
162
180
  devices: Array<UseDevicesData[number]>
163
181
  onDeviceClick: (deviceId: string) => void
182
+ errorFilter: (error: any) => boolean
164
183
  }): JSX.Element {
165
- const { devices, onDeviceClick } = props
184
+ const { devices, onDeviceClick, errorFilter } = props
166
185
  const [filter, setFilter] = useState<AccountFilter | DeviceFilter | null>(
167
186
  null
168
187
  )
@@ -198,6 +217,7 @@ function Content(props: {
198
217
  devices={devices}
199
218
  filter={filter}
200
219
  onFilterSelect={setFilter}
220
+ errorFilter={errorFilter}
201
221
  />
202
222
  {filteredDevices.map((device) => (
203
223
  <DeviceRow
@@ -216,4 +236,6 @@ const t = {
216
236
  devices: 'Devices',
217
237
  noDevicesMessage: 'Sorry, no devices were found',
218
238
  loading: 'Loading devices',
239
+ tryAgain: 'Try again',
240
+ fallbackErrorMessage: 'Devices could not be loaded',
219
241
  }
@@ -0,0 +1,45 @@
1
+ import type {
2
+ DeviceModelV1,
3
+ RouteRequestParams,
4
+ RouteResponse,
5
+ } from '@seamapi/types/devicedb'
6
+ import { useQuery } from '@tanstack/react-query'
7
+ import type { SeamError } from 'seamapi'
8
+
9
+ import { useSeamClient } from 'lib/seam/use-seam-client.js'
10
+ import type { UseSeamQueryResult } from 'lib/seam/use-seam-query-result.js'
11
+
12
+ export type UseDeviceModelParams = DeviceModelsGetParams | string
13
+ export type UseDeviceModelData = DeviceModelV1 | null
14
+
15
+ export function useDeviceModel(
16
+ params?: UseDeviceModelParams
17
+ ): UseSeamQueryResult<'deviceModel', UseDeviceModelData> {
18
+ const normalizedParams =
19
+ typeof params === 'string' ? { device_model_id: params } : params
20
+
21
+ const { client: seam } = useSeamClient()
22
+ const { data, ...rest } = useQuery<
23
+ DeviceModelsGetResponse['device_model'] | null,
24
+ SeamError
25
+ >({
26
+ enabled: seam != null,
27
+ queryKey: ['internal', 'device_models', 'get', normalizedParams],
28
+ queryFn: async () => {
29
+ if (seam == null) return null
30
+ const {
31
+ data: { device_model: deviceModel },
32
+ } = await seam.client.get<DeviceModelsGetResponse>(
33
+ '/internal/devicedb/v1/device_models/get',
34
+ { params: normalizedParams }
35
+ )
36
+ return deviceModel
37
+ },
38
+ })
39
+
40
+ return { ...rest, deviceModel: data }
41
+ }
42
+
43
+ type DeviceModelsGetParams = RouteRequestParams<'/v1/device_models/get'>
44
+
45
+ type DeviceModelsGetResponse = RouteResponse<'/v1/device_models/get'>
@@ -0,0 +1,43 @@
1
+ import type {
2
+ DeviceModelV1,
3
+ RouteRequestParams,
4
+ RouteResponse,
5
+ } from '@seamapi/types/devicedb'
6
+ import { useQuery } from '@tanstack/react-query'
7
+ import type { SeamError } from 'seamapi'
8
+
9
+ import { useSeamClient } from 'lib/seam/use-seam-client.js'
10
+ import type { UseSeamQueryResult } from 'lib/seam/use-seam-query-result.js'
11
+
12
+ export type UseDeviceModelsParams = DeviceModelsListParams
13
+ export type UseDeviceModelsData = DeviceModelV1[]
14
+
15
+ export function useDeviceModels(
16
+ params?: UseDeviceModelsParams
17
+ ): UseSeamQueryResult<'deviceModels', UseDeviceModelsData> {
18
+ const { client: seam } = useSeamClient()
19
+
20
+ const { data, ...rest } = useQuery<
21
+ DeviceModelsListResponse['device_models'],
22
+ SeamError
23
+ >({
24
+ enabled: seam != null,
25
+ queryKey: ['internal', 'device_models', 'list', params],
26
+ queryFn: async () => {
27
+ if (seam == null) return []
28
+ const {
29
+ data: { device_models: deviceModels },
30
+ } = await seam.client.get<DeviceModelsListResponse>(
31
+ '/internal/devicedb/v1/device_models/list',
32
+ { params }
33
+ )
34
+ return deviceModels
35
+ },
36
+ })
37
+
38
+ return { ...rest, deviceModels: data }
39
+ }
40
+
41
+ type DeviceModelsListParams = RouteRequestParams<'/v1/device_models/list'>
42
+
43
+ type DeviceModelsListResponse = RouteResponse<'/v1/device_models/list'>
@@ -0,0 +1,45 @@
1
+ import type {
2
+ Manufacturer,
3
+ RouteRequestParams,
4
+ RouteResponse,
5
+ } from '@seamapi/types/devicedb'
6
+ import { useQuery } from '@tanstack/react-query'
7
+ import type { SeamError } from 'seamapi'
8
+
9
+ import { useSeamClient } from 'lib/seam/use-seam-client.js'
10
+ import type { UseSeamQueryResult } from 'lib/seam/use-seam-query-result.js'
11
+
12
+ export type UseManufacturerParams = ManufacturersGetParams | string
13
+ export type UseManufacturerData = Manufacturer | null
14
+
15
+ export function useManufacturer(
16
+ params?: UseManufacturerParams
17
+ ): UseSeamQueryResult<'manufacturer', UseManufacturerData> {
18
+ const normalizedParams =
19
+ typeof params === 'string' ? { manufacturer_id: params } : params
20
+
21
+ const { client: seam } = useSeamClient()
22
+ const { data, ...rest } = useQuery<
23
+ ManufacturersGetResponse['manufacturer'] | null,
24
+ SeamError
25
+ >({
26
+ enabled: seam != null,
27
+ queryKey: ['internal', 'manufacturers', 'get', normalizedParams],
28
+ queryFn: async () => {
29
+ if (seam == null) return null
30
+ const {
31
+ data: { manufacturer },
32
+ } = await seam.client.get<ManufacturersGetResponse>(
33
+ '/internal/devicedb/v1/manufacturers/get',
34
+ { params: normalizedParams }
35
+ )
36
+ return manufacturer
37
+ },
38
+ })
39
+
40
+ return { ...rest, manufacturer: data }
41
+ }
42
+
43
+ type ManufacturersGetParams = RouteRequestParams<'/v1/manufacturers/get'>
44
+
45
+ type ManufacturersGetResponse = RouteResponse<'/v1/manufacturers/get'>
@@ -0,0 +1,43 @@
1
+ import type {
2
+ Manufacturer,
3
+ RouteRequestParams,
4
+ RouteResponse,
5
+ } from '@seamapi/types/devicedb'
6
+ import { useQuery } from '@tanstack/react-query'
7
+ import type { SeamError } from 'seamapi'
8
+
9
+ import { useSeamClient } from 'lib/seam/use-seam-client.js'
10
+ import type { UseSeamQueryResult } from 'lib/seam/use-seam-query-result.js'
11
+
12
+ export type UseManufacturersParams = ManufacturersListParams
13
+ export type UseManufacturersData = Manufacturer[]
14
+
15
+ export function useManufacturers(
16
+ params?: UseManufacturersParams
17
+ ): UseSeamQueryResult<'manufacturers', UseManufacturersData> {
18
+ const { client: seam } = useSeamClient()
19
+
20
+ const { data, ...rest } = useQuery<
21
+ ManufacturersListResponse['manufacturers'],
22
+ SeamError
23
+ >({
24
+ enabled: seam != null,
25
+ queryKey: ['internal', 'manufacturers', 'list', params],
26
+ queryFn: async () => {
27
+ if (seam == null) return []
28
+ const {
29
+ data: { manufacturers },
30
+ } = await seam.client.get<ManufacturersListResponse>(
31
+ '/internal/devicedb/v1/manufacturers/list',
32
+ { params }
33
+ )
34
+ return manufacturers
35
+ },
36
+ })
37
+
38
+ return { ...rest, manufacturers: data }
39
+ }
40
+
41
+ type ManufacturersListParams = RouteRequestParams<'/v1/manufacturers/list'>
42
+
43
+ type ManufacturersListResponse = RouteResponse<'/v1/manufacturers/list'>
@@ -1,8 +1,18 @@
1
1
  import type { ComponentType } from 'react'
2
+ import type {
3
+ AccessCodeError,
4
+ ConnectedAccountError,
5
+ DeviceError,
6
+ SeamWarning,
7
+ } from 'seamapi'
2
8
 
3
9
  export interface RequiredCommonProps {
4
10
  className: string | undefined
5
11
  onBack: (() => void) | undefined
12
+ errorFilter: (
13
+ error: ConnectedAccountError | DeviceError | AccessCodeError
14
+ ) => boolean
15
+ warningFilter: (warning: SeamWarning) => boolean
6
16
  disableDeleteAccessCode: boolean | undefined
7
17
  disableCreateAccessCode: boolean | undefined
8
18
  disableEditAccessCode: boolean | undefined
@@ -0,0 +1,32 @@
1
+ import type {
2
+ AccessCodeError,
3
+ ConnectedAccountError,
4
+ DeviceError,
5
+ SeamWarning,
6
+ } from 'seamapi'
7
+
8
+ type SeamCompositeError = ConnectedAccountError | DeviceError | AccessCodeError
9
+
10
+ export const accessCodeErrorFilter = (error: SeamCompositeError): boolean => {
11
+ return 'is_access_code_error' in error && error.is_access_code_error
12
+ }
13
+
14
+ export const accessCodeWarningFilter = (_: SeamWarning): boolean => {
15
+ return true
16
+ }
17
+
18
+ export const deviceErrorFilter = (error: SeamCompositeError): boolean => {
19
+ return 'is_device_error' in error && error.is_device_error
20
+ }
21
+
22
+ export const deviceWarningFilter = (_: SeamWarning): boolean => {
23
+ return true
24
+ }
25
+
26
+ export const connectedAccountErrorFilter = (
27
+ error: SeamCompositeError
28
+ ): boolean => {
29
+ return (
30
+ 'is_connected_account_error' in error && error.is_connected_account_error
31
+ )
32
+ }
@@ -12,7 +12,7 @@ export interface TelemetryClientOptions {
12
12
  // Implements a compatible Analytics 2.0 API with custom options.
13
13
  // https://segment.com/docs/connections/sources/catalog/libraries/website/javascript/
14
14
  export class TelemetryClient {
15
- #queue: Queue
15
+ readonly #queue: Queue
16
16
  #anonymousId: string | null
17
17
 
18
18
  #endpoint: string
@@ -154,7 +154,7 @@ export class TelemetryClient {
154
154
  }
155
155
  }
156
156
 
157
- #push = (message: Message): void => {
157
+ readonly #push = (message: Message): void => {
158
158
  if (this.#disabled) return
159
159
  this.#queue.push(async () => {
160
160
  const payload: Payload = {
@@ -178,7 +178,7 @@ export class TelemetryClient {
178
178
  })
179
179
  }
180
180
 
181
- #log = (
181
+ readonly #log = (
182
182
  method: string,
183
183
  ...args: Array<string | Traits | Properties>
184
184
  ): void => {
@@ -11,7 +11,7 @@ interface SnackbarProps {
11
11
  message: string
12
12
  variant: SnackbarVariant
13
13
  visible: boolean
14
- onClose: () => void
14
+ onClose?: () => void
15
15
  action?: {
16
16
  label: string
17
17
  onClick: () => void
@@ -29,7 +29,7 @@ export function Snackbar({
29
29
  autoDismiss = false,
30
30
  dismissAfterMs = 5000,
31
31
  disableCloseButton = false,
32
- onClose,
32
+ onClose = () => {},
33
33
  }: SnackbarProps): JSX.Element {
34
34
  const { label: actionLabel, onClick: handleActionClick } = action ?? {}
35
35
 
@@ -1,3 +1,3 @@
1
- const seamapiReactVersion = '1.64.0'
1
+ const seamapiReactVersion = '1.65.0'
2
2
 
3
3
  export default seamapiReactVersion
@@ -99,8 +99,7 @@
99
99
  grid-auto-rows: 1fr;
100
100
  font-size: 14px;
101
101
  line-height: 134%;
102
- row-gap: 4px;
103
- column-gap: 28px;
102
+ gap: 4px 28px;
104
103
 
105
104
  .seam-label {
106
105
  color: colors.$text-gray-2;
@@ -498,8 +498,7 @@
498
498
  width: auto;
499
499
  display: grid;
500
500
  grid-template-columns: auto auto;
501
- column-gap: 16px;
502
- row-gap: 8px;
501
+ gap: 8px 16px;
503
502
  }
504
503
 
505
504
  .seam-thermostat-property-block {