@seamapi/react 1.48.1 → 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.
Files changed (56) hide show
  1. package/README.md +1 -1
  2. package/dist/elements.js +3285 -3280
  3. package/dist/elements.js.map +1 -1
  4. package/dist/index.css +188 -2
  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/ChevronWide.d.ts +2 -0
  9. package/lib/icons/ChevronWide.js +5 -0
  10. package/lib/icons/ChevronWide.js.map +1 -0
  11. package/lib/icons/Copy.js +2 -4
  12. package/lib/icons/Copy.js.map +1 -1
  13. package/lib/seam/components/AccessCodeDetails/AccessCodeDetails.js +9 -2
  14. package/lib/seam/components/AccessCodeDetails/AccessCodeDetails.js.map +1 -1
  15. package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.d.ts +7 -0
  16. package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.js +32 -0
  17. package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.js.map +1 -0
  18. package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDeviceBar.js +2 -2
  19. package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDeviceBar.js.map +1 -1
  20. package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.d.ts +3 -1
  21. package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.js +20 -3
  22. package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.js.map +1 -1
  23. package/lib/ui/layout/AccordionRow.d.ts +7 -0
  24. package/lib/ui/layout/AccordionRow.js +8 -0
  25. package/lib/ui/layout/AccordionRow.js.map +1 -0
  26. package/lib/ui/layout/DetailRow.d.ts +6 -0
  27. package/lib/ui/layout/DetailRow.js +5 -0
  28. package/lib/ui/layout/DetailRow.js.map +1 -0
  29. package/lib/ui/layout/DetailSection.d.ts +7 -0
  30. package/lib/ui/layout/DetailSection.js +6 -0
  31. package/lib/ui/layout/DetailSection.js.map +1 -0
  32. package/lib/ui/layout/DetailSectionGroup.d.ts +2 -0
  33. package/lib/ui/layout/DetailSectionGroup.js +5 -0
  34. package/lib/ui/layout/DetailSectionGroup.js.map +1 -0
  35. package/lib/version.d.ts +1 -1
  36. package/lib/version.js +1 -1
  37. package/package.json +1 -1
  38. package/src/lib/icons/ChevronWide.tsx +21 -0
  39. package/src/lib/icons/Copy.tsx +6 -21
  40. package/src/lib/seam/components/AccessCodeDetails/AccessCodeDetails.tsx +23 -2
  41. package/src/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.element.ts +13 -0
  42. package/src/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.tsx +103 -0
  43. package/src/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDeviceBar.tsx +4 -2
  44. package/src/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.element.ts +2 -0
  45. package/src/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.tsx +37 -2
  46. package/src/lib/ui/layout/AccordionRow.tsx +36 -0
  47. package/src/lib/ui/layout/DetailRow.tsx +17 -0
  48. package/src/lib/ui/layout/DetailSection.tsx +25 -0
  49. package/src/lib/ui/layout/DetailSectionGroup.tsx +7 -0
  50. package/src/lib/version.ts +1 -1
  51. package/src/styles/_access-code-details.scss +42 -1
  52. package/src/styles/_climate-setting-schedule-details.scss +44 -0
  53. package/src/styles/_layout.scss +146 -0
  54. package/src/styles/_main.scss +2 -0
  55. package/src/styles/_seam-table.scss +8 -0
  56. package/src/styles/_thermostat.scss +4 -1
@@ -1,8 +1,9 @@
1
1
  import classNames from 'classnames'
2
- import { useMemo, useState } from 'react'
2
+ import { useCallback, useMemo, useState } from 'react'
3
3
  import type { ClimateSettingSchedule } from 'seamapi'
4
4
 
5
5
  import { compareByCreatedAtDesc } from 'lib/dates.js'
6
+ import { ClimateSettingScheduleDetails } from 'lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.js'
6
7
  import {
7
8
  useClimateSettingSchedules,
8
9
  type UseClimateSettingSchedulesData,
@@ -20,6 +21,8 @@ import { ClimateSettingScheduleRow } from './ClimateSettingScheduleRow.js'
20
21
  export interface ClimateSettingScheduleTableProps {
21
22
  deviceId: string
22
23
  disableSearch?: boolean
24
+ onClimateSettingScheduleClick?: (climateSettingScheduleId: string) => void
25
+ preventDefaultOnClimateSettingScheduleClick?: boolean
23
26
  climateSettingScheduleFilter?: (
24
27
  climateSettingSchedule: ClimateSettingSchedule,
25
28
  searchInputValue: string
@@ -46,8 +49,11 @@ const defaultClimateSettingScheduleFilter = (
46
49
  export function ClimateSettingScheduleTable({
47
50
  deviceId,
48
51
  disableSearch = false,
52
+ onClimateSettingScheduleClick = () => {},
53
+ preventDefaultOnClimateSettingScheduleClick = false,
49
54
  climateSettingScheduleFilter = defaultClimateSettingScheduleFilter,
50
55
  climateSettingScheduleComparator = compareByCreatedAtDesc,
56
+
51
57
  onBack,
52
58
  heading = t.climateSettingSchedules,
53
59
  className,
@@ -58,6 +64,10 @@ export function ClimateSettingScheduleTable({
58
64
  })
59
65
 
60
66
  const [searchInputValue, setSearchInputValue] = useState('')
67
+ const [
68
+ selectedViewClimateSettingScheduleId,
69
+ setSelectedViewClimateSettingScheduleId,
70
+ ] = useState<string | null>(null)
61
71
 
62
72
  const filteredClimateSettingSchedules = useMemo(
63
73
  () =>
@@ -74,6 +84,31 @@ export function ClimateSettingScheduleTable({
74
84
  ]
75
85
  )
76
86
 
87
+ const handleClimateSettingScheduleClick = useCallback(
88
+ (climateSettingScheduleId: string): void => {
89
+ onClimateSettingScheduleClick(climateSettingScheduleId)
90
+ if (preventDefaultOnClimateSettingScheduleClick) return
91
+ setSelectedViewClimateSettingScheduleId(climateSettingScheduleId)
92
+ },
93
+ [
94
+ onClimateSettingScheduleClick,
95
+ preventDefaultOnClimateSettingScheduleClick,
96
+ setSelectedViewClimateSettingScheduleId,
97
+ ]
98
+ )
99
+
100
+ if (selectedViewClimateSettingScheduleId != null) {
101
+ return (
102
+ <ClimateSettingScheduleDetails
103
+ className={className}
104
+ climateSettingScheduleId={selectedViewClimateSettingScheduleId}
105
+ onBack={() => {
106
+ setSelectedViewClimateSettingScheduleId(null)
107
+ }}
108
+ />
109
+ )
110
+ }
111
+
77
112
  if (isLoading) {
78
113
  return <p className={className}>...</p>
79
114
  }
@@ -105,7 +140,7 @@ export function ClimateSettingScheduleTable({
105
140
  <TableBody>
106
141
  <Content
107
142
  climateSettingSchedules={filteredClimateSettingSchedules}
108
- onClimateSettingScheduleClick={() => {}}
143
+ onClimateSettingScheduleClick={handleClimateSettingScheduleClick}
109
144
  />
110
145
  </TableBody>
111
146
  </div>
@@ -0,0 +1,36 @@
1
+ import type { PropsWithChildren } from 'react'
2
+
3
+ import { ChevronWideIcon } from 'lib/icons/ChevronWide.js'
4
+ import { useToggle } from 'lib/ui/use-toggle.js'
5
+
6
+ interface AccordionRowProps extends PropsWithChildren {
7
+ label: string
8
+ rightCollapsedContent?: JSX.Element
9
+ }
10
+
11
+ export function AccordionRow({
12
+ label,
13
+ rightCollapsedContent,
14
+ children,
15
+ }: AccordionRowProps): JSX.Element {
16
+ const [isExpanded, toggle] = useToggle()
17
+
18
+ return (
19
+ <div className='seam-accordion-row' aria-expanded={isExpanded}>
20
+ <button className='seam-accordion-row-trigger' onClick={toggle}>
21
+ <p className='seam-row-label'>{label}</p>
22
+ <div className='seam-row-inner-wrap'>
23
+ <div className='seam-row-trigger-right-content'>
24
+ {rightCollapsedContent}
25
+ </div>
26
+ <div className='seam-accordion-icon-wrap'>
27
+ <ChevronWideIcon />
28
+ </div>
29
+ </div>
30
+ </button>
31
+ <div className='seam-accordion-row-content'>
32
+ <div className='seam-accordion-row-inner-content'>{children}</div>
33
+ </div>
34
+ </div>
35
+ )
36
+ }
@@ -0,0 +1,17 @@
1
+ import type { PropsWithChildren } from 'react'
2
+
3
+ interface DetailRowProps {
4
+ label: string
5
+ }
6
+
7
+ export function DetailRow({
8
+ label,
9
+ children,
10
+ }: PropsWithChildren<DetailRowProps>): JSX.Element {
11
+ return (
12
+ <div className='seam-detail-row'>
13
+ <p className='seam-row-label'>{label}</p>
14
+ <div className='seam-detail-row-right-area-content'>{children}</div>
15
+ </div>
16
+ )
17
+ }
@@ -0,0 +1,25 @@
1
+ import type { PropsWithChildren } from 'react'
2
+
3
+ import { Tooltip } from 'lib/ui/Tooltip/Tooltip.js'
4
+
5
+ interface DetailSectionProps {
6
+ label?: string
7
+ tooltipContent?: string
8
+ }
9
+
10
+ export function DetailSection({
11
+ label,
12
+ tooltipContent,
13
+ children,
14
+ }: PropsWithChildren<DetailSectionProps>): JSX.Element {
15
+ return (
16
+ <div className='seam-detail-section'>
17
+ <div className='seam-detail-label-wrap'>
18
+ {label != null && <p className='seam-detail-label'>{label}</p>}
19
+ {tooltipContent != null && <Tooltip>{tooltipContent}</Tooltip>}
20
+ </div>
21
+
22
+ <div className='seam-detail-group'>{children}</div>
23
+ </div>
24
+ )
25
+ }
@@ -0,0 +1,7 @@
1
+ import type { PropsWithChildren } from 'react'
2
+
3
+ export function DetailSectionGroup({
4
+ children,
5
+ }: PropsWithChildren): JSX.Element {
6
+ return <div className='seam-detail-sections'>{children}</div>
7
+ }
@@ -1,3 +1,3 @@
1
- const seamapiReactVersion = '1.48.1'
1
+ const seamapiReactVersion = '1.49.0'
2
2
 
3
3
  export default seamapiReactVersion
@@ -33,11 +33,35 @@
33
33
  background: colors.$white;
34
34
  border: 1px solid colors.$text-gray-2;
35
35
  border-radius: 8px;
36
- padding: 10px 16px;
37
36
  font-weight: 600;
38
37
  font-size: 24px;
39
38
  line-height: 134%;
40
39
  margin-bottom: 8px;
40
+ display: flex;
41
+ justify-content: space-between;
42
+
43
+ > span {
44
+ padding: 10px 16px;
45
+ }
46
+
47
+ > .seam-icon-btn {
48
+ height: auto;
49
+ border: 0;
50
+ overflow: visible;
51
+ padding: 0;
52
+ padding: 16px 10px;
53
+ flex: 0 0 48px;
54
+ border-radius: 0 8px 8px 0;
55
+ border-left: 1px solid colors.$divider-stroke-light;
56
+
57
+ &:hover {
58
+ background: colors.$item-hover-bg;
59
+ }
60
+
61
+ svg {
62
+ scale: 0.8333;
63
+ }
64
+ }
41
65
  }
42
66
 
43
67
  .seam-duration {
@@ -105,6 +129,23 @@
105
129
  display: flex;
106
130
  flex: 1;
107
131
 
132
+ &.seam-code-id {
133
+ display: flex;
134
+ justify-content: space-between;
135
+
136
+ .seam-icon-btn {
137
+ border: 0;
138
+
139
+ &:hover {
140
+ background: transparent;
141
+ }
142
+
143
+ svg {
144
+ scale: 0.8333;
145
+ }
146
+ }
147
+ }
148
+
108
149
  .seam-times {
109
150
  display: flex;
110
151
  flex: 1;
@@ -0,0 +1,44 @@
1
+ @use './colors';
2
+
3
+ @mixin all {
4
+ .seam-climate-setting-schedule-details {
5
+ .seam-climate-setting-schedule-details-content {
6
+ margin: 0 16px;
7
+ }
8
+
9
+ .seam-climate-setting-details-value {
10
+ font-style: normal;
11
+ font-weight: 400;
12
+ line-height: 118%;
13
+ font-size: 14px;
14
+ color: colors.$text-gray-1;
15
+
16
+ &.seam-climate-setting-details-schedule-range {
17
+ display: flex;
18
+ align-items: center;
19
+ }
20
+ }
21
+
22
+ .seam-default-setting-message-container {
23
+ display: flex;
24
+ justify-content: center;
25
+ margin: 16px 0;
26
+
27
+ .seam-default-setting-message {
28
+ font-size: 14px;
29
+ font-style: normal;
30
+ font-weight: 400;
31
+ line-height: 115%;
32
+ color: colors.$text-gray-2;
33
+
34
+ .seam-default-setting-text {
35
+ color: colors.$text-gray-1;
36
+ }
37
+ }
38
+ }
39
+
40
+ .seam-creation-date {
41
+ color: colors.$text-gray-1;
42
+ }
43
+ }
44
+ }
@@ -33,6 +33,152 @@
33
33
  }
34
34
  }
35
35
 
36
+ @mixin detail-section {
37
+ .seam-detail-sections {
38
+ display: flex;
39
+ flex-direction: column;
40
+ gap: 32px;
41
+ }
42
+
43
+ .seam-detail-section {
44
+ width: 100%;
45
+ }
46
+
47
+ .seam-detail-label-wrap {
48
+ width: 100%;
49
+ display: flex;
50
+ justify-content: flex-start;
51
+ align-items: center;
52
+ flex-direction: row;
53
+ gap: 4px;
54
+ margin-bottom: 8px;
55
+ }
56
+
57
+ .seam-detail-label {
58
+ color: colors.$text-gray-1;
59
+ font-size: 16px;
60
+ font-weight: 400;
61
+ line-height: 134%;
62
+ }
63
+
64
+ .seam-detail-group {
65
+ border-radius: 8px;
66
+ border: 1px solid colors.$text-gray-3;
67
+ overflow: hidden;
68
+ }
69
+ }
70
+
71
+ @mixin detail-row-common {
72
+ .seam-detail-row,
73
+ .seam-accordion-row {
74
+ background-color: colors.$white;
75
+
76
+ &:not(:last-of-type) {
77
+ border-bottom: 1px solid colors.$divider-stroke-light;
78
+ }
79
+ }
80
+
81
+ .seam-detail-row,
82
+ .seam-accordion-row-trigger {
83
+ display: flex;
84
+ justify-content: space-between;
85
+ align-items: center;
86
+ flex-direction: row;
87
+ min-height: 64px;
88
+ padding: 8px 16px;
89
+ }
90
+
91
+ .seam-row-label {
92
+ font-size: 16px;
93
+ font-weight: 600;
94
+ line-height: 118%;
95
+ }
96
+ }
97
+
98
+ @mixin detail-row {
99
+ .seam-detail-row-right-area-content {
100
+ display: flex;
101
+ justify-content: center;
102
+ align-items: center;
103
+ flex-direction: row;
104
+ gap: 8px;
105
+ }
106
+ }
107
+
108
+ @mixin accordion-row {
109
+ .seam-accordion-row {
110
+ overflow: hidden;
111
+
112
+ .seam-accordion-row-trigger {
113
+ appearance: none;
114
+ width: 100%;
115
+ background-color: colors.$white;
116
+ font-size: 16px;
117
+ border: none;
118
+ box-shadow: none;
119
+ cursor: pointer;
120
+ font-family: inherit;
121
+ }
122
+
123
+ .seam-accordion-row-content {
124
+ display: flex;
125
+ justify-content: center;
126
+ align-items: flex-start;
127
+ flex-direction: column;
128
+ max-height: 0;
129
+ opacity: 0;
130
+ transition: all 0.3s ease-in-out;
131
+ }
132
+
133
+ &[aria-expanded='true'] {
134
+ .seam-accordion-row-content {
135
+ max-height: 64px;
136
+ opacity: 1;
137
+ }
138
+
139
+ .seam-accordion-icon-wrap {
140
+ transform: rotate(180deg);
141
+ }
142
+
143
+ .seam-row-trigger-right-content {
144
+ transform: scale(0.95);
145
+ opacity: 0;
146
+ }
147
+ }
148
+
149
+ .seam-accordion-row-inner-content {
150
+ height: 64px;
151
+ padding: 0 16px;
152
+ overflow: hidden;
153
+ }
154
+
155
+ .seam-row-inner-wrap {
156
+ display: flex;
157
+ justify-content: center;
158
+ align-items: center;
159
+ flex-direction: row;
160
+ gap: 16px;
161
+ }
162
+
163
+ .seam-row-trigger-right-content {
164
+ transition: 0.2s ease-in-out;
165
+ }
166
+
167
+ .seam-accordion-icon-wrap {
168
+ width: 24px;
169
+ height: 24px;
170
+ display: flex;
171
+ justify-content: center;
172
+ align-items: center;
173
+ transition: transform 0.2s ease-in-out;
174
+ }
175
+ }
176
+ }
177
+
36
178
  @mixin all {
37
179
  @include header;
180
+ @include detail-section;
181
+ @include detail-row-common;
182
+ @include detail-row;
183
+ @include accordion-row;
38
184
  }
@@ -20,6 +20,7 @@
20
20
  @use './thermostat';
21
21
  @use './tooltip';
22
22
  @use './seam-table';
23
+ @use './climate-setting-schedule-details';
23
24
  @use './switch';
24
25
 
25
26
  .seam-components {
@@ -50,4 +51,5 @@
50
51
  @include supported-device-table.all;
51
52
  @include thermostat.all;
52
53
  @include seam-table.all;
54
+ @include climate-setting-schedule-details.all;
53
55
  }
@@ -99,6 +99,14 @@
99
99
  align-items: center;
100
100
  justify-content: space-between;
101
101
  flex: 1;
102
+
103
+ svg {
104
+ scale: 0.75;
105
+
106
+ * {
107
+ fill: colors.$primary;
108
+ }
109
+ }
102
110
  }
103
111
  }
104
112
  }
@@ -304,7 +304,6 @@
304
304
  .seam-climate-setting-schedule-card {
305
305
  background: colors.$bg-a;
306
306
  border-radius: 16px;
307
- margin: 0 24px 16px;
308
307
 
309
308
  .seam-climate-setting-schedule-content {
310
309
  display: flex;
@@ -394,6 +393,10 @@
394
393
  }
395
394
  }
396
395
  }
396
+
397
+ .seam-climate-setting-schedule-device-chevron {
398
+ transform: rotate(270deg);
399
+ }
397
400
  }
398
401
  }
399
402