@seamapi/react 1.3.0 → 1.4.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 (68) hide show
  1. package/README.md +25 -4
  2. package/index.css +43 -37
  3. package/index.css.map +1 -1
  4. package/index.min.css +1 -1
  5. package/index.min.css.map +1 -1
  6. package/lib/ui/AccessCodeDetails/AccessCodeDetails.d.ts +1 -0
  7. package/lib/ui/AccessCodeDetails/AccessCodeDevice.d.ts +1 -0
  8. package/lib/ui/AccessCodeTable/AccessCodeTable.d.ts +1 -0
  9. package/lib/ui/AccessCodeTable/CodeDetails.d.ts +1 -0
  10. package/lib/ui/Alert/Alert.js +1 -1
  11. package/lib/ui/Alert/Alert.js.map +1 -1
  12. package/lib/ui/Alert/Alerts.d.ts +2 -2
  13. package/lib/ui/Alert/Alerts.js.map +1 -1
  14. package/lib/ui/Button.js +1 -1
  15. package/lib/ui/Button.js.map +1 -1
  16. package/lib/ui/DeviceDetails/DeviceDetails.d.ts +1 -0
  17. package/lib/ui/DeviceDetails/DeviceDetails.js +10 -20
  18. package/lib/ui/DeviceDetails/DeviceDetails.js.map +1 -1
  19. package/lib/ui/DeviceDetails/DeviceModel.d.ts +1 -0
  20. package/lib/ui/DeviceTable/DeviceHealthBar.js +2 -2
  21. package/lib/ui/DeviceTable/DeviceHealthBar.js.map +1 -1
  22. package/lib/ui/DeviceTable/DeviceRow.d.ts +1 -0
  23. package/lib/ui/DeviceTable/DeviceTable.d.ts +1 -0
  24. package/lib/ui/IconButton.d.ts +1 -0
  25. package/lib/ui/Menu/Menu.js +1 -3
  26. package/lib/ui/Menu/Menu.js.map +1 -1
  27. package/lib/ui/SupportedDeviceTable/FilterCategoryMenu.d.ts +3 -9
  28. package/lib/ui/SupportedDeviceTable/FilterCategoryMenu.js +3 -7
  29. package/lib/ui/SupportedDeviceTable/FilterCategoryMenu.js.map +1 -1
  30. package/lib/ui/SupportedDeviceTable/SupportedDeviceContent.js +27 -34
  31. package/lib/ui/SupportedDeviceTable/SupportedDeviceContent.js.map +1 -1
  32. package/lib/ui/SupportedDeviceTable/SupportedDeviceFilterArea.js +3 -3
  33. package/lib/ui/SupportedDeviceTable/SupportedDeviceFilterArea.js.map +1 -1
  34. package/lib/ui/SupportedDeviceTable/SupportedDeviceRow.js +1 -1
  35. package/lib/ui/SupportedDeviceTable/SupportedDeviceRow.js.map +1 -1
  36. package/lib/ui/Table/EmptyPlaceholder.d.ts +1 -0
  37. package/lib/ui/Table/TableCell.d.ts +1 -0
  38. package/lib/ui/Table/TableFilterBar/TableFilterBar.d.ts +2 -2
  39. package/lib/ui/Table/TableFilterBar/TableFilterBar.js +2 -3
  40. package/lib/ui/Table/TableFilterBar/TableFilterBar.js.map +1 -1
  41. package/lib/ui/Table/TableRow.d.ts +1 -0
  42. package/lib/ui/TextButton.d.ts +1 -0
  43. package/lib/ui/TextField/SearchTextField.d.ts +1 -0
  44. package/lib/ui/TextField/TextField.js +1 -1
  45. package/lib/ui/TextField/TextField.js.map +1 -1
  46. package/lib/ui/device/BatteryStatus.d.ts +1 -0
  47. package/lib/ui/device/LockStatus.d.ts +1 -0
  48. package/lib/ui/device/OnlineStatus.d.ts +1 -0
  49. package/lib/ui/layout/ContentHeader.d.ts +1 -0
  50. package/lib/ui/layout/DotDivider.d.ts +1 -0
  51. package/lib/ui/typography/Title.d.ts +1 -0
  52. package/lib/version.js +1 -1
  53. package/package.json +3 -3
  54. package/src/lib/ui/Alert/Alert.tsx +1 -1
  55. package/src/lib/ui/Alert/Alerts.tsx +4 -2
  56. package/src/lib/ui/Button.tsx +1 -1
  57. package/src/lib/ui/DeviceDetails/DeviceDetails.tsx +11 -31
  58. package/src/lib/ui/DeviceTable/DeviceHealthBar.tsx +2 -2
  59. package/src/lib/ui/Menu/Menu.tsx +5 -4
  60. package/src/lib/ui/SupportedDeviceTable/FilterCategoryMenu.tsx +6 -11
  61. package/src/lib/ui/SupportedDeviceTable/SupportedDeviceContent.tsx +42 -54
  62. package/src/lib/ui/SupportedDeviceTable/SupportedDeviceFilterArea.tsx +4 -4
  63. package/src/lib/ui/SupportedDeviceTable/SupportedDeviceRow.tsx +1 -1
  64. package/src/lib/ui/Table/TableFilterBar/TableFilterBar.tsx +3 -6
  65. package/src/lib/ui/TextField/TextField.tsx +1 -1
  66. package/src/styles/_main.scss +2 -2
  67. package/src/styles/_menus.scss +9 -1
  68. package/src/styles/{_supported-devices.scss → _supported-device-table.scss} +8 -8
@@ -1,6 +1,5 @@
1
1
  import { useQuery } from '@tanstack/react-query'
2
- import axios from 'axios'
3
- import { useCallback, useEffect, useState } from 'react'
2
+ import { useState } from 'react'
4
3
 
5
4
  import { Button } from 'lib/ui/Button.js'
6
5
  import { SupportedDeviceFilterArea } from 'lib/ui/SupportedDeviceTable/SupportedDeviceFilterArea.js'
@@ -9,8 +8,6 @@ import type { DeviceModel, Filters } from 'lib/ui/SupportedDeviceTable/types.js'
9
8
  import { SupportedDeviceHeader } from './SupportedDeviceHeader.js'
10
9
  import { SupportedDeviceRow } from './SupportedDeviceRow.js'
11
10
 
12
- const BASE_URL = 'https://devicedb.seam.co/api/device_models/list'
13
-
14
11
  export interface SupportedDeviceContentProps {
15
12
  cannotFilter?: boolean
16
13
  }
@@ -18,7 +15,6 @@ export interface SupportedDeviceContentProps {
18
15
  export function SupportedDeviceContent({
19
16
  cannotFilter = false,
20
17
  }: SupportedDeviceContentProps) {
21
- const [allDeviceModels, setAllDeviceModels] = useState<DeviceModel[]>([])
22
18
  const [filterValue, setFilterValue] = useState('')
23
19
  const [filters, setFilters] = useState<Filters>({
24
20
  supportedOnly: false,
@@ -26,54 +22,46 @@ export function SupportedDeviceContent({
26
22
  brand: null,
27
23
  })
28
24
 
29
- const fetchDeviceModels = useCallback(async () => {
30
- const queries = []
31
-
32
- if (filterValue.trim() !== '') {
33
- queries.push(`text_search=${encodeURIComponent(filterValue.trim())}`)
34
- }
35
-
36
- if (filters.supportedOnly) {
37
- queries.push('support_level=live')
38
- }
39
-
40
- if (filters.category !== null) {
41
- queries.push(`main_category=${encodeURIComponent(filters.category)}`)
42
- }
43
-
44
- if (filters.brand !== null) {
45
- queries.push(`brand=${encodeURIComponent(filters.brand)}`)
46
- }
47
-
48
- const url = `${BASE_URL}?${queries.join('&')}`
49
- return await axios.get(url)
50
- }, [filterValue, filters])
51
-
52
- const { data, isLoading, isError, refetch } = useQuery<{
53
- data: {
54
- device_models?: DeviceModel[]
55
- }
56
- }>({
25
+ const {
26
+ data: deviceModels,
27
+ isLoading,
28
+ isError,
29
+ refetch,
30
+ } = useQuery<DeviceModel[]>({
57
31
  queryKey: ['supported_devices', filterValue, filters],
58
- queryFn: fetchDeviceModels,
32
+ queryFn: async () => {
33
+ const url = new URL('https://devicedb.seam.co/api/device_models/list')
34
+
35
+ if (filterValue.trim() !== '') {
36
+ url.searchParams.set('text_search', filterValue.trim())
37
+ }
38
+
39
+ if (filters.supportedOnly) {
40
+ url.searchParams.set('support_level', 'live')
41
+ }
42
+
43
+ if (filters.category !== null) {
44
+ url.searchParams.set('main_category', filters.category)
45
+ }
46
+
47
+ if (filters.brand !== null) {
48
+ url.searchParams.set('brand', filters.brand)
49
+ }
50
+
51
+ const res = await fetch(url)
52
+ if (!res.ok) {
53
+ throw new Error('Failed to load device models')
54
+ }
55
+ const data = await res.json()
56
+ return data?.device_models ?? []
57
+ },
59
58
  })
60
59
 
61
- useEffect(() => {
62
- if (
63
- data?.data?.device_models !== undefined &&
64
- allDeviceModels.length === 0
65
- ) {
66
- setAllDeviceModels(data.data.device_models)
67
- }
68
- }, [data, allDeviceModels.length])
69
-
70
- const deviceModels = data?.data?.device_models ?? []
71
-
72
60
  return (
73
- <div className='seam-supported-devices-table-wrap'>
61
+ <div className='seam-supported-device-table-content-wrap'>
74
62
  {!cannotFilter && (
75
63
  <SupportedDeviceFilterArea
76
- deviceModels={allDeviceModels}
64
+ deviceModels={deviceModels ?? []}
77
65
  filterValue={filterValue}
78
66
  setFilterValue={setFilterValue}
79
67
  filters={filters}
@@ -82,13 +70,13 @@ export function SupportedDeviceContent({
82
70
  )}
83
71
 
84
72
  {isLoading && (
85
- <div className='seam-supported-devices-table-state-block'>
73
+ <div className='seam-supported-device-table-content-state-block'>
86
74
  <p>Loading device models...</p>
87
75
  </div>
88
76
  )}
89
77
 
90
78
  {isError && (
91
- <div className='seam-supported-devices-table-state-block'>
79
+ <div className='seam-supported-device-table-content-state-block'>
92
80
  <p>There was an error fetching device models.</p>
93
81
  <Button
94
82
  variant='solid'
@@ -102,8 +90,8 @@ export function SupportedDeviceContent({
102
90
  </div>
103
91
  )}
104
92
 
105
- {!isLoading && !isError && data?.data?.device_models !== null && (
106
- <table className='seam-supported-devices-table'>
93
+ {!isLoading && !isError && deviceModels !== null && (
94
+ <table className='seam-supported-device-table-content'>
107
95
  <SupportedDeviceHeader />
108
96
  <tbody>
109
97
  {deviceModels.length !== 0 &&
@@ -115,9 +103,9 @@ export function SupportedDeviceContent({
115
103
  ))}
116
104
 
117
105
  {deviceModels.length === 0 && (
118
- <tr className='seam-supported-devices-table-message-row'>
106
+ <tr className='seam-supported-device-table-content-message-row'>
119
107
  <td colSpan={6}>
120
- <div className='seam-supported-devices-table-message'>
108
+ <div className='seam-supported-device-table-content-message'>
121
109
  {filterValue.length === 0 ? (
122
110
  <p>No device models found.</p>
123
111
  ) : (
@@ -129,7 +117,7 @@ export function SupportedDeviceContent({
129
117
  onClick={() => {
130
118
  setFilterValue('')
131
119
  }}
132
- className='seam-supported-devices-table-message-clear-search'
120
+ className='seam-supported-device-table-content-message-clear-search'
133
121
  >
134
122
  Clear search terms
135
123
  </Button>
@@ -55,7 +55,7 @@ export function SupportedDeviceFilterArea({
55
55
  : 'Filter'
56
56
 
57
57
  return (
58
- <div className='seam-supported-devices-filter-area'>
58
+ <div className='seam-supported-device-table-filter-area'>
59
59
  <div className='seam-deliberate-block' />
60
60
  <div className='seam-filters-wrap'>
61
61
  <Menu
@@ -70,7 +70,7 @@ export function SupportedDeviceFilterArea({
70
70
  )}
71
71
  >
72
72
  <div
73
- className='seam-supported-devices-filter-menu'
73
+ className='seam-supported-device-table-filter-menu'
74
74
  onClick={(event) => {
75
75
  event.stopPropagation()
76
76
  }}
@@ -116,13 +116,13 @@ export function SupportedDeviceFilterArea({
116
116
  </div>
117
117
  </Menu>
118
118
 
119
- <div className='seam-supported-devices-filter-area-search-bar-wrap'>
119
+ <div className='seam-supported-device-table-filter-area-search-bar-wrap'>
120
120
  <SearchTextField
121
121
  value={filterValue}
122
122
  onChange={(value) => {
123
123
  setFilterValue(value)
124
124
  }}
125
- className='seam-supported-devices-filter-area-search-bar'
125
+ className='seam-supported-device-table-filter-area-search-bar'
126
126
  />
127
127
  </div>
128
128
  </div>
@@ -11,7 +11,7 @@ export function SupportedDeviceRow({ deviceModel }: SupportedDeviceRowProps) {
11
11
  return (
12
12
  <tr>
13
13
  <td>
14
- <img style={{ width: 40 }} src={deviceModel.icon_url} />
14
+ <img width={40} src={deviceModel.icon_url} />
15
15
  </td>
16
16
  <td>{deviceModel.main_category}</td>
17
17
  <td>{deviceModel.model_name}</td>
@@ -3,23 +3,20 @@ import { IconButton } from 'lib/ui/IconButton.js'
3
3
  import type { ButtonProps, DivProps } from 'lib/ui/types.js'
4
4
 
5
5
  interface TableFilterBarProps extends DivProps {
6
- isFilterCleared?: boolean
6
+ filterCleared?: boolean
7
7
  onFilterClear?: () => void
8
8
  }
9
9
 
10
10
  export function TableFilterBar({
11
- isFilterCleared,
11
+ filterCleared = false,
12
12
  onFilterClear,
13
13
  children,
14
14
  ...props
15
15
  }: TableFilterBarProps) {
16
- const showClearFilterButton = isFilterCleared === false
17
16
  return (
18
17
  <div className='seam-table-filter-bar' {...props}>
19
18
  {children}{' '}
20
- {showClearFilterButton ? (
21
- <ClearFiltersButton onClick={onFilterClear} />
22
- ) : null}
19
+ {!filterCleared && <ClearFiltersButton onClick={onFilterClear} />}
23
20
  </div>
24
21
  )
25
22
  }
@@ -23,7 +23,7 @@ export function TextField(props: TextFieldProps): JSX.Element {
23
23
  startAdornment,
24
24
  endAdornment,
25
25
  inputProps,
26
- disabled,
26
+ disabled = false,
27
27
  } = props
28
28
 
29
29
  return (
@@ -12,7 +12,7 @@
12
12
  @use './device-details';
13
13
  @use './device-table';
14
14
  @use './access-code-details';
15
- @use './supported-devices';
15
+ @use './supported-device-table';
16
16
 
17
17
  .seam-components {
18
18
  // Reset
@@ -33,5 +33,5 @@
33
33
  @include access-code-table.all;
34
34
  @include access-code-details.all;
35
35
  @include alert.all;
36
- @include supported-devices.all;
36
+ @include supported-device-table.all;
37
37
  }
@@ -9,7 +9,15 @@
9
9
  position: fixed;
10
10
  inset: 0;
11
11
  z-index: 999999;
12
- display: none; // Toggled in JS (component)
12
+ display: none;
13
+ }
14
+
15
+ .seam-menu-hidden {
16
+ display: none;
17
+ }
18
+
19
+ .seam-menu-visible {
20
+ display: flex;
13
21
  }
14
22
 
15
23
  .seam-menu-content {
@@ -3,7 +3,7 @@
3
3
  $row-padding: 8px;
4
4
 
5
5
  @mixin all {
6
- .seam-supported-devices-filter-area {
6
+ .seam-supported-device-table-filter-area {
7
7
  width: 100%;
8
8
  display: flex;
9
9
  justify-content: space-between;
@@ -19,7 +19,7 @@ $row-padding: 8px;
19
19
  gap: 8px;
20
20
  }
21
21
 
22
- .seam-supported-devices-filter-area-search-bar-wrap {
22
+ .seam-supported-device-table-filter-area-search-bar-wrap {
23
23
  position: relative;
24
24
  display: flex;
25
25
  justify-content: center;
@@ -28,7 +28,7 @@ $row-padding: 8px;
28
28
  }
29
29
  }
30
30
 
31
- .seam-supported-devices-filter-menu {
31
+ .seam-supported-device-table-filter-menu {
32
32
  width: 100%;
33
33
  padding: 8px 16px;
34
34
 
@@ -56,7 +56,7 @@ $row-padding: 8px;
56
56
  }
57
57
  }
58
58
 
59
- .seam-supported-devices-filter-menu-wrap {
59
+ .seam-supported-device-table-filter-menu-wrap {
60
60
  width: 100%;
61
61
  display: flex;
62
62
  justify-content: space-between;
@@ -92,7 +92,7 @@ $row-padding: 8px;
92
92
  }
93
93
  }
94
94
 
95
- .seam-supported-devices-table-state-block {
95
+ .seam-supported-device-table-content-state-block {
96
96
  width: 100%;
97
97
  background-color: colors.$bg-a;
98
98
  padding: 32px 8px;
@@ -103,11 +103,11 @@ $row-padding: 8px;
103
103
  gap: 8px;
104
104
  }
105
105
 
106
- .seam-supported-devices-table-message-row {
106
+ .seam-supported-device-table-content-message-row {
107
107
  height: auto !important;
108
108
  }
109
109
 
110
- .seam-supported-devices-table-message {
110
+ .seam-supported-device-table-content-message {
111
111
  width: 100%;
112
112
  padding: 32px 0;
113
113
  display: flex;
@@ -128,7 +128,7 @@ $row-padding: 8px;
128
128
  }
129
129
  }
130
130
 
131
- .seam-supported-devices-table {
131
+ .seam-supported-device-table-content {
132
132
  width: 100%;
133
133
  overflow-x: auto;
134
134
  table-layout: auto;