@seamapi/react 1.48.0 → 1.49.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.
- package/README.md +1 -1
- package/dist/elements.js +4653 -4626
- package/dist/elements.js.map +1 -1
- package/dist/index.css +587 -2
- package/dist/index.css.map +1 -1
- package/dist/index.min.css +1 -1
- package/dist/index.min.css.map +1 -1
- package/lib/dates.d.ts +9 -0
- package/lib/dates.js +15 -0
- package/lib/dates.js.map +1 -1
- package/lib/icons/ArrowRight.d.ts +2 -0
- package/lib/icons/ArrowRight.js +7 -0
- package/lib/icons/ArrowRight.js.map +1 -0
- package/lib/icons/ChevronWide.d.ts +2 -0
- package/lib/icons/ChevronWide.js +5 -0
- package/lib/icons/ChevronWide.js.map +1 -0
- package/lib/icons/Copy.js +2 -4
- package/lib/icons/Copy.js.map +1 -1
- package/lib/icons/TemperatureAdd.d.ts +2 -0
- package/lib/icons/TemperatureAdd.js +7 -0
- package/lib/icons/TemperatureAdd.js.map +1 -0
- package/lib/icons/TemperatureSubtract.d.ts +2 -0
- package/lib/icons/TemperatureSubtract.js +7 -0
- package/lib/icons/TemperatureSubtract.js.map +1 -0
- package/lib/seam/SeamProvider.d.ts +2 -2
- package/lib/seam/SeamProvider.js.map +1 -1
- package/lib/seam/access-codes/use-generate-access-code-code.d.ts +6 -0
- package/lib/seam/access-codes/use-generate-access-code-code.js +13 -0
- package/lib/seam/access-codes/use-generate-access-code-code.js.map +1 -0
- package/lib/seam/components/AccessCodeDetails/AccessCodeDetails.js +9 -2
- package/lib/seam/components/AccessCodeDetails/AccessCodeDetails.js.map +1 -1
- package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleCard.d.ts +6 -0
- package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleCard.js +41 -0
- package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleCard.js.map +1 -0
- package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.d.ts +7 -0
- package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.js +32 -0
- package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.js.map +1 -0
- package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDeviceBar.d.ts +4 -0
- package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDeviceBar.js +29 -0
- package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDeviceBar.js.map +1 -0
- package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleRow.js +2 -2
- package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleRow.js.map +1 -1
- package/lib/seam/components/ClimateSettingScheduleTable/{ClimateSettingScheduleDetails.d.ts → ClimateSettingScheduleRowDetails.d.ts} +1 -1
- package/lib/seam/components/ClimateSettingScheduleTable/{ClimateSettingScheduleDetails.js → ClimateSettingScheduleRowDetails.js} +2 -2
- package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleRowDetails.js.map +1 -0
- package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.d.ts +3 -1
- package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.js +20 -3
- package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.js.map +1 -1
- package/lib/seam/use-seam-client.js +2 -2
- package/lib/seam/use-seam-client.js.map +1 -1
- package/lib/ui/AccessCodeForm/AccessCodeFormDatePicker.js +1 -1
- package/lib/ui/AccessCodeForm/AccessCodeFormDatePicker.js.map +1 -1
- package/lib/ui/Menu/Menu.js +5 -5
- package/lib/ui/Menu/Menu.js.map +1 -1
- package/lib/ui/Switch/Switch.d.ts +8 -0
- package/lib/ui/Switch/Switch.js +15 -0
- package/lib/ui/Switch/Switch.js.map +1 -0
- package/lib/ui/TextField/TextField.js +1 -3
- package/lib/ui/TextField/TextField.js.map +1 -1
- package/lib/ui/clipboard.js +1 -1
- package/lib/ui/clipboard.js.map +1 -1
- package/lib/ui/layout/AccordionRow.d.ts +7 -0
- package/lib/ui/layout/AccordionRow.js +8 -0
- package/lib/ui/layout/AccordionRow.js.map +1 -0
- package/lib/ui/layout/DetailRow.d.ts +6 -0
- package/lib/ui/layout/DetailRow.js +5 -0
- package/lib/ui/layout/DetailRow.js.map +1 -0
- package/lib/ui/layout/DetailSection.d.ts +7 -0
- package/lib/ui/layout/DetailSection.js +6 -0
- package/lib/ui/layout/DetailSection.js.map +1 -0
- package/lib/ui/layout/DetailSectionGroup.d.ts +2 -0
- package/lib/ui/layout/DetailSectionGroup.js +5 -0
- package/lib/ui/layout/DetailSectionGroup.js.map +1 -0
- package/lib/ui/thermostat/TemperatureControl.d.ts +11 -0
- package/lib/ui/thermostat/TemperatureControl.js +42 -0
- package/lib/ui/thermostat/TemperatureControl.js.map +1 -0
- package/lib/ui/use-current-time.d.ts +2 -0
- package/lib/ui/use-current-time.js +12 -0
- package/lib/ui/use-current-time.js.map +1 -0
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +7 -7
- package/src/lib/dates.ts +17 -0
- package/src/lib/element.tsx +6 -4
- package/src/lib/icons/ArrowRight.tsx +36 -0
- package/src/lib/icons/ChevronWide.tsx +21 -0
- package/src/lib/icons/Copy.tsx +6 -21
- package/src/lib/icons/TemperatureAdd.tsx +38 -0
- package/src/lib/icons/TemperatureSubtract.tsx +35 -0
- package/src/lib/seam/SeamProvider.tsx +2 -3
- package/src/lib/seam/access-codes/use-generate-access-code-code.ts +38 -0
- package/src/lib/seam/components/AccessCodeDetails/AccessCodeDetails.tsx +23 -2
- package/src/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleCard.tsx +101 -0
- package/src/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.element.ts +13 -0
- package/src/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.tsx +103 -0
- package/src/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDeviceBar.tsx +60 -0
- package/src/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleRow.tsx +2 -2
- package/src/lib/seam/components/ClimateSettingScheduleTable/{ClimateSettingScheduleDetails.tsx → ClimateSettingScheduleRowDetails.tsx} +1 -1
- package/src/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.element.ts +2 -0
- package/src/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.tsx +37 -2
- package/src/lib/seam/use-seam-client.ts +2 -2
- package/src/lib/ui/AccessCodeForm/AccessCodeFormDatePicker.tsx +2 -2
- package/src/lib/ui/Menu/Menu.tsx +5 -6
- package/src/lib/ui/Switch/Switch.tsx +38 -0
- package/src/lib/ui/TextField/TextField.tsx +1 -3
- package/src/lib/ui/clipboard.ts +1 -1
- package/src/lib/ui/layout/AccordionRow.tsx +36 -0
- package/src/lib/ui/layout/DetailRow.tsx +17 -0
- package/src/lib/ui/layout/DetailSection.tsx +25 -0
- package/src/lib/ui/layout/DetailSectionGroup.tsx +7 -0
- package/src/lib/ui/thermostat/TemperatureControl.tsx +121 -0
- package/src/lib/ui/use-current-time.ts +16 -0
- package/src/lib/version.ts +1 -1
- package/src/styles/_access-code-details.scss +42 -1
- package/src/styles/_climate-setting-schedule-details.scss +44 -0
- package/src/styles/_colors.scss +4 -0
- package/src/styles/_layout.scss +146 -0
- package/src/styles/_main.scss +4 -0
- package/src/styles/_seam-table.scss +8 -0
- package/src/styles/_switch.scss +53 -0
- package/src/styles/_thermostat.scss +387 -2
- package/src/styles/_tooltip.scss +3 -0
- package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleDetails.js.map +0 -1
package/lib/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seamapi/react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.49.0",
|
|
4
4
|
"description": "Seam Components.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
"@tanstack/react-query": "^4.28.0",
|
|
123
123
|
"classnames": "^2.3.2",
|
|
124
124
|
"luxon": "^3.3.0",
|
|
125
|
-
"seamapi": "^8.
|
|
125
|
+
"seamapi": "^8.9.0",
|
|
126
126
|
"uuid": "^9.0.0"
|
|
127
127
|
},
|
|
128
128
|
"devDependencies": {
|
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
"@mui/icons-material": "^5.11.16",
|
|
134
134
|
"@mui/material": "^5.12.2",
|
|
135
135
|
"@rxfork/r2wc-react-to-web-component": "^2.3.0",
|
|
136
|
-
"@seamapi/fake-seam-connect": "^1.
|
|
136
|
+
"@seamapi/fake-seam-connect": "^1.9.0",
|
|
137
137
|
"@storybook/addon-designs": "^7.0.1",
|
|
138
138
|
"@storybook/addon-essentials": "^7.0.2",
|
|
139
139
|
"@storybook/addon-links": "^7.0.2",
|
|
@@ -159,11 +159,11 @@
|
|
|
159
159
|
"eslint-config-standard": "^17.1.0",
|
|
160
160
|
"eslint-config-standard-jsx": "^11.0.0",
|
|
161
161
|
"eslint-config-standard-react": "^13.0.0",
|
|
162
|
-
"eslint-config-standard-with-typescript": "^
|
|
162
|
+
"eslint-config-standard-with-typescript": "^39.0.0",
|
|
163
163
|
"eslint-plugin-simple-import-sort": "^10.0.0",
|
|
164
164
|
"eslint-plugin-storybook": "^0.6.11",
|
|
165
|
-
"eslint-plugin-unused-imports": "^
|
|
166
|
-
"execa": "^
|
|
165
|
+
"eslint-plugin-unused-imports": "^3.0.0",
|
|
166
|
+
"execa": "^8.0.1",
|
|
167
167
|
"fast-glob": "^3.2.12",
|
|
168
168
|
"http-proxy-middleware": "^2.0.6",
|
|
169
169
|
"isomorphic-fetch": "^3.0.0",
|
|
@@ -182,7 +182,7 @@
|
|
|
182
182
|
"tsc-alias": "^1.8.5",
|
|
183
183
|
"tsconfig-paths-webpack-plugin": "^4.0.1",
|
|
184
184
|
"tsx": "^3.12.7",
|
|
185
|
-
"typescript": "
|
|
185
|
+
"typescript": "~5.1.0",
|
|
186
186
|
"vite": "^4.2.1",
|
|
187
187
|
"vite-tsconfig-paths": "^4.0.8",
|
|
188
188
|
"zustand-hoist": "^1.0.0"
|
package/src/lib/dates.ts
CHANGED
|
@@ -138,3 +138,20 @@ export const createIsoDate = (date: string, timezone: string): string => {
|
|
|
138
138
|
*/
|
|
139
139
|
export const getTimezoneFromIsoDate = (date: string): string | null =>
|
|
140
140
|
DateTime.fromISO(date).zoneName
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Takes an ISO datetime string (2023-07-20T00:00:00.000-07:00) and returns a string like
|
|
144
|
+
* (Jul 20, 12:00 AM PDT).
|
|
145
|
+
*
|
|
146
|
+
* @param date
|
|
147
|
+
* @returns string
|
|
148
|
+
*
|
|
149
|
+
*/
|
|
150
|
+
export const formatDateAndTime = (date: string): string =>
|
|
151
|
+
DateTime.fromISO(date).toLocaleString({
|
|
152
|
+
month: 'short',
|
|
153
|
+
day: 'numeric',
|
|
154
|
+
hour: 'numeric',
|
|
155
|
+
minute: '2-digit',
|
|
156
|
+
timeZoneName: 'short',
|
|
157
|
+
})
|
package/src/lib/element.tsx
CHANGED
|
@@ -28,8 +28,10 @@ export type ElementProps<T> = Record<
|
|
|
28
28
|
'string' | 'number' | 'boolean' | 'array' | 'function' | 'json' | 'object'
|
|
29
29
|
>
|
|
30
30
|
|
|
31
|
-
type ProviderProps =
|
|
32
|
-
SeamProviderPropsWithClientSessionToken
|
|
31
|
+
type ProviderProps = Omit<
|
|
32
|
+
SeamProviderPropsWithPublishableKey & SeamProviderPropsWithClientSessionToken,
|
|
33
|
+
'children'
|
|
34
|
+
>
|
|
33
35
|
|
|
34
36
|
const providerProps: ElementProps<ProviderProps> = {
|
|
35
37
|
publishableKey: 'string',
|
|
@@ -53,7 +55,7 @@ export const defineCustomElement = ({
|
|
|
53
55
|
...providerProps,
|
|
54
56
|
},
|
|
55
57
|
})
|
|
56
|
-
globalThis
|
|
58
|
+
globalThis.customElements?.define(name, element)
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
function withProvider<P extends JSX.IntrinsicAttributes>(
|
|
@@ -82,7 +84,7 @@ function withProvider<P extends JSX.IntrinsicAttributes>(
|
|
|
82
84
|
disableFontInjection={
|
|
83
85
|
disableFontInjection ?? globalThis.disableSeamFontInjection
|
|
84
86
|
}
|
|
85
|
-
unminifiyCss={unminifiyCss ?? globalThis
|
|
87
|
+
unminifiyCss={unminifiyCss ?? globalThis.unminifiySeamCss}
|
|
86
88
|
>
|
|
87
89
|
<Component {...(props as P)} />
|
|
88
90
|
</SeamProvider>
|
|
@@ -0,0 +1,36 @@
|
|
|
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 ArrowRightIcon(props: SVGProps<SVGSVGElement>): JSX.Element {
|
|
7
|
+
return (
|
|
8
|
+
<svg
|
|
9
|
+
xmlns='http://www.w3.org/2000/svg'
|
|
10
|
+
width={18}
|
|
11
|
+
height={19}
|
|
12
|
+
fill='none'
|
|
13
|
+
{...props}
|
|
14
|
+
>
|
|
15
|
+
<mask
|
|
16
|
+
id='arrow-right_svg__a'
|
|
17
|
+
width={18}
|
|
18
|
+
height={19}
|
|
19
|
+
x={0}
|
|
20
|
+
y={0}
|
|
21
|
+
maskUnits='userSpaceOnUse'
|
|
22
|
+
style={{
|
|
23
|
+
maskType: 'alpha',
|
|
24
|
+
}}
|
|
25
|
+
>
|
|
26
|
+
<path fill='#D9D9D9' d='M0 .5h18v18H0z' />
|
|
27
|
+
</mask>
|
|
28
|
+
<g mask='url(#arrow-right_svg__a)'>
|
|
29
|
+
<path
|
|
30
|
+
fill='#B9BEC5'
|
|
31
|
+
d='m10.5 14-1.05-1.088 2.663-2.662H3v-1.5h9.113L9.45 6.088 10.5 5 15 9.5 10.5 14Z'
|
|
32
|
+
/>
|
|
33
|
+
</g>
|
|
34
|
+
</svg>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
@@ -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 ChevronWideIcon(props: SVGProps<SVGSVGElement>): JSX.Element {
|
|
7
|
+
return (
|
|
8
|
+
<svg
|
|
9
|
+
xmlns='http://www.w3.org/2000/svg'
|
|
10
|
+
width={25}
|
|
11
|
+
height={24}
|
|
12
|
+
fill='none'
|
|
13
|
+
{...props}
|
|
14
|
+
>
|
|
15
|
+
<path
|
|
16
|
+
fill='#D5D8DC'
|
|
17
|
+
d='m22.123 8-10 10-10-10 1.775-1.775 8.225 8.225 8.225-8.225L22.123 8Z'
|
|
18
|
+
/>
|
|
19
|
+
</svg>
|
|
20
|
+
)
|
|
21
|
+
}
|
package/src/lib/icons/Copy.tsx
CHANGED
|
@@ -7,30 +7,15 @@ export function CopyIcon(props: SVGProps<SVGSVGElement>): JSX.Element {
|
|
|
7
7
|
return (
|
|
8
8
|
<svg
|
|
9
9
|
xmlns='http://www.w3.org/2000/svg'
|
|
10
|
-
width={
|
|
11
|
-
height={
|
|
10
|
+
width={25}
|
|
11
|
+
height={25}
|
|
12
12
|
fill='none'
|
|
13
13
|
{...props}
|
|
14
14
|
>
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
x={0}
|
|
20
|
-
y={0}
|
|
21
|
-
maskUnits='userSpaceOnUse'
|
|
22
|
-
style={{
|
|
23
|
-
maskType: 'alpha',
|
|
24
|
-
}}
|
|
25
|
-
>
|
|
26
|
-
<path fill='#D9D9D9' d='M0 0h18v18H0z' />
|
|
27
|
-
</mask>
|
|
28
|
-
<g mask='url(#copy_svg__a)'>
|
|
29
|
-
<path
|
|
30
|
-
fill='#007AFC'
|
|
31
|
-
d='M3.75 16.5c-.413 0-.766-.147-1.06-.44A1.446 1.446 0 0 1 2.25 15V4.5h1.5V15H12v1.5H3.75Zm3-3c-.412 0-.766-.147-1.059-.44A1.445 1.445 0 0 1 5.25 12V3c0-.413.147-.766.441-1.06.293-.293.647-.44 1.059-.44h6.75c.412 0 .766.147 1.06.44.293.294.44.647.44 1.06v9c0 .412-.147.766-.44 1.06-.294.293-.648.44-1.06.44H6.75Zm0-1.5h6.75V3H6.75v9Z'
|
|
32
|
-
/>
|
|
33
|
-
</g>
|
|
15
|
+
<path
|
|
16
|
+
fill='#232B3A'
|
|
17
|
+
d='M5.84 22.988c-.55 0-1.02-.195-1.412-.587a1.928 1.928 0 0 1-.587-1.413v-14h2v14h11v2h-11Zm4-4c-.55 0-1.02-.195-1.411-.587a1.927 1.927 0 0 1-.588-1.413v-12c0-.55.196-1.02.588-1.413a1.925 1.925 0 0 1 1.412-.587h9c.55 0 1.02.196 1.413.587.391.392.587.863.587 1.413v12c0 .55-.196 1.021-.587 1.413a1.928 1.928 0 0 1-1.413.587h-9Zm0-2h9v-12h-9v12Z'
|
|
18
|
+
/>
|
|
34
19
|
</svg>
|
|
35
20
|
)
|
|
36
21
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
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 TemperatureAddIcon(
|
|
7
|
+
props: SVGProps<SVGSVGElement>
|
|
8
|
+
): JSX.Element {
|
|
9
|
+
return (
|
|
10
|
+
<svg
|
|
11
|
+
xmlns='http://www.w3.org/2000/svg'
|
|
12
|
+
width={18}
|
|
13
|
+
height={18}
|
|
14
|
+
fill='none'
|
|
15
|
+
{...props}
|
|
16
|
+
>
|
|
17
|
+
<mask
|
|
18
|
+
id='temperature-add_svg__a'
|
|
19
|
+
width={18}
|
|
20
|
+
height={18}
|
|
21
|
+
x={0}
|
|
22
|
+
y={0}
|
|
23
|
+
maskUnits='userSpaceOnUse'
|
|
24
|
+
style={{
|
|
25
|
+
maskType: 'alpha',
|
|
26
|
+
}}
|
|
27
|
+
>
|
|
28
|
+
<path fill='#2196F3' d='M0 0h18v18H0z' />
|
|
29
|
+
</mask>
|
|
30
|
+
<g mask='url(#temperature-add_svg__a)'>
|
|
31
|
+
<path
|
|
32
|
+
fill='#9DA1A9'
|
|
33
|
+
d='M8.25 14.25v-4.5h-4.5v-1.5h4.5v-4.5h1.5v4.5h4.5v1.5h-4.5v4.5h-1.5Z'
|
|
34
|
+
/>
|
|
35
|
+
</g>
|
|
36
|
+
</svg>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
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 TemperatureSubtractIcon(
|
|
7
|
+
props: SVGProps<SVGSVGElement>
|
|
8
|
+
): JSX.Element {
|
|
9
|
+
return (
|
|
10
|
+
<svg
|
|
11
|
+
xmlns='http://www.w3.org/2000/svg'
|
|
12
|
+
width={18}
|
|
13
|
+
height={18}
|
|
14
|
+
fill='none'
|
|
15
|
+
{...props}
|
|
16
|
+
>
|
|
17
|
+
<mask
|
|
18
|
+
id='temperature-subtract_svg__a'
|
|
19
|
+
width={18}
|
|
20
|
+
height={18}
|
|
21
|
+
x={0}
|
|
22
|
+
y={0}
|
|
23
|
+
maskUnits='userSpaceOnUse'
|
|
24
|
+
style={{
|
|
25
|
+
maskType: 'alpha',
|
|
26
|
+
}}
|
|
27
|
+
>
|
|
28
|
+
<path fill='#2196F3' d='M0 0h18v18H0z' />
|
|
29
|
+
</mask>
|
|
30
|
+
<g mask='url(#temperature-subtract_svg__a)'>
|
|
31
|
+
<path fill='#9DA1A9' d='M3.75 9.75v-1.5h10.5v1.5H3.75Z' />
|
|
32
|
+
</g>
|
|
33
|
+
</svg>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
@@ -25,11 +25,10 @@ export interface SeamContext {
|
|
|
25
25
|
clientSessionToken?: string | undefined
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export type SeamProviderProps =
|
|
28
|
+
export type SeamProviderProps =
|
|
29
29
|
| SeamProviderPropsWithClient
|
|
30
30
|
| SeamProviderPropsWithPublishableKey
|
|
31
31
|
| SeamProviderPropsWithClientSessionToken
|
|
32
|
-
>
|
|
33
32
|
|
|
34
33
|
export interface SeamProviderPropsWithClient extends SeamProviderBaseProps {
|
|
35
34
|
client: Seam
|
|
@@ -48,7 +47,7 @@ export interface SeamProviderPropsWithClientSessionToken
|
|
|
48
47
|
clientSessionToken: string
|
|
49
48
|
}
|
|
50
49
|
|
|
51
|
-
interface SeamProviderBaseProps {
|
|
50
|
+
interface SeamProviderBaseProps extends PropsWithChildren {
|
|
52
51
|
disableCssInjection?: boolean | undefined
|
|
53
52
|
disableFontInjection?: boolean | undefined
|
|
54
53
|
unminifiyCss?: boolean | undefined
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useMutation, type UseMutationResult } from '@tanstack/react-query'
|
|
2
|
+
import type {
|
|
3
|
+
AccessCode,
|
|
4
|
+
AccessCodeGenerateCodeRequest,
|
|
5
|
+
AccessCodeGenerateCodeResponse,
|
|
6
|
+
SeamError,
|
|
7
|
+
} from 'seamapi'
|
|
8
|
+
|
|
9
|
+
import { NullSeamClientError, useSeamClient } from 'lib/seam/use-seam-client.js'
|
|
10
|
+
|
|
11
|
+
export type UseGenerateAccessCodeCodeParams = never
|
|
12
|
+
export type UseGenerateAccessCodeCodeData = Pick<
|
|
13
|
+
AccessCode,
|
|
14
|
+
'code' | 'device_id'
|
|
15
|
+
>
|
|
16
|
+
export type UseGenerateAccessCodeCodeMutationParams =
|
|
17
|
+
AccessCodeGenerateCodeRequest
|
|
18
|
+
|
|
19
|
+
export function useGenerateAccessCodeCode(): UseMutationResult<
|
|
20
|
+
UseGenerateAccessCodeCodeData,
|
|
21
|
+
SeamError,
|
|
22
|
+
UseGenerateAccessCodeCodeMutationParams
|
|
23
|
+
> {
|
|
24
|
+
const { client } = useSeamClient()
|
|
25
|
+
|
|
26
|
+
return useMutation<
|
|
27
|
+
AccessCodeGenerateCodeResponse['generated_code'],
|
|
28
|
+
SeamError,
|
|
29
|
+
AccessCodeGenerateCodeRequest
|
|
30
|
+
>({
|
|
31
|
+
mutationFn: async (
|
|
32
|
+
mutationParams: UseGenerateAccessCodeCodeMutationParams
|
|
33
|
+
) => {
|
|
34
|
+
if (client === null) throw new NullSeamClientError()
|
|
35
|
+
return await client.accessCodes.generateCode(mutationParams)
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
}
|
|
@@ -8,12 +8,15 @@ import type {
|
|
|
8
8
|
DeviceError,
|
|
9
9
|
} from 'seamapi'
|
|
10
10
|
|
|
11
|
+
import { CopyIcon } from 'lib/icons/Copy.js'
|
|
11
12
|
import { useAccessCode } from 'lib/seam/access-codes/use-access-code.js'
|
|
12
13
|
import { useDeleteAccessCode } from 'lib/seam/access-codes/use-delete-access-code.js'
|
|
13
14
|
import { AccessCodeDevice } from 'lib/seam/components/AccessCodeDetails/AccessCodeDevice.js'
|
|
14
15
|
import { DeviceDetails } from 'lib/seam/components/DeviceDetails/DeviceDetails.js'
|
|
15
16
|
import { Alerts } from 'lib/ui/Alert/Alerts.js'
|
|
16
17
|
import { Button } from 'lib/ui/Button.js'
|
|
18
|
+
import { copyToClipboard } from 'lib/ui/clipboard.js'
|
|
19
|
+
import { IconButton } from 'lib/ui/IconButton.js'
|
|
17
20
|
import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
|
|
18
21
|
import { useIsDateInPast } from 'lib/ui/use-is-date-in-past.js'
|
|
19
22
|
|
|
@@ -82,7 +85,16 @@ export function AccessCodeDetails({
|
|
|
82
85
|
>
|
|
83
86
|
<span className='seam-label'>{t.accessCode}</span>
|
|
84
87
|
<h5 className='seam-access-code-name'>{name}</h5>
|
|
85
|
-
<div className='seam-code'>
|
|
88
|
+
<div className='seam-code'>
|
|
89
|
+
<span>{accessCode.code}</span>
|
|
90
|
+
<IconButton
|
|
91
|
+
onClick={() => {
|
|
92
|
+
void copyToClipboard(accessCode.code ?? '')
|
|
93
|
+
}}
|
|
94
|
+
>
|
|
95
|
+
<CopyIcon />
|
|
96
|
+
</IconButton>
|
|
97
|
+
</div>
|
|
86
98
|
<div className='seam-duration'>
|
|
87
99
|
<Duration accessCode={accessCode} />
|
|
88
100
|
</div>
|
|
@@ -117,7 +129,16 @@ export function AccessCodeDetails({
|
|
|
117
129
|
<div className='seam-details'>
|
|
118
130
|
<div className='seam-row'>
|
|
119
131
|
<div className='seam-heading'>{t.id}:</div>
|
|
120
|
-
<div className='seam-content'>
|
|
132
|
+
<div className='seam-content seam-code-id'>
|
|
133
|
+
<span>{accessCode.access_code_id}</span>
|
|
134
|
+
<IconButton
|
|
135
|
+
onClick={() => {
|
|
136
|
+
void copyToClipboard(accessCode.access_code_id)
|
|
137
|
+
}}
|
|
138
|
+
>
|
|
139
|
+
<CopyIcon />
|
|
140
|
+
</IconButton>
|
|
141
|
+
</div>
|
|
121
142
|
</div>
|
|
122
143
|
<div className='seam-row'>
|
|
123
144
|
<div className='seam-heading'>{t.created}:</div>
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { DateTime } from 'luxon'
|
|
2
|
+
import type { ClimateSettingSchedule } from 'seamapi'
|
|
3
|
+
|
|
4
|
+
import { formatDateAndTime } from 'lib/dates.js'
|
|
5
|
+
import { ClimateSettingScheduleIcon } from 'lib/icons/ClimateSettingSchedule.js'
|
|
6
|
+
import { useClimateSettingSchedule } from 'lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedule.js'
|
|
7
|
+
import { DotDivider } from 'lib/ui/layout/DotDivider.js'
|
|
8
|
+
import { ClimateSettingStatus } from 'lib/ui/thermostat/ClimateSettingStatus.js'
|
|
9
|
+
import { useCurrentTime } from 'lib/ui/use-current-time.js'
|
|
10
|
+
|
|
11
|
+
import { ClimateSettingScheduleDeviceBar } from './ClimateSettingScheduleDeviceBar.js'
|
|
12
|
+
|
|
13
|
+
interface ClimateSettingScheduleCardProps {
|
|
14
|
+
climateSettingScheduleId: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function ClimateSettingScheduleCard({
|
|
18
|
+
climateSettingScheduleId,
|
|
19
|
+
}: ClimateSettingScheduleCardProps): JSX.Element {
|
|
20
|
+
return (
|
|
21
|
+
<div className='seam-climate-setting-schedule-card'>
|
|
22
|
+
<Content climateSettingScheduleId={climateSettingScheduleId} />
|
|
23
|
+
</div>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function Content(props: {
|
|
28
|
+
climateSettingScheduleId: string
|
|
29
|
+
}): JSX.Element | null {
|
|
30
|
+
const { climateSettingScheduleId } = props
|
|
31
|
+
|
|
32
|
+
const { climateSettingSchedule } = useClimateSettingSchedule(
|
|
33
|
+
climateSettingScheduleId
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
if (climateSettingSchedule == null) {
|
|
37
|
+
return null
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const name = climateSettingSchedule.name ?? t.fallbackName
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<div className='seam-climate-setting-schedule-content'>
|
|
44
|
+
<div className='seam-climate-setting-schedule-summary-container'>
|
|
45
|
+
<div className='seam-climate-setting-schedule-icon-block'>
|
|
46
|
+
<ClimateSettingScheduleIcon />
|
|
47
|
+
</div>
|
|
48
|
+
<div className='seam-climate-setting-schedule-summary'>
|
|
49
|
+
<h5 className='seam-climate-setting-schedule-heading'>{name}</h5>
|
|
50
|
+
<div className='seam-climate-setting-schedule-subheading'>
|
|
51
|
+
<ClimateSettingStatus climateSetting={climateSettingSchedule} />
|
|
52
|
+
<DotDivider />
|
|
53
|
+
<ClimateSettingScheduleTiming
|
|
54
|
+
climateSettingSchedule={climateSettingSchedule}
|
|
55
|
+
/>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
<ClimateSettingScheduleDeviceBar
|
|
60
|
+
deviceId={climateSettingSchedule.device_id}
|
|
61
|
+
/>
|
|
62
|
+
</div>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function ClimateSettingScheduleTiming(props: {
|
|
67
|
+
climateSettingSchedule: ClimateSettingSchedule
|
|
68
|
+
}): JSX.Element | null {
|
|
69
|
+
const { climateSettingSchedule } = props
|
|
70
|
+
|
|
71
|
+
const currentTime = useCurrentTime()
|
|
72
|
+
|
|
73
|
+
if (currentTime === null) return null
|
|
74
|
+
|
|
75
|
+
const startTime = DateTime.fromISO(climateSettingSchedule.schedule_starts_at)
|
|
76
|
+
const endTime = DateTime.fromISO(climateSettingSchedule.schedule_ends_at)
|
|
77
|
+
|
|
78
|
+
if (currentTime < startTime)
|
|
79
|
+
return (
|
|
80
|
+
<span>
|
|
81
|
+
{t.starts}{' '}
|
|
82
|
+
{formatDateAndTime(climateSettingSchedule.schedule_starts_at)}
|
|
83
|
+
</span>
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
if (startTime <= currentTime && currentTime <= endTime)
|
|
87
|
+
return (
|
|
88
|
+
<span>
|
|
89
|
+
{t.ends} {formatDateAndTime(climateSettingSchedule.schedule_starts_at)}
|
|
90
|
+
</span>
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
return <span>{t.expired}</span>
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const t = {
|
|
97
|
+
starts: 'Starts',
|
|
98
|
+
ends: 'Ends',
|
|
99
|
+
expired: 'Expired',
|
|
100
|
+
fallbackName: 'Climate Setting Schedule',
|
|
101
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ElementProps } from 'lib/element.js'
|
|
2
|
+
|
|
3
|
+
import type { ClimateSettingScheduleDetailsProps } from './ClimateSettingScheduleDetails.js'
|
|
4
|
+
|
|
5
|
+
export const name = 'seam-climate-setting-schedule-details'
|
|
6
|
+
|
|
7
|
+
export const props: ElementProps<ClimateSettingScheduleDetailsProps> = {
|
|
8
|
+
climateSettingScheduleId: 'string',
|
|
9
|
+
onBack: 'object',
|
|
10
|
+
className: 'string',
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { ClimateSettingScheduleDetails as Component } from './ClimateSettingScheduleDetails.js'
|
package/src/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.tsx
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import classNames from 'classnames'
|
|
2
|
+
|
|
3
|
+
import { formatDateAndTime } from 'lib/dates.js'
|
|
4
|
+
import { ArrowRightIcon } from 'lib/icons/ArrowRight.js'
|
|
5
|
+
import { useClimateSettingSchedule } from 'lib/seam/thermostats/climate-setting-schedules/use-climate-setting-schedule.js'
|
|
6
|
+
import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
|
|
7
|
+
import { DetailRow } from 'lib/ui/layout/DetailRow.js'
|
|
8
|
+
import { DetailSection } from 'lib/ui/layout/DetailSection.js'
|
|
9
|
+
import { DetailSectionGroup } from 'lib/ui/layout/DetailSectionGroup.js'
|
|
10
|
+
import { ClimateSettingStatus } from 'lib/ui/thermostat/ClimateSettingStatus.js'
|
|
11
|
+
|
|
12
|
+
import { ClimateSettingScheduleCard } from './ClimateSettingScheduleCard.js'
|
|
13
|
+
|
|
14
|
+
export interface ClimateSettingScheduleDetailsProps {
|
|
15
|
+
climateSettingScheduleId: string
|
|
16
|
+
onBack?: () => void
|
|
17
|
+
className?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function ClimateSettingScheduleDetails({
|
|
21
|
+
climateSettingScheduleId,
|
|
22
|
+
onBack,
|
|
23
|
+
className,
|
|
24
|
+
}: ClimateSettingScheduleDetailsProps): JSX.Element | null {
|
|
25
|
+
const { climateSettingSchedule } = useClimateSettingSchedule(
|
|
26
|
+
climateSettingScheduleId
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
if (climateSettingSchedule == null) {
|
|
30
|
+
return null
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const isManualOverrideAllowed =
|
|
34
|
+
climateSettingSchedule.manual_override_allowed ?? false
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<div
|
|
38
|
+
className={classNames('seam-climate-setting-schedule-details', className)}
|
|
39
|
+
>
|
|
40
|
+
<ContentHeader title={t.climateSettingSchedule} onBack={onBack} />
|
|
41
|
+
<div className='seam-climate-setting-schedule-details-content'>
|
|
42
|
+
<ClimateSettingScheduleCard
|
|
43
|
+
climateSettingScheduleId={climateSettingScheduleId}
|
|
44
|
+
/>
|
|
45
|
+
<div className='seam-default-setting-message-container'>
|
|
46
|
+
<span className='seam-default-setting-message'>
|
|
47
|
+
{t.defaultSettingMessagePart1}{' '}
|
|
48
|
+
<span className='seam-default-setting-text'>
|
|
49
|
+
{t.defaultSetting}
|
|
50
|
+
</span>{' '}
|
|
51
|
+
{t.defaultSettingMessagePart2}
|
|
52
|
+
</span>
|
|
53
|
+
</div>
|
|
54
|
+
<DetailSectionGroup>
|
|
55
|
+
<DetailSection>
|
|
56
|
+
<DetailRow label={t.startEndTime}>
|
|
57
|
+
<span className='seam-climate-setting-details-value seam-climate-setting-details-schedule-range'>
|
|
58
|
+
{`${formatDateAndTime(
|
|
59
|
+
climateSettingSchedule.schedule_starts_at
|
|
60
|
+
)}`}
|
|
61
|
+
<ArrowRightIcon />
|
|
62
|
+
{`${formatDateAndTime(
|
|
63
|
+
climateSettingSchedule.schedule_ends_at
|
|
64
|
+
)}`}
|
|
65
|
+
</span>
|
|
66
|
+
</DetailRow>
|
|
67
|
+
<DetailRow label={t.climateSetting}>
|
|
68
|
+
<ClimateSettingStatus
|
|
69
|
+
climateSetting={climateSettingSchedule}
|
|
70
|
+
iconPlacement='right'
|
|
71
|
+
/>
|
|
72
|
+
</DetailRow>
|
|
73
|
+
<DetailRow label={t.allowManualOverride}>
|
|
74
|
+
<span className='seam-climate-setting-details-value'>
|
|
75
|
+
{isManualOverrideAllowed ? t.on : t.off}
|
|
76
|
+
</span>
|
|
77
|
+
</DetailRow>
|
|
78
|
+
</DetailSection>
|
|
79
|
+
<DetailSection>
|
|
80
|
+
<DetailRow label={t.creationDate}>
|
|
81
|
+
<div className='seam-creation-date'>
|
|
82
|
+
{formatDateAndTime(climateSettingSchedule.created_at)}
|
|
83
|
+
</div>
|
|
84
|
+
</DetailRow>
|
|
85
|
+
</DetailSection>
|
|
86
|
+
</DetailSectionGroup>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const t = {
|
|
93
|
+
climateSettingSchedule: 'Climate setting schedule',
|
|
94
|
+
startEndTime: 'Start/End Time',
|
|
95
|
+
climateSetting: 'Climate setting',
|
|
96
|
+
allowManualOverride: 'Allow manual override',
|
|
97
|
+
creationDate: 'Creation date',
|
|
98
|
+
defaultSettingMessagePart1: 'Thermostat will return to its',
|
|
99
|
+
defaultSetting: 'default setting',
|
|
100
|
+
defaultSettingMessagePart2: 'at end time.',
|
|
101
|
+
on: 'On',
|
|
102
|
+
off: 'Off',
|
|
103
|
+
}
|
package/src/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDeviceBar.tsx
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { isThermostatDevice, type ThermostatDevice } from 'seamapi'
|
|
2
|
+
|
|
3
|
+
import { ChevronWideIcon } from 'lib/icons/ChevronWide.js'
|
|
4
|
+
import { useDevice } from 'lib/seam/devices/use-device.js'
|
|
5
|
+
import { DeviceImage } from 'lib/ui/device/DeviceImage.js'
|
|
6
|
+
import { ClimateSettingStatus } from 'lib/ui/thermostat/ClimateSettingStatus.js'
|
|
7
|
+
|
|
8
|
+
export function ClimateSettingScheduleDeviceBar({
|
|
9
|
+
deviceId,
|
|
10
|
+
}: {
|
|
11
|
+
deviceId: string
|
|
12
|
+
}): JSX.Element | null {
|
|
13
|
+
const { isLoading, device } = useDevice({
|
|
14
|
+
device_id: deviceId,
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
if (isLoading) {
|
|
18
|
+
return null
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (device == null) {
|
|
22
|
+
return null
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!isThermostatDevice(device)) {
|
|
26
|
+
return null
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return <Content device={device} />
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function Content(props: { device: ThermostatDevice }): JSX.Element {
|
|
33
|
+
const { device } = props
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<div className='seam-climate-setting-schedule-device-bar'>
|
|
37
|
+
<div className='seam-climate-setting-schedule-device-content'>
|
|
38
|
+
<div className='seam-device-image'>
|
|
39
|
+
<DeviceImage device={device} />
|
|
40
|
+
</div>
|
|
41
|
+
<div className='seam-climate-setting-schedule-device-details'>
|
|
42
|
+
<div className='seam-device-name'>{device.properties.name}</div>
|
|
43
|
+
<div className='seam-device-current-climate-setting'>
|
|
44
|
+
{t.currentClimate}:
|
|
45
|
+
<ClimateSettingStatus
|
|
46
|
+
climateSetting={device.properties.current_climate_setting}
|
|
47
|
+
/>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
<div className='seam-climate-setting-schedule-device-chevron'>
|
|
52
|
+
<ChevronWideIcon />
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const t = {
|
|
59
|
+
currentClimate: 'Current climate',
|
|
60
|
+
}
|