@seamapi/react 1.24.0 → 1.26.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 (69) hide show
  1. package/dist/elements.js +3987 -3821
  2. package/dist/elements.js.map +1 -1
  3. package/dist/index.css +157 -45
  4. package/dist/index.css.map +1 -1
  5. package/dist/index.min.css +1 -1
  6. package/dist/index.min.css.map +1 -1
  7. package/lib/seam/components/SupportedDeviceTable/HiddenDevicesOverlay.d.ts +5 -0
  8. package/lib/seam/components/SupportedDeviceTable/HiddenDevicesOverlay.js +8 -0
  9. package/lib/seam/components/SupportedDeviceTable/HiddenDevicesOverlay.js.map +1 -0
  10. package/lib/seam/components/SupportedDeviceTable/ShowAllDevicesButton.d.ts +8 -0
  11. package/lib/seam/components/SupportedDeviceTable/ShowAllDevicesButton.js +14 -0
  12. package/lib/seam/components/SupportedDeviceTable/ShowAllDevicesButton.js.map +1 -0
  13. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceBrandSection.d.ts +7 -0
  14. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceBrandSection.js +45 -0
  15. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceBrandSection.js.map +1 -0
  16. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceContent.d.ts +2 -1
  17. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceContent.js +36 -11
  18. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceContent.js.map +1 -1
  19. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceContentRows.d.ts +7 -0
  20. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceContentRows.js +12 -0
  21. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceContentRows.js.map +1 -0
  22. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceFilterArea.d.ts +2 -1
  23. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceFilterArea.js +12 -4
  24. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceFilterArea.js.map +1 -1
  25. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceFilterResultRowProps.d.ts +7 -0
  26. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceFilterResultRowProps.js +12 -0
  27. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceFilterResultRowProps.js.map +1 -0
  28. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceRow.d.ts +4 -0
  29. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceRow.js +19 -5
  30. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceRow.js.map +1 -1
  31. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceTable.d.ts +2 -1
  32. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceTable.js +3 -3
  33. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceTable.js.map +1 -1
  34. package/lib/seam/components/SupportedDeviceTable/use-device-provider.d.ts +2 -0
  35. package/lib/seam/components/SupportedDeviceTable/use-device-provider.js +15 -0
  36. package/lib/seam/components/SupportedDeviceTable/use-device-provider.js.map +1 -0
  37. package/lib/seam/components/SupportedDeviceTable/use-filtered-device-models.d.ts +5 -1
  38. package/lib/seam/components/SupportedDeviceTable/use-filtered-device-models.js +9 -2
  39. package/lib/seam/components/SupportedDeviceTable/use-filtered-device-models.js.map +1 -1
  40. package/lib/seam/devices/use-device-providers.d.ts +5 -0
  41. package/lib/seam/devices/use-device-providers.js +17 -0
  42. package/lib/seam/devices/use-device-providers.js.map +1 -0
  43. package/lib/version.d.ts +1 -1
  44. package/lib/version.js +1 -1
  45. package/package.json +14 -4
  46. package/src/lib/seam/components/SupportedDeviceTable/HiddenDevicesOverlay.tsx +11 -0
  47. package/src/lib/seam/components/SupportedDeviceTable/ShowAllDevicesButton.tsx +32 -0
  48. package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceBrandSection.tsx +96 -0
  49. package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceContent.tsx +62 -16
  50. package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceContentRows.tsx +27 -0
  51. package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceFilterArea.tsx +22 -3
  52. package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceFilterResultRowProps.tsx +49 -0
  53. package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceRow.tsx +52 -20
  54. package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceTable.element.ts +1 -0
  55. package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceTable.tsx +4 -0
  56. package/src/lib/seam/components/SupportedDeviceTable/use-device-provider.ts +22 -0
  57. package/src/lib/seam/components/SupportedDeviceTable/use-filtered-device-models.ts +21 -4
  58. package/src/lib/seam/devices/use-device-providers.ts +25 -0
  59. package/src/lib/version.ts +1 -1
  60. package/src/styles/_access-code-details.scss +1 -1
  61. package/src/styles/_buttons.scss +3 -3
  62. package/src/styles/_colors.scss +6 -2
  63. package/src/styles/_menus.scss +1 -1
  64. package/src/styles/_supported-device-table.scss +192 -52
  65. package/src/styles/_tables.scss +1 -1
  66. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceHeader.d.ts +0 -2
  67. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceHeader.js +0 -12
  68. package/lib/seam/components/SupportedDeviceTable/SupportedDeviceHeader.js.map +0 -1
  69. package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceHeader.tsx +0 -22
@@ -0,0 +1,27 @@
1
+ import { SupportedDeviceRow } from 'lib/seam/components/SupportedDeviceTable/SupportedDeviceRow.js'
2
+ import type { UseDeviceModelsData } from 'lib/seam/device-models/use-device-models.js'
3
+
4
+ interface SupportedDeviceContentRowsProps {
5
+ deviceModels: UseDeviceModelsData
6
+ }
7
+
8
+ export function SupportedDeviceContentRows({
9
+ deviceModels,
10
+ }: SupportedDeviceContentRowsProps): JSX.Element | null {
11
+ return (
12
+ <div className='seam-supported-device-table-content'>
13
+ {deviceModels.map((deviceModel, index) => (
14
+ <SupportedDeviceRow
15
+ key={[
16
+ deviceModel.main_category,
17
+ deviceModel.brand,
18
+ deviceModel.model_name,
19
+ deviceModel.manufacturer_model_id,
20
+ index,
21
+ ].join(':')}
22
+ deviceModel={deviceModel}
23
+ />
24
+ ))}
25
+ </div>
26
+ )
27
+ }
@@ -14,6 +14,7 @@ export interface SupportedDeviceFilterAreaProps {
14
14
  setFilterValue: (filter: string) => void
15
15
  filters: DeviceModelFilters
16
16
  setFilters: Dispatch<SetStateAction<DeviceModelFilters>>
17
+ brands: string[]
17
18
  }
18
19
 
19
20
  export function SupportedDeviceFilterArea({
@@ -21,13 +22,14 @@ export function SupportedDeviceFilterArea({
21
22
  setFilterValue,
22
23
  filters,
23
24
  setFilters,
25
+ brands,
24
26
  }: SupportedDeviceFilterAreaProps): JSX.Element {
25
27
  const appliedFiltersCount = Object.values(filters).filter(
26
28
  (v) => v != null && v !== false
27
29
  ).length
28
30
 
29
31
  const filterProperty = 'brand'
30
- const availableProperties = useAvailableProperties(filterProperty)
32
+ const availableProperties = useAvailableProperties(filterProperty, { brands })
31
33
 
32
34
  const resetFilter = (filterType: keyof DeviceModelFilters): void => {
33
35
  setFilters((filters) => ({
@@ -116,12 +118,29 @@ export function SupportedDeviceFilterArea({
116
118
  )
117
119
  }
118
120
 
119
- const useAvailableProperties = (property: keyof DeviceModel): string[] => {
121
+ const useAvailableProperties = (
122
+ property: keyof DeviceModel,
123
+ options: {
124
+ brands: string[]
125
+ }
126
+ ): string[] => {
120
127
  const { deviceModels } = useDeviceModels()
121
128
  if (deviceModels == null) return []
122
129
  const properties = new Set<string>()
123
130
  for (const deviceModel of deviceModels) {
124
- properties.add(capitalize(deviceModel[property]))
131
+ const value = deviceModel[property]
132
+
133
+ // If we're only looking at a subset of brands, such as ["yale", "august"], then we
134
+ // don't want to show other brands in the filter.
135
+ if (
136
+ property === 'brand' &&
137
+ options.brands.length > 0 &&
138
+ !options.brands.includes(value)
139
+ ) {
140
+ continue
141
+ }
142
+
143
+ properties.add(capitalize(value))
125
144
  }
126
145
  return Array.from(properties)
127
146
  }
@@ -0,0 +1,49 @@
1
+ import type { DeviceModel } from 'seamapi'
2
+
3
+ import {
4
+ connectionTypeNames,
5
+ ImageColumn,
6
+ StatusColumn,
7
+ } from 'lib/seam/components/SupportedDeviceTable/SupportedDeviceRow.js'
8
+ import { useDeviceProvider } from 'lib/seam/components/SupportedDeviceTable/use-device-provider.js'
9
+ import { DotDivider } from 'lib/ui/layout/DotDivider.js'
10
+
11
+ export interface SupportedDeviceFilterResultRowProps {
12
+ deviceModel: DeviceModel
13
+ }
14
+
15
+ export function SupportedDeviceFilterResultRow({
16
+ deviceModel,
17
+ }: SupportedDeviceFilterResultRowProps): JSX.Element {
18
+ return (
19
+ <div className='seam-row filter-result-row'>
20
+ <ImageColumn deviceModel={deviceModel} />
21
+ <ModelColumn deviceModel={deviceModel} />
22
+ <StatusColumn deviceModel={deviceModel} />
23
+ </div>
24
+ )
25
+ }
26
+
27
+ export function ModelColumn({
28
+ deviceModel,
29
+ }: SupportedDeviceFilterResultRowProps) {
30
+ const deviceProvider = useDeviceProvider(deviceModel.brand)
31
+
32
+ return (
33
+ <div className='seam-col seam-model-col'>
34
+ <div className='seam-model-name'>
35
+ <img
36
+ src={deviceProvider.image_url}
37
+ alt={deviceModel.brand}
38
+ className='seam-brand-image'
39
+ />{' '}
40
+ {deviceModel.model_name}
41
+ </div>
42
+ <div className='seam-model-id'>
43
+ {deviceModel.manufacturer_model_id}
44
+ <DotDivider />
45
+ {connectionTypeNames[deviceModel.connection_type]}
46
+ </div>
47
+ </div>
48
+ )
49
+ }
@@ -1,7 +1,7 @@
1
1
  import classNames from 'classnames'
2
2
  import type { DeviceModel } from 'seamapi'
3
3
 
4
- import { capitalize } from 'lib/strings.js'
4
+ import { DotDivider } from 'lib/ui/layout/DotDivider.js'
5
5
 
6
6
  export interface SupportedDeviceRowProps {
7
7
  deviceModel: DeviceModel
@@ -10,37 +10,69 @@ export interface SupportedDeviceRowProps {
10
10
  export function SupportedDeviceRow({
11
11
  deviceModel,
12
12
  }: SupportedDeviceRowProps): JSX.Element {
13
- const statusColor = supportLevelColors[deviceModel.support_level] ?? 'gray'
14
13
  return (
15
- <tr>
16
- <td>
14
+ <div className='seam-row'>
15
+ <ImageColumn deviceModel={deviceModel} />
16
+ <ModelColumn deviceModel={deviceModel} />
17
+ <StatusColumn deviceModel={deviceModel} />
18
+ </div>
19
+ )
20
+ }
21
+
22
+ export function ImageColumn({ deviceModel }: SupportedDeviceRowProps) {
23
+ return (
24
+ <div className='seam-col seam-device-image-col'>
25
+ <div className='seam-image-box'>
17
26
  <img width={40} src={deviceModel.icon_url} />
18
- </td>
19
- <td>{deviceModel.main_category}</td>
20
- <td>{deviceModel.model_name}</td>
21
- <td>{deviceModel.manufacturer_model_id}</td>
22
- <td>{connectionTypeNames[deviceModel.connection_type]}</td>
23
- <td>
24
- <div
25
- className={classNames('seam-status-pill', `status-${statusColor}`)}
26
- >
27
- <span>{capitalize(deviceModel.support_level)}</span>
28
- </div>
29
- </td>
30
- </tr>
27
+ </div>
28
+ </div>
29
+ )
30
+ }
31
+
32
+ export function ModelColumn({ deviceModel }: SupportedDeviceRowProps) {
33
+ return (
34
+ <div className='seam-col seam-model-col'>
35
+ <div className='seam-model-name'>{deviceModel.model_name}</div>
36
+ <div className='seam-model-id'>
37
+ {deviceModel.manufacturer_model_id}
38
+ <DotDivider />
39
+ {connectionTypeNames[deviceModel.connection_type]}
40
+ </div>
41
+ </div>
42
+ )
43
+ }
44
+
45
+ export function StatusColumn({ deviceModel }: SupportedDeviceRowProps) {
46
+ const statusColor = supportLevelColors[deviceModel.support_level] ?? 'unknown'
47
+
48
+ return (
49
+ <div className='seam-col seam-status-col'>
50
+ <div className={classNames('seam-status-pill', `status-${statusColor}`)}>
51
+ <span>{status[deviceModel.support_level]}</span>
52
+ </div>
53
+ </div>
31
54
  )
32
55
  }
33
56
 
34
57
  const supportLevelColors: Record<
35
58
  DeviceModel['support_level'],
36
- 'green' | 'blue' | 'orange'
59
+ 'green' | 'blue' | 'unknown'
37
60
  > = {
38
61
  live: 'green',
39
62
  beta: 'blue',
40
- unsupported: 'orange',
63
+ unsupported: 'unknown',
64
+ }
65
+
66
+ const status: Record<DeviceModel['support_level'], string> = {
67
+ live: 'LIVE',
68
+ beta: 'BETA',
69
+ unsupported: 'Inquire',
41
70
  }
42
71
 
43
- const connectionTypeNames: Record<DeviceModel['connection_type'], string> = {
72
+ export const connectionTypeNames: Record<
73
+ DeviceModel['connection_type'],
74
+ string
75
+ > = {
44
76
  wifi: 'Wifi',
45
77
  zwave: 'Z-Wave',
46
78
  zigbee: 'Zigbee',
@@ -7,6 +7,7 @@ export const name = 'seam-supported-device-table'
7
7
  export const props: ElementProps<SupportedDeviceTableProps> = {
8
8
  cannotFilter: 'boolean',
9
9
  disableFilter: 'boolean',
10
+ brands: 'json',
10
11
  className: 'string',
11
12
  }
12
13
 
@@ -11,12 +11,14 @@ export interface SupportedDeviceTableProps {
11
11
  * @deprecated Use disableFilter.
12
12
  */
13
13
  cannotFilter?: boolean
14
+ brands?: string[]
14
15
  className?: string
15
16
  }
16
17
 
17
18
  export function SupportedDeviceTable({
18
19
  disableFilter = false,
19
20
  cannotFilter,
21
+ brands = [],
20
22
  className,
21
23
  }: SupportedDeviceTableProps = {}): JSX.Element {
22
24
  const [filterValue, setFilterValue] = useState('')
@@ -41,6 +43,7 @@ export function SupportedDeviceTable({
41
43
  setFilterValue={setFilterValue}
42
44
  filters={filters}
43
45
  setFilters={setFilters}
46
+ brands={brands}
44
47
  />
45
48
  )}
46
49
  <SupportedDeviceContent
@@ -49,6 +52,7 @@ export function SupportedDeviceTable({
49
52
  }}
50
53
  filterValue={filterValue}
51
54
  filters={filters}
55
+ brands={brands}
52
56
  />
53
57
  </div>
54
58
  )
@@ -0,0 +1,22 @@
1
+ import type { DeviceProvider } from 'seamapi'
2
+
3
+ import { useDeviceProviders } from 'lib/seam/devices/use-device-providers.js'
4
+
5
+ export function useDeviceProvider(brand: string): DeviceProvider {
6
+ const { deviceProviders } = useDeviceProviders()
7
+
8
+ const definedProvider = deviceProviders?.find(
9
+ (provider) => provider.device_provider_name === brand
10
+ )
11
+
12
+ if (definedProvider != null) {
13
+ return definedProvider
14
+ }
15
+
16
+ return {
17
+ device_provider_name: 'unknown',
18
+ display_name: 'Unknown',
19
+ image_url: `https://connect.getseam.com/assets/images/logos/seam.png`,
20
+ provider_categories: [],
21
+ }
22
+ }
@@ -9,10 +9,15 @@ export interface DeviceModelFilters {
9
9
  brand: string | null
10
10
  }
11
11
 
12
- export const useFilteredDeviceModels = (
13
- filterValue: string,
12
+ export const useFilteredDeviceModels = ({
13
+ filterValue,
14
+ filters,
15
+ brands,
16
+ }: {
17
+ filterValue: string
14
18
  filters: DeviceModelFilters
15
- ): ReturnType<typeof useDeviceModels> => {
19
+ brands: string[]
20
+ }): ReturnType<typeof useDeviceModels> => {
16
21
  const params: UseDeviceModelsParams = {}
17
22
 
18
23
  if (filterValue.trim() !== '') {
@@ -31,5 +36,17 @@ export const useFilteredDeviceModels = (
31
36
  params.brand = filters.brand
32
37
  }
33
38
 
34
- return useDeviceModels(params)
39
+ const query = useDeviceModels(params)
40
+
41
+ if (brands.length === 0) {
42
+ return query
43
+ }
44
+
45
+ // If the user only wants models for a collection of brands, such as ["yale", "august"], then
46
+ // we'll filter everything else out here.
47
+ const onlySpecificBrands = query.deviceModels?.filter((deviceModel) =>
48
+ brands.includes(deviceModel.brand)
49
+ )
50
+
51
+ return { ...query, deviceModels: onlySpecificBrands }
35
52
  }
@@ -0,0 +1,25 @@
1
+ import { useQuery } from '@tanstack/react-query'
2
+ import type { DeviceProvider } from 'seamapi'
3
+
4
+ import { useSeamClient } from 'lib/seam/use-seam-client.js'
5
+
6
+ export function useDeviceProviders(): {
7
+ deviceProviders: DeviceProvider[] | undefined
8
+ isLoading: boolean
9
+ } {
10
+ const { client } = useSeamClient()
11
+
12
+ const { data, isLoading } = useQuery({
13
+ queryFn: async () => {
14
+ if (client == null) {
15
+ return []
16
+ }
17
+
18
+ return await client?.devices.listDeviceProviders({})
19
+ },
20
+ queryKey: ['devices', 'list_device_providers'],
21
+ enabled: client != null,
22
+ })
23
+
24
+ return { deviceProviders: data, isLoading }
25
+ }
@@ -1,3 +1,3 @@
1
- const seamapiReactVersion = '1.24.0'
1
+ const seamapiReactVersion = '1.26.0'
2
2
 
3
3
  export default seamapiReactVersion
@@ -30,7 +30,7 @@
30
30
  }
31
31
 
32
32
  > .seam-code {
33
- background: #fff;
33
+ background: colors.$white;
34
34
  border: 1px solid colors.$text-gray-2;
35
35
  border-radius: 8px;
36
36
  padding: 10px 16px;
@@ -6,7 +6,7 @@
6
6
  border-radius: 6px;
7
7
  border: 1px solid rgb(0 122 252 / 50%);
8
8
  cursor: pointer;
9
- background: #fff;
9
+ background: colors.$white;
10
10
  padding: 6px;
11
11
  line-height: 0;
12
12
 
@@ -62,7 +62,7 @@
62
62
  @mixin button-variant {
63
63
  &.seam-btn-solid {
64
64
  background: colors.$primary;
65
- color: #fff;
65
+ color: colors.$white;
66
66
  border: 1px solid colors.$primary;
67
67
 
68
68
  &:hover {
@@ -106,7 +106,7 @@
106
106
  &:disabled {
107
107
  color: colors.$text-gray-2-5;
108
108
  border-color: colors.$text-gray-3;
109
- background: #fff;
109
+ background: colors.$white;
110
110
  }
111
111
  }
112
112
  }
@@ -18,10 +18,10 @@ $bg-d: #cbd0d3;
18
18
  $bg-c: #dde0e2;
19
19
  $bg-b: #e9edef;
20
20
  $bg-a: #f1f3f4;
21
+ $bg-aa: #fafafa;
21
22
  $bg-gray: #ececec;
22
23
  $status-red: #e36857;
23
- $status-orange: #f3980f;
24
- $status-green: #27ae60;
24
+ $white: #fff;
25
25
  $alert-error-dark: #cb7d7d;
26
26
  $alert-error-line: #f1d4d4;
27
27
  $alert-error-fill: #ffefef;
@@ -29,3 +29,7 @@ $alert-warn-dark: #ca8852;
29
29
  $alert-warn-line: #f8d8be;
30
30
  $alert-warn-fill: #fff2e0;
31
31
  $item-hover-bg: #f4f6f8;
32
+ $pill-green-bg: rgb(98 232 139 / 30%);
33
+ $pill-green-text: #0d8841;
34
+ $pill-blue-bg: rgb(125 192 241 / 30%);
35
+ $pill-blue-text: #1653b8;
@@ -24,7 +24,7 @@
24
24
  width: 250px;
25
25
  position: absolute;
26
26
  padding: 8px 0;
27
- background: #fff;
27
+ background: colors.$white;
28
28
  box-shadow: 0 0 1px rgb(0 0 0 / 30%), 0 2px 16px 2px rgb(15 22 28 / 15%);
29
29
  border-radius: 8px;
30
30