@seamapi/react 1.50.0 → 1.51.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 (31) hide show
  1. package/README.md +1 -1
  2. package/dist/elements.js +9778 -8689
  3. package/dist/elements.js.map +1 -1
  4. package/dist/index.css +22 -0
  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/icons/Bee.d.ts +2 -0
  9. package/lib/icons/Bee.js +5 -0
  10. package/lib/icons/Bee.js.map +1 -0
  11. package/lib/seam/components/DeviceDetails/DeviceDetails.js +5 -1
  12. package/lib/seam/components/DeviceDetails/DeviceDetails.js.map +1 -1
  13. package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.d.ts +7 -0
  14. package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.js +66 -0
  15. package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.js.map +1 -0
  16. package/lib/seam/connected-accounts/use-connected-account.d.ts +2 -1
  17. package/lib/seam/connected-accounts/use-connected-account.js.map +1 -1
  18. package/lib/ui/layout/DetailRow.d.ts +2 -1
  19. package/lib/ui/layout/DetailRow.js +5 -2
  20. package/lib/ui/layout/DetailRow.js.map +1 -1
  21. package/lib/version.d.ts +1 -1
  22. package/lib/version.js +1 -1
  23. package/package.json +1 -1
  24. package/src/lib/icons/Bee.tsx +21 -0
  25. package/src/lib/seam/components/DeviceDetails/DeviceDetails.tsx +6 -1
  26. package/src/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.tsx +175 -0
  27. package/src/lib/seam/connected-accounts/use-connected-account.ts +2 -1
  28. package/src/lib/ui/layout/DetailRow.tsx +9 -1
  29. package/src/lib/version.ts +1 -1
  30. package/src/styles/_device-details.scss +4 -0
  31. package/src/styles/_layout.scss +21 -0
@@ -1,5 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- export function DetailRow({ label, sublabel, children, }) {
3
- return (_jsxs("div", { className: 'seam-detail-row', children: [_jsxs("div", { className: 'seam-detail-row-label-wrap', children: [_jsx("p", { className: 'seam-row-label', children: label }), sublabel != null && _jsx("p", { className: 'seam-row-sublabel', children: sublabel })] }), _jsx("div", { className: 'seam-detail-row-right-area-content', children: children })] }));
2
+ import classNames from 'classnames';
3
+ export function DetailRow({ label, sublabel, onClick, children, }) {
4
+ return (_jsxs("div", { className: classNames('seam-detail-row', {
5
+ 'seam-detail-row-clickable': onClick != null,
6
+ }), onClick: onClick, children: [_jsxs("div", { className: 'seam-detail-row-label-wrap', children: [_jsx("p", { className: 'seam-row-label', children: label }), sublabel != null && _jsx("p", { className: 'seam-row-sublabel', children: sublabel })] }), _jsx("div", { className: 'seam-detail-row-right-area-content', children: children })] }));
4
7
  }
5
8
  //# sourceMappingURL=DetailRow.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DetailRow.js","sourceRoot":"","sources":["../../../src/lib/ui/layout/DetailRow.tsx"],"names":[],"mappings":";AAOA,MAAM,UAAU,SAAS,CAAC,EACxB,KAAK,EACL,QAAQ,EACR,QAAQ,GAC0B;IAClC,OAAO,CACL,eAAK,SAAS,EAAC,iBAAiB,aAC9B,eAAK,SAAS,EAAC,4BAA4B,aACzC,YAAG,SAAS,EAAC,gBAAgB,YAAE,KAAK,GAAK,EACxC,QAAQ,IAAI,IAAI,IAAI,YAAG,SAAS,EAAC,mBAAmB,YAAE,QAAQ,GAAK,IAChE,EACN,cAAK,SAAS,EAAC,oCAAoC,YAAE,QAAQ,GAAO,IAChE,CACP,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"DetailRow.js","sourceRoot":"","sources":["../../../src/lib/ui/layout/DetailRow.tsx"],"names":[],"mappings":";AAAA,OAAO,UAAU,MAAM,YAAY,CAAA;AASnC,MAAM,UAAU,SAAS,CAAC,EACxB,KAAK,EACL,QAAQ,EACR,OAAO,EACP,QAAQ,GAC0B;IAClC,OAAO,CACL,eACE,SAAS,EAAE,UAAU,CAAC,iBAAiB,EAAE;YACvC,2BAA2B,EAAE,OAAO,IAAI,IAAI;SAC7C,CAAC,EACF,OAAO,EAAE,OAAO,aAEhB,eAAK,SAAS,EAAC,4BAA4B,aACzC,YAAG,SAAS,EAAC,gBAAgB,YAAE,KAAK,GAAK,EACxC,QAAQ,IAAI,IAAI,IAAI,YAAG,SAAS,EAAC,mBAAmB,YAAE,QAAQ,GAAK,IAChE,EACN,cAAK,SAAS,EAAC,oCAAoC,YAAE,QAAQ,GAAO,IAChE,CACP,CAAA;AACH,CAAC"}
package/lib/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- declare const seamapiReactVersion = "1.50.0";
1
+ declare const seamapiReactVersion = "1.51.0";
2
2
  export default seamapiReactVersion;
package/lib/version.js CHANGED
@@ -1,3 +1,3 @@
1
- const seamapiReactVersion = '1.50.0';
1
+ const seamapiReactVersion = '1.51.0';
2
2
  export default seamapiReactVersion;
3
3
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seamapi/react",
3
- "version": "1.50.0",
3
+ "version": "1.51.0",
4
4
  "description": "Seam Components.",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -0,0 +1,21 @@
1
+ /*
2
+ * Automaically generated by SVGR from assets/icons/*.svg.
3
+ * Do not edit this file or add other components to this directory.
4
+ */
5
+ import type { SVGProps } from 'react'
6
+ export function BeeIcon(props: SVGProps<SVGSVGElement>): JSX.Element {
7
+ return (
8
+ <svg
9
+ xmlns='http://www.w3.org/2000/svg'
10
+ width={33}
11
+ height={33}
12
+ fill='none'
13
+ {...props}
14
+ >
15
+ <path
16
+ fill='#5DBE77'
17
+ d='M23.902 25.469c-.18.263-3.2-.2-4.15-5.212-.95-5.01 1.214-5.411 1.214-5.411s2.745-.79 4.086 4.938c1.225 5.21-1.15 5.685-1.15 5.685Zm-8.437-6.917h-.01c-1.468-.98-1.996-1.853-1.996-1.853 1.257-.18 2.724-.958 2.724-.958l.813.568v.01l.834.548s-.18 1.643.106 2.874c0 0-1.014-.168-2.46-1.168m-9.63-5.327s-.422-2.4 4.931-3.18c5.881-.852 6.156 2 6.156 2s.412 2.18-4.646 3.138c-5.068.958-6.62-1.695-6.44-1.958Zm14.149-6.117c.612.421.77 1.242.348 1.853a1.33 1.33 0 0 1-1.858.347 1.322 1.322 0 0 1-.348-1.852 1.33 1.33 0 0 1 1.858-.348Zm4.445 3.022c.612.41.77 1.242.36 1.853-.413.61-1.247.758-1.86.347a1.322 1.322 0 0 1-.348-1.853 1.33 1.33 0 0 1 1.859-.347m2.523 10.58c-.37-3.053-2.006-5.496-2.64-6.19 0 0-.063-.021-.01-.148.053-.126.158-.495.158-.495s0-.042.074-.063c.074-.02.834-.179 1.426-1.042.59-.863.971-2.653-1.046-4.022 0 0-.01 0-.031-.094-.01-.085-.338-1.548-1.225-2.159-.887-.6-2.376-.368-2.46-.347-.085.021-.095 0-.095 0-2.017-1.369-3.548-.358-4.14.505-.59.864-.453 1.632-.453 1.706 0 .074-.032.084-.032.084l-.401.327c-.095.084-.138.042-.138.042-.886-.337-3.769-.969-6.747-.19-2.977.78-4.16 1.874-4.814 2.832-.655.958-1.024 2.874 1.024 4.264 2.048 1.39 4.952 1.263 4.952 1.263.084 0 .095.063.095.063.707 2.506 3.051 3.97 3.21 4.075.158.116 2.386 1.747 4.973 1.484 0 0 .063-.01.095.074 0 0 .95 2.737 2.988 4.127 2.048 1.39 3.696.347 4.35-.61.655-.959 1.246-2.454.887-5.496m-9.914 3.074s-1.964.084-4.213-1.443c-2.25-1.526-2.893-3.38-2.893-3.38-.053-.146-.106-.052-.106-.052-.602.885-.781 1.39-.443 2.8.327 1.359 1.974 2.517 2.09 2.601.116.074 1.795 1.18 3.189.99 1.436-.2 1.848-.558 2.45-1.443 0 0 .063-.084-.085-.073m-4.424 2.39s-.95 0-1.943-.664l-.507.737.507-.747c-.992-.674-1.34-1.558-1.34-1.558-.16-.243-.201 0-.201 0-.55 2.116.39 3.032.475 3.105.095.042 1.298.58 3.072-.705 0 0 .211-.126-.074-.179'
18
+ />
19
+ </svg>
20
+ )
21
+ }
@@ -1,6 +1,7 @@
1
- import { isLockDevice } from 'seamapi'
1
+ import { isLockDevice, isThermostatDevice } from 'seamapi'
2
2
 
3
3
  import { LockDeviceDetails } from 'lib/seam/components/DeviceDetails/LockDeviceDetails.js'
4
+ import { ThermostatDeviceDetails } from 'lib/seam/components/DeviceDetails/ThermostatDeviceDetails.js'
4
5
  import { useDevice } from 'lib/seam/devices/use-device.js'
5
6
 
6
7
  export interface DeviceDetailsProps {
@@ -35,5 +36,9 @@ export function DeviceDetails({
35
36
  )
36
37
  }
37
38
 
39
+ if (isThermostatDevice(device)) {
40
+ return <ThermostatDeviceDetails device={device} />
41
+ }
42
+
38
43
  return null
39
44
  }
@@ -0,0 +1,175 @@
1
+ import classNames from 'classnames'
2
+ import { useState } from 'react'
3
+ import type { ThermostatDevice } from 'seamapi'
4
+
5
+ import { BeeIcon } from 'lib/icons/Bee.js'
6
+ import { ChevronWideIcon } from 'lib/icons/ChevronWide.js'
7
+ import { ClimateSettingScheduleTable } from 'lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.js'
8
+ import { useConnectedAccount } from 'lib/seam/connected-accounts/use-connected-account.js'
9
+ import { useClimateSettingSchedules } from 'lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedules.js'
10
+ import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
11
+ import { DetailRow } from 'lib/ui/layout/DetailRow.js'
12
+ import { DetailSection } from 'lib/ui/layout/DetailSection.js'
13
+ import { DetailSectionGroup } from 'lib/ui/layout/DetailSectionGroup.js'
14
+ import { ClimateSettingStatus } from 'lib/ui/thermostat/ClimateSettingStatus.js'
15
+ import { ThermostatCard } from 'lib/ui/thermostat/ThermostatCard.js'
16
+
17
+ export function ThermostatDeviceDetails(props: {
18
+ device: ThermostatDevice
19
+ onBack?: () => void
20
+ className?: string
21
+ }): JSX.Element | null {
22
+ const { device, onBack, className } = props
23
+
24
+ const [climateSettingsOpen, setClimateSettingsOpen] = useState(false)
25
+
26
+ const { connectedAccount } = useConnectedAccount(device.connected_account_id)
27
+
28
+ const {
29
+ climateSettingSchedules,
30
+ isLoading: isLoadingClimateSchedules,
31
+ isError: isErrorClimateSchedules,
32
+ } = useClimateSettingSchedules({
33
+ device_id: device.device_id,
34
+ })
35
+
36
+ const isClimateSchedulesPlural = climateSettingSchedules?.length !== 1
37
+
38
+ if (climateSettingsOpen) {
39
+ return (
40
+ <ClimateSettingScheduleTable
41
+ deviceId={device.device_id}
42
+ onBack={() => {
43
+ setClimateSettingsOpen(false)
44
+ }}
45
+ />
46
+ )
47
+ }
48
+
49
+ if (device == null) {
50
+ return null
51
+ }
52
+
53
+ return (
54
+ <div className={classNames('seam-device-details', className)}>
55
+ <ContentHeader title={t.thermostat} onBack={onBack} />
56
+
57
+ <div className='seam-body'>
58
+ <ThermostatCard device={device} />
59
+
60
+ <div className='seam-thermostat-device-details'>
61
+ <DetailSectionGroup>
62
+ <DetailSection
63
+ label={t.scheduledClimates}
64
+ tooltipContent={t.scheduledClimatesTooltip}
65
+ >
66
+ <DetailRow
67
+ label={
68
+ isLoadingClimateSchedules || isErrorClimateSchedules
69
+ ? t.viewingClimateSchedules
70
+ : `${climateSettingSchedules?.length} ${
71
+ isClimateSchedulesPlural
72
+ ? t.climateSchedules
73
+ : t.climateSchedule
74
+ }`
75
+ }
76
+ onClick={() => {
77
+ setClimateSettingsOpen(true)
78
+ }}
79
+ >
80
+ <div className='seam-detail-row-rotated-icon'>
81
+ <ChevronWideIcon />
82
+ </div>
83
+ </DetailRow>
84
+ </DetailSection>
85
+
86
+ <DetailSection
87
+ label={t.currentSettings}
88
+ tooltipContent={t.currentSettingsTooltip}
89
+ >
90
+ <DetailRow label={t.climate}>
91
+ <ClimateSettingStatus
92
+ climateSetting={device.properties.current_climate_setting}
93
+ temperatureUnit='fahrenheit'
94
+ />
95
+ </DetailRow>
96
+ </DetailSection>
97
+
98
+ <DetailSection
99
+ label={t.defaultSettings}
100
+ tooltipContent={t.defaultSettingsTooltip}
101
+ >
102
+ <DetailRow label={t.defaultClimate}>
103
+ {/* @ts-expect-error not currently included in sdk */}
104
+ {device.properties.default_climate_setting != null ? (
105
+ <ClimateSettingStatus
106
+ climateSetting={device.properties.current_climate_setting}
107
+ temperatureUnit='fahrenheit'
108
+ />
109
+ ) : (
110
+ <p>{t.none}</p>
111
+ )}
112
+ </DetailRow>
113
+ <DetailRow label={t.allowManualOverride}>
114
+ <p>
115
+ {device.properties.current_climate_setting
116
+ .manual_override_allowed
117
+ ? t.yes
118
+ : t.no}
119
+ </p>
120
+ </DetailRow>
121
+ </DetailSection>
122
+
123
+ <DetailSection
124
+ label={t.deviceDetails}
125
+ tooltipContent={t.deviceDetailsTooltip}
126
+ >
127
+ <DetailRow label={t.brand}>
128
+ <div className='seam-detail-row-hstack'>
129
+ {device.properties.model.manufacturer_display_name}
130
+ {device.properties.manufacturer === 'ecobee' && <BeeIcon />}
131
+ </div>
132
+ </DetailRow>
133
+ <DetailRow
134
+ label={t.linkedAccount}
135
+ sublabel={
136
+ connectedAccount?.user_identifier?.email ??
137
+ device.connected_account_id
138
+ }
139
+ />
140
+ <DetailRow label={t.deviceId} sublabel={device.device_id} />
141
+ </DetailSection>
142
+ </DetailSectionGroup>
143
+ </div>
144
+ </div>
145
+ </div>
146
+ )
147
+ }
148
+
149
+ const t = {
150
+ thermostat: 'Thermostat',
151
+ climateSchedule: 'scheduled climate',
152
+ climateSchedules: 'scheduled climates',
153
+ viewingClimateSchedules: 'View scheduled climates',
154
+ scheduledClimates: 'Scheduled climates',
155
+ scheduledClimatesTooltip:
156
+ "Scheduled climates let you automatically change the thermostat's climate at a set time.",
157
+ currentSettings: 'Current settings',
158
+ currentSettingsTooltip:
159
+ 'These are the settings currently on the device. If you change them here, they change on the device.',
160
+ climate: 'Climate',
161
+ defaultSettings: 'Default settings',
162
+ defaultSettingsTooltip:
163
+ 'When a scheduled climate reaches its end time, the default settings will kick in.',
164
+ defaultClimate: 'Default climate',
165
+ allowManualOverride: 'Allow manual override',
166
+ deviceDetails: 'Device details',
167
+ deviceDetailsTooltip:
168
+ 'When a scheduled climate reaches its end time, the default settings will kick in.',
169
+ brand: 'Brand',
170
+ linkedAccount: 'Linked account',
171
+ deviceId: 'Device ID',
172
+ none: 'None',
173
+ yes: 'Yes',
174
+ no: 'No',
175
+ }
@@ -9,10 +9,11 @@ import type {
9
9
  import { useSeamClient } from 'lib/seam/use-seam-client.js'
10
10
  import type { UseSeamQueryResult } from 'lib/seam/use-seam-query-result.js'
11
11
 
12
+ export type UseConnectedAccountParams = ConnectedAccountsGetRequest | string
12
13
  export type UseConnectedAccountData = ConnectedAccount | null
13
14
 
14
15
  export function useConnectedAccount(
15
- params: ConnectedAccountsGetRequest
16
+ params: UseConnectedAccountParams
16
17
  ): UseSeamQueryResult<'connectedAccount', UseConnectedAccountData> {
17
18
  const normalizedParams =
18
19
  typeof params === 'string' ? { connected_account_id: params } : params
@@ -1,17 +1,25 @@
1
+ import classNames from 'classnames'
1
2
  import type { PropsWithChildren } from 'react'
2
3
 
3
4
  interface DetailRowProps {
4
5
  label: string
5
6
  sublabel?: string
7
+ onClick?: () => void
6
8
  }
7
9
 
8
10
  export function DetailRow({
9
11
  label,
10
12
  sublabel,
13
+ onClick,
11
14
  children,
12
15
  }: PropsWithChildren<DetailRowProps>): JSX.Element {
13
16
  return (
14
- <div className='seam-detail-row'>
17
+ <div
18
+ className={classNames('seam-detail-row', {
19
+ 'seam-detail-row-clickable': onClick != null,
20
+ })}
21
+ onClick={onClick}
22
+ >
15
23
  <div className='seam-detail-row-label-wrap'>
16
24
  <p className='seam-row-label'>{label}</p>
17
25
  {sublabel != null && <p className='seam-row-sublabel'>{sublabel}</p>}
@@ -1,3 +1,3 @@
1
- const seamapiReactVersion = '1.50.0'
1
+ const seamapiReactVersion = '1.51.0'
2
2
 
3
3
  export default seamapiReactVersion
@@ -151,5 +151,9 @@
151
151
  justify-content: center;
152
152
  }
153
153
  }
154
+
155
+ .seam-thermostat-device-details {
156
+ margin-top: 8px;
157
+ }
154
158
  }
155
159
  }
@@ -76,6 +76,15 @@
76
76
  &:not(:last-of-type) {
77
77
  border-bottom: 1px solid colors.$divider-stroke-light;
78
78
  }
79
+
80
+ &.seam-detail-row-clickable {
81
+ cursor: pointer;
82
+ transition: 0.2s ease;
83
+
84
+ &:hover {
85
+ background-color: colors.$bg-a;
86
+ }
87
+ }
79
88
  }
80
89
 
81
90
  .seam-detail-row,
@@ -108,6 +117,18 @@
108
117
  font-weight: 400;
109
118
  line-height: 118%;
110
119
  }
120
+
121
+ .seam-detail-row-hstack {
122
+ display: flex;
123
+ justify-content: flex-start;
124
+ align-items: center;
125
+ flex-direction: row;
126
+ gap: 8px;
127
+ }
128
+
129
+ .seam-detail-row-rotated-icon {
130
+ transform: rotate(-90deg);
131
+ }
111
132
  }
112
133
 
113
134
  @mixin detail-row {