@seamapi/react 1.61.1 → 1.62.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 (54) hide show
  1. package/README.md +1 -1
  2. package/dist/elements.js +4586 -4403
  3. package/dist/elements.js.map +1 -1
  4. package/dist/index.css +124 -12
  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/CheckGreen.d.ts +2 -0
  9. package/lib/icons/CheckGreen.js +7 -0
  10. package/lib/icons/CheckGreen.js.map +1 -0
  11. package/lib/icons/CloseWhite.d.ts +2 -0
  12. package/lib/icons/CloseWhite.js +7 -0
  13. package/lib/icons/CloseWhite.js.map +1 -0
  14. package/lib/seam/components/AccessCodeTable/AccessCodeTable.js +21 -8
  15. package/lib/seam/components/AccessCodeTable/AccessCodeTable.js.map +1 -1
  16. package/lib/seam/components/CreateAccessCodeForm/CreateAccessCodeForm.d.ts +2 -1
  17. package/lib/seam/components/CreateAccessCodeForm/CreateAccessCodeForm.js +7 -4
  18. package/lib/seam/components/CreateAccessCodeForm/CreateAccessCodeForm.js.map +1 -1
  19. package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.js +1 -2
  20. package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.js.map +1 -1
  21. package/lib/seam/components/EditAccessCodeForm/EditAccessCodeForm.d.ts +2 -1
  22. package/lib/seam/components/EditAccessCodeForm/EditAccessCodeForm.js +11 -4
  23. package/lib/seam/components/EditAccessCodeForm/EditAccessCodeForm.js.map +1 -1
  24. package/lib/seam/components/SupportedDeviceTable/FilterCategoryMenu.js +12 -9
  25. package/lib/seam/components/SupportedDeviceTable/FilterCategoryMenu.js.map +1 -1
  26. package/lib/ui/Menu/Menu.js +32 -25
  27. package/lib/ui/Menu/Menu.js.map +1 -1
  28. package/lib/ui/Snackbar/Snackbar.d.ts +17 -0
  29. package/lib/ui/Snackbar/Snackbar.js +34 -0
  30. package/lib/ui/Snackbar/Snackbar.js.map +1 -0
  31. package/lib/ui/thermostat/ClimateModeMenu.js +4 -4
  32. package/lib/ui/thermostat/ClimateModeMenu.js.map +1 -1
  33. package/lib/version.d.ts +1 -1
  34. package/lib/version.js +1 -1
  35. package/package.json +2 -2
  36. package/src/lib/icons/CheckGreen.tsx +36 -0
  37. package/src/lib/icons/CloseWhite.tsx +36 -0
  38. package/src/lib/seam/components/AccessCodeTable/AccessCodeTable.tsx +96 -58
  39. package/src/lib/seam/components/CreateAccessCodeForm/CreateAccessCodeForm.element.ts +1 -0
  40. package/src/lib/seam/components/CreateAccessCodeForm/CreateAccessCodeForm.tsx +20 -4
  41. package/src/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.tsx +1 -6
  42. package/src/lib/seam/components/EditAccessCodeForm/EditAccessCodeForm.element.ts +1 -0
  43. package/src/lib/seam/components/EditAccessCodeForm/EditAccessCodeForm.tsx +18 -2
  44. package/src/lib/seam/components/SupportedDeviceTable/FilterCategoryMenu.tsx +20 -15
  45. package/src/lib/ui/Menu/Menu.tsx +50 -40
  46. package/src/lib/ui/Snackbar/Snackbar.tsx +93 -0
  47. package/src/lib/ui/thermostat/ClimateModeMenu.tsx +4 -4
  48. package/src/lib/version.ts +1 -1
  49. package/src/styles/_colors.scss +2 -0
  50. package/src/styles/_loading_toast.scss +5 -16
  51. package/src/styles/_main.scss +2 -0
  52. package/src/styles/_motion.scss +34 -0
  53. package/src/styles/_snackbar.scss +110 -0
  54. package/src/styles/_supported-device-table.scss +9 -0
@@ -0,0 +1,93 @@
1
+ import classNames from 'classnames'
2
+ import { useEffect } from 'react'
3
+
4
+ import { CheckGreenIcon } from 'lib/icons/CheckGreen.js'
5
+ import { CloseWhiteIcon } from 'lib/icons/CloseWhite.js'
6
+ import { ExclamationCircleIcon } from 'lib/icons/ExclamationCircle.js'
7
+
8
+ type SnackbarVariant = 'success' | 'error'
9
+
10
+ interface SnackbarProps {
11
+ message: string
12
+ variant: SnackbarVariant
13
+ visible: boolean
14
+ onClose: () => void
15
+ action?: {
16
+ label: string
17
+ onClick: () => void
18
+ }
19
+ autoDismiss?: boolean
20
+ dismissAfterMs?: number
21
+ disableCloseButton?: boolean
22
+ }
23
+
24
+ export function Snackbar({
25
+ message,
26
+ variant,
27
+ visible,
28
+ action,
29
+ autoDismiss = false,
30
+ dismissAfterMs = 5000,
31
+ disableCloseButton = false,
32
+ onClose,
33
+ }: SnackbarProps): JSX.Element {
34
+ const { label: actionLabel, onClick: handleActionClick } = action ?? {}
35
+
36
+ useEffect(() => {
37
+ if (!autoDismiss) {
38
+ return () => {}
39
+ }
40
+
41
+ const timeout = globalThis.setTimeout(() => {
42
+ onClose()
43
+ }, dismissAfterMs)
44
+
45
+ return () => {
46
+ globalThis.clearTimeout(timeout)
47
+ }
48
+ }, [autoDismiss, dismissAfterMs, onClose])
49
+
50
+ return (
51
+ <div className='seam-snackbar-wrap'>
52
+ <div
53
+ className={classNames('seam-snackbar', {
54
+ 'seam-snackbar-visible': visible,
55
+ })}
56
+ >
57
+ <SnackbarIcon variant={variant} />
58
+ <div className='seam-snackbar-message-wrap'>
59
+ <p className='seam-snackbar-message'>{message}</p>
60
+ </div>
61
+ <div className='seam-snackbar-actions-wrap'>
62
+ {action != null && (
63
+ <button
64
+ className='seam-snackbar-action'
65
+ onClick={handleActionClick}
66
+ >
67
+ <span className='seam-snackbar-action-label'>{actionLabel}</span>
68
+ </button>
69
+ )}
70
+ {!disableCloseButton && (
71
+ <button
72
+ className='seam-snackbar-close-button'
73
+ onClick={() => {
74
+ onClose()
75
+ }}
76
+ >
77
+ <CloseWhiteIcon />
78
+ </button>
79
+ )}
80
+ </div>
81
+ </div>
82
+ </div>
83
+ )
84
+ }
85
+
86
+ function SnackbarIcon(props: { variant: SnackbarVariant }): JSX.Element {
87
+ switch (props.variant) {
88
+ case 'success':
89
+ return <CheckGreenIcon />
90
+ case 'error':
91
+ return <ExclamationCircleIcon />
92
+ }
93
+ }
@@ -24,7 +24,7 @@ export function ClimateModeMenu({
24
24
  renderButton={({ onOpen }) => (
25
25
  <button onClick={onOpen} className='seam-climate-mode-menu-button'>
26
26
  <div className='seam-climate-mode-menu-button-icon'>
27
- {ModeIcon(mode)}
27
+ <ModeIcon mode={mode} />
28
28
  </div>
29
29
  <ChevronDownIcon />
30
30
  </button>
@@ -39,7 +39,7 @@ export function ClimateModeMenu({
39
39
  <ThermoModeMenuOption
40
40
  key={m}
41
41
  label={t[m]}
42
- icon={ModeIcon(m)}
42
+ icon={<ModeIcon mode={m} />}
43
43
  isSelected={mode === m}
44
44
  onClick={() => {
45
45
  onChange(m)
@@ -50,8 +50,8 @@ export function ClimateModeMenu({
50
50
  )
51
51
  }
52
52
 
53
- function ModeIcon(mode: HvacModeSetting): JSX.Element {
54
- switch (mode) {
53
+ function ModeIcon(props: { mode: HvacModeSetting }): JSX.Element {
54
+ switch (props.mode) {
55
55
  case 'heat':
56
56
  return <ThermostatHeatIcon />
57
57
  case 'cool':
@@ -1,3 +1,3 @@
1
- const seamapiReactVersion = '1.61.1'
1
+ const seamapiReactVersion = '1.62.0'
2
2
 
3
3
  export default seamapiReactVersion
@@ -20,6 +20,7 @@ $bg-b: #e9edef;
20
20
  $bg-a: #f1f3f4;
21
21
  $bg-aa: #fafafa;
22
22
  $bg-gray: #ececec;
23
+ $feedback-bg: #30373a;
23
24
  $status-red: #e36857;
24
25
  $white: #fff;
25
26
  $black: #000;
@@ -38,3 +39,4 @@ $thermo-orange: #fc8e28;
38
39
  $thermo-orange-faded: #fff2e0;
39
40
  $thermo-blue: #6b95ff;
40
41
  $thermo-blue-faded: #e7f2ff;
42
+ $text-hyperlink: #6ac1ff;
@@ -1,21 +1,10 @@
1
1
  @use './colors';
2
-
3
- @keyframes scale-in {
4
- 0% {
5
- transform: scale(0.5);
6
- opacity: 0;
7
- visibility: hidden;
8
- }
9
-
10
- 100% {
11
- transform: scale(1);
12
- opacity: 1;
13
- visibility: visible;
14
- }
15
- }
2
+ @use './motion';
16
3
 
17
4
  @mixin all {
18
5
  .seam-loading-toast {
6
+ @include motion.scale-in;
7
+
19
8
  height: 32px;
20
9
  padding: 0 10px;
21
10
  display: flex;
@@ -29,8 +18,8 @@
29
18
  0 0 1px 0 rgb(24 29 37 / 25%);
30
19
  gap: 8px;
31
20
  will-change: transform;
32
- animation: scale-in 0.2s cubic-bezier(0.22, 1, 0.36, 1);
33
- transition: all 0.2s cubic-bezier(0.22, 1, 0.36, 1);
21
+ animation: scale-in 0.2s motion.$ease-out-quint;
22
+ transition: all 0.2s motion.$ease-out-quint;
34
23
  pointer-events: none;
35
24
  position: absolute;
36
25
  z-index: 9;
@@ -21,6 +21,7 @@
21
21
  @use './thermostat';
22
22
  @use './tooltip';
23
23
  @use './seam-table';
24
+ @use './snackbar';
24
25
  @use './spinner';
25
26
  @use './switch';
26
27
  @use './climate-setting-schedule-form';
@@ -45,6 +46,7 @@
45
46
  @include checkbox.all;
46
47
  @include radio-field.all;
47
48
  @include tooltip.all;
49
+ @include snackbar.all;
48
50
  @include spinner.all;
49
51
  @include switch.all;
50
52
  @include time-zone-picker.all;
@@ -0,0 +1,34 @@
1
+ $ease-out-quint: cubic-bezier(0.22, 1, 0.36, 1);
2
+ $ease-in-out-quint: cubic-bezier(0.83, 0, 0.17, 1);
3
+
4
+ @mixin scale-in {
5
+ @keyframes scale-in {
6
+ 0% {
7
+ transform: scale(0.5);
8
+ opacity: 0;
9
+ visibility: hidden;
10
+ }
11
+
12
+ 100% {
13
+ transform: scale(1);
14
+ opacity: 1;
15
+ visibility: visible;
16
+ }
17
+ }
18
+ }
19
+
20
+ @mixin fade-in-up {
21
+ @keyframes fade-in-up {
22
+ 0% {
23
+ transform: translateY(24px);
24
+ opacity: 0;
25
+ visibility: hidden;
26
+ }
27
+
28
+ 100% {
29
+ transform: translateY(0);
30
+ opacity: 1;
31
+ visibility: visible;
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,110 @@
1
+ @use './colors';
2
+ @use './motion';
3
+
4
+ @mixin all {
5
+ .seam-snackbar-wrap {
6
+ width: 100%;
7
+ position: fixed;
8
+ bottom: 0;
9
+ display: flex;
10
+ justify-content: center;
11
+ align-items: center;
12
+ pointer-events: none;
13
+ height: 0;
14
+ z-index: 9;
15
+ }
16
+
17
+ .seam-snackbar {
18
+ @include motion.fade-in-up;
19
+
20
+ pointer-events: auto;
21
+ display: flex;
22
+ padding: 16px;
23
+ align-items: flex-start;
24
+ border-radius: 12px;
25
+ background: colors.$feedback-bg;
26
+ box-shadow: 0 2px 12px 0 rgb(0 0 0 / 25%);
27
+ gap: 10px;
28
+ position: absolute;
29
+ bottom: 24px;
30
+ will-change: transform;
31
+ transition: all 0.2s motion.$ease-in-out-quint;
32
+ opacity: 0;
33
+ visibility: hidden;
34
+ transform: translateY(24px);
35
+
36
+ &.seam-snackbar-visible {
37
+ animation: fade-in-up 0.2s motion.$ease-in-out-quint;
38
+ transform: translateY(0);
39
+ opacity: 1;
40
+ visibility: visible;
41
+ }
42
+
43
+ .seam-snackbar-message-wrap {
44
+ display: flex;
45
+ max-width: 300px;
46
+ }
47
+
48
+ .seam-snackbar-message {
49
+ color: colors.$white;
50
+ font-size: 16px;
51
+ font-weight: 400;
52
+ line-height: 134%;
53
+ margin: 0;
54
+ padding: 0;
55
+ }
56
+
57
+ .seam-snackbar-actions-wrap {
58
+ height: 24px;
59
+ display: flex;
60
+ align-items: center;
61
+ flex-direction: row;
62
+ gap: 16px;
63
+ }
64
+
65
+ .seam-snackbar-action {
66
+ appearance: none;
67
+ background-color: transparent;
68
+ margin: 0;
69
+ padding: 0;
70
+ padding-top: 0;
71
+ display: flex;
72
+ justify-content: center;
73
+ align-items: center;
74
+ box-shadow: none;
75
+ border: none;
76
+ cursor: pointer;
77
+ transition: opacity 0.2s ease-in-out;
78
+
79
+ &:hover {
80
+ opacity: 0.75;
81
+ }
82
+
83
+ .seam-snackbar-action-label {
84
+ color: colors.$text-hyperlink;
85
+ font-size: 16px;
86
+ font-weight: 600;
87
+ line-height: 0.8;
88
+ white-space: nowrap;
89
+ }
90
+ }
91
+
92
+ .seam-snackbar-close-button {
93
+ appearance: none;
94
+ background-color: transparent;
95
+ display: flex;
96
+ justify-content: center;
97
+ align-items: center;
98
+ border: 0;
99
+ box-shadow: none;
100
+ margin: 0;
101
+ padding: 0;
102
+ cursor: pointer;
103
+ transition: opacity 0.2s ease-in-out;
104
+
105
+ &:hover {
106
+ opacity: 0.75;
107
+ }
108
+ }
109
+ }
110
+ }
@@ -3,6 +3,10 @@
3
3
  $row-padding: 8px;
4
4
 
5
5
  @mixin all {
6
+ .seam-supported-device-table-content-wrap {
7
+ background: colors.$white;
8
+ }
9
+
6
10
  .seam-supported-device-table-filter-area {
7
11
  width: 100%;
8
12
  display: flex;
@@ -372,4 +376,9 @@ $row-padding: 8px;
372
376
  align-items: center;
373
377
  }
374
378
  }
379
+
380
+ .seam-supported-device-table-filter-menu-content {
381
+ max-height: 300px;
382
+ overflow: auto;
383
+ }
375
384
  }