@seamapi/react 1.34.0 → 1.36.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 (52) hide show
  1. package/README.md +1 -1
  2. package/dist/elements.js +3880 -3856
  3. package/dist/elements.js.map +1 -1
  4. package/lib/icons/ClimateSettingSchedule.d.ts +2 -0
  5. package/lib/icons/ClimateSettingSchedule.js +5 -0
  6. package/lib/icons/ClimateSettingSchedule.js.map +1 -0
  7. package/lib/icons/ThermostatCool.d.ts +2 -0
  8. package/lib/icons/ThermostatCool.js +5 -0
  9. package/lib/icons/ThermostatCool.js.map +1 -0
  10. package/lib/icons/ThermostatHeat.d.ts +2 -0
  11. package/lib/icons/ThermostatHeat.js +5 -0
  12. package/lib/icons/ThermostatHeat.js.map +1 -0
  13. package/lib/icons/ThermostatHeatCool.d.ts +2 -0
  14. package/lib/icons/ThermostatHeatCool.js +5 -0
  15. package/lib/icons/ThermostatHeatCool.js.map +1 -0
  16. package/lib/icons/ThermostatOff.d.ts +2 -0
  17. package/lib/icons/ThermostatOff.js +5 -0
  18. package/lib/icons/ThermostatOff.js.map +1 -0
  19. package/lib/seam/SeamProvider.js +16 -12
  20. package/lib/seam/SeamProvider.js.map +1 -1
  21. package/lib/seam/access-codes/use-create-access-code.js +3 -4
  22. package/lib/seam/access-codes/use-create-access-code.js.map +1 -1
  23. package/lib/seam/connect-webviews/use-create-connect-webview.js +3 -4
  24. package/lib/seam/connect-webviews/use-create-connect-webview.js.map +1 -1
  25. package/lib/seam/devices/use-toggle-lock.js +3 -4
  26. package/lib/seam/devices/use-toggle-lock.js.map +1 -1
  27. package/lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedules.d.ts +5 -0
  28. package/lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedules.js +29 -0
  29. package/lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedules.js.map +1 -0
  30. package/lib/seam/use-seam-client.d.ts +3 -0
  31. package/lib/seam/use-seam-client.js +12 -0
  32. package/lib/seam/use-seam-client.js.map +1 -1
  33. package/lib/ui/RadioField/RadioField.d.ts +1 -1
  34. package/lib/ui/RadioField/RadioField.js +2 -2
  35. package/lib/ui/RadioField/RadioField.js.map +1 -1
  36. package/lib/version.d.ts +1 -1
  37. package/lib/version.js +1 -1
  38. package/package.json +2 -2
  39. package/src/elements.ts +1 -1
  40. package/src/lib/icons/ClimateSettingSchedule.tsx +25 -0
  41. package/src/lib/icons/ThermostatCool.tsx +23 -0
  42. package/src/lib/icons/ThermostatHeat.tsx +23 -0
  43. package/src/lib/icons/ThermostatHeatCool.tsx +27 -0
  44. package/src/lib/icons/ThermostatOff.tsx +21 -0
  45. package/src/lib/seam/SeamProvider.tsx +27 -16
  46. package/src/lib/seam/access-codes/use-create-access-code.ts +2 -5
  47. package/src/lib/seam/connect-webviews/use-create-connect-webview.ts +2 -5
  48. package/src/lib/seam/devices/use-toggle-lock.ts +2 -5
  49. package/src/lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedules.ts +53 -0
  50. package/src/lib/seam/use-seam-client.ts +15 -0
  51. package/src/lib/ui/RadioField/RadioField.tsx +6 -5
  52. package/src/lib/version.ts +1 -1
@@ -150,13 +150,7 @@ const defaultSeamContextValue = createDefaultSeamContextValue()
150
150
  export const seamContext = createContext<SeamContext>(defaultSeamContextValue)
151
151
 
152
152
  export function useSeamContext(): SeamContext {
153
- const context = useContext(seamContext)
154
-
155
- if (context == null) {
156
- throw new Error('useSeamContext must be used inside a <SeamProvider/>')
157
- }
158
-
159
- return context
153
+ return useContext(seamContext)
160
154
  }
161
155
 
162
156
  const isSeamProviderPropsWithClient = (
@@ -167,8 +161,11 @@ const isSeamProviderPropsWithClient = (
167
161
  const { client } = props
168
162
  if (client == null) return false
169
163
 
170
- if (Object.values(props).some((v) => v == null)) {
171
- throw new Error('Cannot provide a Seam client along with other options.')
164
+ const otherNonNullProps = Object.values(props).filter((v) => v != null)
165
+ if (otherNonNullProps.length > 0) {
166
+ throw new InvalidSeamProviderProps(
167
+ `The client prop cannot be used with ${otherNonNullProps.join(' or ')}.`
168
+ )
172
169
  }
173
170
 
174
171
  return true
@@ -183,12 +180,14 @@ const isSeamProviderPropsWithPublishableKey = (
183
180
  if (publishableKey == null) return false
184
181
 
185
182
  if ('client' in props && props.client != null) {
186
- throw new Error('Cannot provide a Seam client along with other options.')
183
+ throw new InvalidSeamProviderProps(
184
+ 'The client prop cannot be used with the publishableKey prop.'
185
+ )
187
186
  }
188
187
 
189
188
  if ('clientSessionToken' in props && props.clientSessionToken != null) {
190
- throw new Error(
191
- 'Cannot provide both a publishableKey and a clientSessionToken.'
189
+ throw new InvalidSeamProviderProps(
190
+ 'The clientSessionToken prop cannot be used with the publishableKey prop.'
192
191
  )
193
192
  }
194
193
 
@@ -205,18 +204,30 @@ const isSeamProviderPropsWithClientSessionToken = (
205
204
  if (clientSessionToken == null) return false
206
205
 
207
206
  if ('client' in props && props.client != null) {
208
- throw new Error('Cannot provide a Seam client along with other options.')
207
+ throw new InvalidSeamProviderProps(
208
+ 'The client prop cannot be used with the clientSessionToken prop.'
209
+ )
209
210
  }
210
211
 
211
212
  if ('publishableKey' in props && props.publishableKey != null) {
212
- throw new Error(
213
- 'Cannot provide both a clientSessionToken and a publishableKey.'
213
+ throw new InvalidSeamProviderProps(
214
+ 'The publishableKey prop cannot be used with the clientSessionToken prop.'
214
215
  )
215
216
  }
216
217
 
217
218
  if ('userIdentifierKey' in props && props.userIdentifierKey != null) {
218
- throw new Error('Cannot use a userIdentifierKey with a clientSessionToken.')
219
+ throw new InvalidSeamProviderProps(
220
+ 'The userIdentifierKey prop cannot be used with the clientSessionToken prop.'
221
+ )
219
222
  }
220
223
 
221
224
  return true
222
225
  }
226
+
227
+ class InvalidSeamProviderProps extends Error {
228
+ constructor(message: string) {
229
+ super(`SeamProvider received invalid props: ${message}`)
230
+ this.name = this.constructor.name
231
+ Error.captureStackTrace(this, this.constructor)
232
+ }
233
+ }
@@ -10,7 +10,7 @@ import type {
10
10
  SeamError,
11
11
  } from 'seamapi'
12
12
 
13
- import { useSeamClient } from 'lib/seam/use-seam-client.js'
13
+ import { NullSeamClientError, useSeamClient } from 'lib/seam/use-seam-client.js'
14
14
 
15
15
  export type UseCreateAccessCodeParams = never
16
16
  export type UseCreateAccessCodeData = AccessCode
@@ -30,10 +30,7 @@ export function useCreateAccessCode(): UseMutationResult<
30
30
  AccessCodeCreateRequest
31
31
  >({
32
32
  mutationFn: async (mutationParams: UseCreateAccessCodeMutationParams) => {
33
- if (client === null) {
34
- throw new Error('Missing seam client')
35
- }
36
-
33
+ if (client === null) throw new NullSeamClientError()
37
34
  return await client.accessCodes.create(mutationParams)
38
35
  },
39
36
  onSuccess: () => {
@@ -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.34.0'
1
+ const seamapiReactVersion = '1.36.0'
2
2
 
3
3
  export default seamapiReactVersion