@seamapi/react 2.14.0 → 2.16.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 (46) hide show
  1. package/README.md +2 -2
  2. package/dist/elements.js +22418 -15795
  3. package/dist/elements.js.map +1 -1
  4. package/dist/index.css +49 -1
  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/dates.d.ts +1 -0
  9. package/lib/dates.js +4 -0
  10. package/lib/dates.js.map +1 -1
  11. package/lib/icons/NoiseLevels.d.ts +2 -0
  12. package/lib/icons/NoiseLevels.js +5 -0
  13. package/lib/icons/NoiseLevels.js.map +1 -0
  14. package/lib/seam/components/DeviceDetails/DeviceDetails.js +5 -1
  15. package/lib/seam/components/DeviceDetails/DeviceDetails.js.map +1 -1
  16. package/lib/seam/components/DeviceDetails/DeviceInfo.js +1 -1
  17. package/lib/seam/components/DeviceDetails/DeviceInfo.js.map +1 -1
  18. package/lib/seam/components/DeviceDetails/NoiseSensorDeviceDetails.d.ts +8 -0
  19. package/lib/seam/components/DeviceDetails/NoiseSensorDeviceDetails.js +15 -0
  20. package/lib/seam/components/DeviceDetails/NoiseSensorDeviceDetails.js.map +1 -0
  21. package/lib/seam/noise-sensors/use-noise-thresholds.d.ts +5 -0
  22. package/lib/seam/noise-sensors/use-noise-thresholds.js +26 -0
  23. package/lib/seam/noise-sensors/use-noise-thresholds.js.map +1 -0
  24. package/lib/ui/layout/DetailRow.d.ts +1 -1
  25. package/lib/ui/layout/DetailSection.d.ts +3 -2
  26. package/lib/ui/layout/DetailSection.js +3 -2
  27. package/lib/ui/layout/DetailSection.js.map +1 -1
  28. package/lib/ui/noise-sensor/NoiseThresholdsList.d.ts +7 -0
  29. package/lib/ui/noise-sensor/NoiseThresholdsList.js +45 -0
  30. package/lib/ui/noise-sensor/NoiseThresholdsList.js.map +1 -0
  31. package/lib/version.d.ts +1 -1
  32. package/lib/version.js +1 -1
  33. package/package.json +3 -2
  34. package/src/lib/dates.ts +5 -0
  35. package/src/lib/icons/NoiseLevels.tsx +31 -0
  36. package/src/lib/seam/components/DeviceDetails/DeviceDetails.tsx +6 -1
  37. package/src/lib/seam/components/DeviceDetails/DeviceInfo.tsx +4 -1
  38. package/src/lib/seam/components/DeviceDetails/NoiseSensorDeviceDetails.tsx +58 -0
  39. package/src/lib/seam/noise-sensors/use-noise-thresholds.ts +46 -0
  40. package/src/lib/ui/layout/DetailRow.tsx +1 -1
  41. package/src/lib/ui/layout/DetailSection.tsx +5 -2
  42. package/src/lib/ui/noise-sensor/NoiseThresholdsList.tsx +141 -0
  43. package/src/lib/version.ts +1 -1
  44. package/src/styles/_device-details.scss +1 -0
  45. package/src/styles/_layout.scss +55 -0
  46. package/src/styles/_thermostat.scss +1 -1
@@ -0,0 +1,141 @@
1
+ import type { NoiseSensorDevice, NoiseThresholds } from 'seamapi'
2
+ import { ZonedTime } from 'zoned-time'
3
+
4
+ import { formatTime, formatTimeZone } from 'lib/dates.js'
5
+ import { ArrowRightIcon } from 'lib/icons/ArrowRight.js'
6
+ import { useNoiseThresholds } from 'lib/seam/noise-sensors/use-noise-thresholds.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
+
11
+ interface NoiseThresholdsListProps {
12
+ device: NoiseSensorDevice
13
+ }
14
+
15
+ export function NoiseThresholdsList({
16
+ device,
17
+ }: NoiseThresholdsListProps): JSX.Element {
18
+ const { noiseThresholds, isInitialLoading } = useNoiseThresholds({
19
+ device_id: device.device_id,
20
+ })
21
+
22
+ return (
23
+ <DetailSectionGroup>
24
+ <div className='seam-detail-section-wrap'>
25
+ <DetailSection
26
+ label={t.noiseThresholds}
27
+ tooltipContent={
28
+ device.device_type === 'minut_sensor' ? (
29
+ <div className='seam-detail-section-tooltip-inner-content'>
30
+ <span className='seam-tooltip-content'>
31
+ {t.minutTooltipFirst}
32
+ </span>
33
+ <span className='seam-tooltip-content'>
34
+ {t.minutTooltipSecond}
35
+ </span>
36
+ </div>
37
+ ) : (
38
+ t.tooltip
39
+ )
40
+ }
41
+ >
42
+ <Content
43
+ isInitialLoading={isInitialLoading}
44
+ noiseThresholds={noiseThresholds}
45
+ />
46
+ </DetailSection>
47
+
48
+ <div className='seam-detail-section-footer'>
49
+ <div className='seam-empty-div' />
50
+ <div className='seam-detail-section-footer-content'>
51
+ <div className='seam-detail-section-footer-content-text'>
52
+ <p>{getTimeZoneCaption(device, noiseThresholds)}</p>
53
+ </div>
54
+ </div>
55
+ </div>
56
+ </div>
57
+ </DetailSectionGroup>
58
+ )
59
+ }
60
+
61
+ function Content({
62
+ isInitialLoading,
63
+ noiseThresholds,
64
+ }: {
65
+ isInitialLoading: boolean
66
+ noiseThresholds: NoiseThresholds[] | undefined
67
+ }): JSX.Element | JSX.Element[] {
68
+ if (isInitialLoading) {
69
+ return (
70
+ <DetailRow
71
+ label={<span className='seam-detail-row-empty-label'>{t.loading}</span>}
72
+ />
73
+ )
74
+ }
75
+
76
+ if (noiseThresholds == null || noiseThresholds.length === 0) {
77
+ return (
78
+ <DetailRow
79
+ label={<span className='seam-detail-row-empty-label'>{t.none}</span>}
80
+ />
81
+ )
82
+ }
83
+
84
+ return noiseThresholds?.map((noiseThreshold) => (
85
+ <DetailRow
86
+ key={noiseThreshold.noise_threshold_id}
87
+ label={
88
+ <div className='seam-detail-row-label-column'>
89
+ {noiseThreshold.name !== '' && (
90
+ <span className='seam-detail-row-label'>{noiseThreshold.name}</span>
91
+ )}
92
+ <div className='seam-detail-row-label-block'>
93
+ <span className='seam-row-sublabel seam-row-sublabel-text-default'>
94
+ {formatTime(noiseThreshold.starts_daily_at)}
95
+ </span>
96
+ <ArrowRightIcon />
97
+ <span className='seam-row-sublabel seam-row-sublabel-text-default'>
98
+ {formatTime(noiseThreshold.ends_daily_at)}
99
+ </span>
100
+ </div>
101
+ </div>
102
+ }
103
+ >
104
+ <p>
105
+ {noiseThreshold.noise_threshold_decibels} {t.decibel}
106
+ </p>
107
+ </DetailRow>
108
+ ))
109
+ }
110
+
111
+ const getTimeZoneCaption = (
112
+ device: NoiseSensorDevice,
113
+ thresholds: NoiseThresholds[] | undefined
114
+ ): string | null => {
115
+ if (device.location?.timezone != null) {
116
+ return `${t.allTimesIn} ${formatTimeZone(device.location.timezone)}`
117
+ }
118
+
119
+ const firstThreshold = thresholds?.[0]
120
+
121
+ if (firstThreshold != null) {
122
+ const zonedTime = ZonedTime.from(firstThreshold.starts_daily_at)
123
+ return `${t.allTimesIn} ${formatTimeZone(zonedTime.timeZone)}`
124
+ }
125
+
126
+ return null
127
+ }
128
+
129
+ const t = {
130
+ noiseThresholds: 'Noise thresholds',
131
+ tooltip:
132
+ 'A noise threshold is the highest noise level (in dB) you want to allow for a given time range in the day.',
133
+ minutTooltipFirst:
134
+ 'A noise threshold is the highest noise level (in dB) you want to allow.',
135
+ minutTooltipSecond:
136
+ 'Quiet hours is a separate threshold that takes effect only for a specified time range.',
137
+ none: 'None',
138
+ loading: 'Loading...',
139
+ decibel: 'dB',
140
+ allTimesIn: 'All times in',
141
+ }
@@ -1,3 +1,3 @@
1
- const seamapiReactVersion = '2.14.0'
1
+ const seamapiReactVersion = '2.16.0'
2
2
 
3
3
  export default seamapiReactVersion
@@ -103,6 +103,7 @@
103
103
 
104
104
  .seam-label {
105
105
  color: colors.$text-gray-2;
106
+ white-space: nowrap;
106
107
  }
107
108
 
108
109
  .seam-status-text {
@@ -40,6 +40,12 @@
40
40
  gap: 32px;
41
41
  }
42
42
 
43
+ .seam-detail-section-wrap {
44
+ display: flex;
45
+ flex-direction: column;
46
+ gap: 6px;
47
+ }
48
+
43
49
  .seam-detail-section {
44
50
  width: 100%;
45
51
  }
@@ -66,6 +72,27 @@
66
72
  border: 1px solid colors.$text-gray-3;
67
73
  overflow: hidden;
68
74
  }
75
+
76
+ .seam-detail-section-footer {
77
+ width: 100%;
78
+ display: flex;
79
+ justify-content: space-between;
80
+ align-items: center;
81
+ flex-direction: row;
82
+ }
83
+
84
+ .seam-detail-section-footer-content-text {
85
+ font-size: 12px;
86
+ color: colors.$text-gray-2-5;
87
+ }
88
+
89
+ .seam-detail-section-tooltip-inner-content {
90
+ display: flex;
91
+ justify-content: flex-start;
92
+ align-items: flex-start;
93
+ flex-direction: column;
94
+ gap: 8px;
95
+ }
69
96
  }
70
97
 
71
98
  @mixin detail-row-common {
@@ -105,17 +132,45 @@
105
132
  gap: 4px;
106
133
  }
107
134
 
135
+ .seam-detail-row-label-column {
136
+ display: flex;
137
+ justify-content: flex-start;
138
+ align-items: flex-start;
139
+ flex-direction: column;
140
+ gap: 4px;
141
+ }
142
+
143
+ .seam-detail-row-label-block {
144
+ display: flex;
145
+ justify-content: flex-start;
146
+ align-items: center;
147
+ flex-direction: row;
148
+ gap: 4px;
149
+ }
150
+
108
151
  .seam-row-label {
109
152
  font-size: 16px;
110
153
  font-weight: 600;
111
154
  line-height: 118%;
112
155
  }
113
156
 
157
+ .seam-detail-row-empty-label {
158
+ font-size: 16px;
159
+ font-style: italic;
160
+ font-weight: 400;
161
+ line-height: 118%;
162
+ color: colors.$text-gray-2;
163
+ }
164
+
114
165
  .seam-row-sublabel {
115
166
  color: colors.$text-gray-1;
116
167
  font-size: 14px;
117
168
  font-weight: 400;
118
169
  line-height: 118%;
170
+
171
+ &.seam-row-sublabel-text-default {
172
+ color: colors.$text-default;
173
+ }
119
174
  }
120
175
 
121
176
  .seam-detail-row-hstack {
@@ -146,7 +146,7 @@
146
146
  height: var(--track-height);
147
147
  border-radius: 0.5em 0 0 0.5em;
148
148
  margin: 0;
149
- border: none;
149
+ border-style: none;
150
150
  border-right-width: 0;
151
151
  }
152
152