@seamapi/react 1.35.0 → 1.37.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 (40) hide show
  1. package/README.md +1 -1
  2. package/dist/elements.js +4501 -4476
  3. package/dist/elements.js.map +1 -1
  4. package/lib/seam/SeamProvider.js +16 -12
  5. package/lib/seam/SeamProvider.js.map +1 -1
  6. package/lib/seam/access-codes/use-create-access-code.js +3 -4
  7. package/lib/seam/access-codes/use-create-access-code.js.map +1 -1
  8. package/lib/seam/components/AccessCodeTable/AccessCodeTable.d.ts +2 -1
  9. package/lib/seam/components/AccessCodeTable/AccessCodeTable.js +2 -2
  10. package/lib/seam/components/AccessCodeTable/AccessCodeTable.js.map +1 -1
  11. package/lib/seam/components/DeviceTable/DeviceTable.d.ts +2 -1
  12. package/lib/seam/components/DeviceTable/DeviceTable.js +2 -2
  13. package/lib/seam/components/DeviceTable/DeviceTable.js.map +1 -1
  14. package/lib/seam/connect-webviews/use-create-connect-webview.js +3 -4
  15. package/lib/seam/connect-webviews/use-create-connect-webview.js.map +1 -1
  16. package/lib/seam/devices/use-toggle-lock.js +3 -4
  17. package/lib/seam/devices/use-toggle-lock.js.map +1 -1
  18. package/lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedules.d.ts +5 -0
  19. package/lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedules.js +29 -0
  20. package/lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedules.js.map +1 -0
  21. package/lib/seam/use-seam-client.d.ts +3 -0
  22. package/lib/seam/use-seam-client.js +12 -0
  23. package/lib/seam/use-seam-client.js.map +1 -1
  24. package/lib/ui/RadioField/RadioField.d.ts +1 -1
  25. package/lib/ui/RadioField/RadioField.js +2 -2
  26. package/lib/ui/RadioField/RadioField.js.map +1 -1
  27. package/lib/version.d.ts +1 -1
  28. package/lib/version.js +1 -1
  29. package/package.json +2 -2
  30. package/src/elements.ts +1 -1
  31. package/src/lib/seam/SeamProvider.tsx +27 -16
  32. package/src/lib/seam/access-codes/use-create-access-code.ts +2 -5
  33. package/src/lib/seam/components/AccessCodeTable/AccessCodeTable.tsx +10 -3
  34. package/src/lib/seam/components/DeviceTable/DeviceTable.tsx +9 -3
  35. package/src/lib/seam/connect-webviews/use-create-connect-webview.ts +2 -5
  36. package/src/lib/seam/devices/use-toggle-lock.ts +2 -5
  37. package/src/lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedules.ts +53 -0
  38. package/src/lib/seam/use-seam-client.ts +15 -0
  39. package/src/lib/ui/RadioField/RadioField.tsx +6 -5
  40. package/src/lib/version.ts +1 -1
@@ -34,6 +34,7 @@ export interface DeviceTableProps {
34
34
  onDeviceClick?: (deviceId: string) => void
35
35
  preventDefaultOnDeviceClick?: boolean
36
36
  onBack?: () => void
37
+ title?: string | null
37
38
  className?: string
38
39
  }
39
40
 
@@ -56,6 +57,7 @@ export function DeviceTable({
56
57
  onBack,
57
58
  deviceFilter = defaultDeviceFilter,
58
59
  deviceComparator = compareByCreatedAtDesc,
60
+ title = t.devices,
59
61
  className,
60
62
  }: DeviceTableProps = {}): JSX.Element {
61
63
  const { devices, isLoading, isError, error } = useDevices({
@@ -109,9 +111,13 @@ export function DeviceTable({
109
111
  <div className={classNames('seam-device-table', className)}>
110
112
  <ContentHeader onBack={onBack} />
111
113
  <TableHeader>
112
- <TableTitle>
113
- {t.devices} <Caption>({filteredDevices.length})</Caption>
114
- </TableTitle>
114
+ {title != null ? (
115
+ <TableTitle>
116
+ {title ?? t.devices} <Caption>({filteredDevices.length})</Caption>
117
+ </TableTitle>
118
+ ) : (
119
+ <div className='seam-fragment' />
120
+ )}
115
121
  {!disableSearch && (
116
122
  <SearchTextField
117
123
  value={searchInputValue}
@@ -6,7 +6,7 @@ import type {
6
6
  SeamError,
7
7
  } from 'seamapi'
8
8
 
9
- import { useSeamClient } from 'lib/seam/use-seam-client.js'
9
+ import { NullSeamClientError, useSeamClient } from 'lib/seam/use-seam-client.js'
10
10
 
11
11
  export interface UseCreateConnectWebviewParams {
12
12
  willNavigateToWebview?: boolean
@@ -32,10 +32,7 @@ export function useCreateConnectWebview({
32
32
  mutationFn: async (
33
33
  mutationParams: UseCreateConnectWebviewMutationParams
34
34
  ) => {
35
- if (client == null) {
36
- throw new Error('Missing seam client')
37
- }
38
-
35
+ if (client === null) throw new NullSeamClientError()
39
36
  return await client.connectWebviews.create(mutationParams)
40
37
  },
41
38
  onSuccess: ({ url }) => {
@@ -11,7 +11,7 @@ import {
11
11
  type SeamError,
12
12
  } from 'seamapi'
13
13
 
14
- import { useSeamClient } from 'lib/seam/use-seam-client.js'
14
+ import { NullSeamClientError, useSeamClient } from 'lib/seam/use-seam-client.js'
15
15
 
16
16
  export function useToggleLock({
17
17
  device_id: deviceId,
@@ -26,10 +26,7 @@ export function useToggleLock({
26
26
 
27
27
  return useMutation<{ actionAttempt: ActionAttempt }, SeamError>({
28
28
  mutationFn: async () => {
29
- if (client == null) {
30
- throw new Error('Missing seam client')
31
- }
32
-
29
+ if (client === null) throw new NullSeamClientError()
33
30
  const toggle = locked ? client.locks.unlockDoor : client.locks.lockDoor
34
31
  return await toggle(deviceId)
35
32
  },
@@ -0,0 +1,53 @@
1
+ import { useQuery, useQueryClient } from '@tanstack/react-query'
2
+ import type {
3
+ ClimateSettingSchedule,
4
+ ClimateSettingSchedulesListRequest,
5
+ ClimateSettingSchedulesListResponse,
6
+ SeamError,
7
+ } 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 UseClimateSettingSchedulesParams =
13
+ ClimateSettingSchedulesListRequest
14
+ export type UseClimateSettingSchedulesData = ClimateSettingSchedule[]
15
+
16
+ export function useClimateSettingSchedules(
17
+ params: UseClimateSettingSchedulesParams
18
+ ): UseSeamQueryResult<
19
+ 'climateSettingSchedules',
20
+ UseClimateSettingSchedulesData
21
+ > {
22
+ const { client } = useSeamClient()
23
+ const queryClient = useQueryClient()
24
+
25
+ const { data, ...rest } = useQuery<
26
+ ClimateSettingSchedulesListResponse['climate_setting_schedules'],
27
+ SeamError
28
+ >({
29
+ enabled: client != null,
30
+ queryKey: ['thermostats', 'climate_setting_schedules', 'list', params],
31
+ queryFn: async () => {
32
+ if (client == null) return []
33
+ return await client.thermostats.climateSettingSchedules.list(params)
34
+ },
35
+ onSuccess: (schedules) => {
36
+ // Prime cache for each schedule.
37
+ for (const schedule of schedules) {
38
+ queryClient.setQueryData(
39
+ [
40
+ 'climate_setting_schedules',
41
+ 'get',
42
+ {
43
+ climate_setting_schedule_id: schedule.climate_setting_schedule_id,
44
+ },
45
+ ],
46
+ schedule
47
+ )
48
+ }
49
+ },
50
+ })
51
+
52
+ return { ...rest, climateSettingSchedules: data }
53
+ }
@@ -71,6 +71,21 @@ export function useSeamClient(): {
71
71
  return { client: data ?? null, isLoading, isError, error }
72
72
  }
73
73
 
74
+ export class NullSeamClientError extends Error {
75
+ constructor() {
76
+ super(
77
+ [
78
+ 'Attempted to use a null Seam client.',
79
+ 'Either a hook using useSeamClient was called outside of a SeamProvider,',
80
+ 'or there was an error when creating the Seam client in useSeamClient,',
81
+ 'or useSeamClient is still loading the client.',
82
+ ].join(' ')
83
+ )
84
+ this.name = this.constructor.name
85
+ Error.captureStackTrace(this, this.constructor)
86
+ }
87
+ }
88
+
74
89
  function useUserIdentifierKeyOrFingerprint(
75
90
  userIdentifierKey: string | undefined
76
91
  ): string {
@@ -14,11 +14,12 @@ interface RadioOption<Value> {
14
14
  value: Value
15
15
  }
16
16
 
17
- type RadioFieldContext<Value extends string> =
18
- | Omit<RadioFieldProps<Value>, 'options'>
19
- | undefined
17
+ type RadioFieldContext<Value extends string> = Omit<
18
+ RadioFieldProps<Value>,
19
+ 'options'
20
+ > | null
20
21
 
21
- const radioFieldContext = createContext<RadioFieldContext<any>>(undefined)
22
+ const radioFieldContext = createContext<RadioFieldContext<any>>(null)
22
23
 
23
24
  export function RadioField<Value extends string>({
24
25
  value,
@@ -48,7 +49,7 @@ export function useRadioField<Value extends string>(): NonNullable<
48
49
  RadioFieldContext<Value>
49
50
  > {
50
51
  const context = useContext<RadioFieldContext<Value>>(radioFieldContext)
51
- if (context === undefined) {
52
+ if (context === null) {
52
53
  throw new Error('useRadioField must be used within a <RadioField/>')
53
54
  }
54
55
  return context
@@ -1,3 +1,3 @@
1
- const seamapiReactVersion = '1.35.0'
1
+ const seamapiReactVersion = '1.37.0'
2
2
 
3
3
  export default seamapiReactVersion