@seamapi/react 1.6.0 → 1.8.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.
- package/README.md +18 -5
- package/dist/elements.js +25043 -0
- package/dist/elements.js.map +1 -0
- package/hooks.d.ts +1 -0
- package/hooks.js +2 -0
- package/hooks.js.map +1 -0
- package/index.css +6 -0
- package/index.css.map +1 -1
- package/index.min.css +1 -1
- package/index.min.css.map +1 -1
- package/lib/{sort-by.d.ts → dates.d.ts} +1 -1
- package/lib/{sort-by.js → dates.js} +2 -2
- package/lib/dates.js.map +1 -0
- package/lib/index.d.ts +2 -2
- package/lib/index.js +2 -2
- package/lib/index.js.map +1 -1
- package/lib/{SeamProvider.d.ts → seam/SeamProvider.d.ts} +9 -6
- package/lib/{SeamProvider.js → seam/SeamProvider.js} +29 -30
- package/lib/seam/SeamProvider.js.map +1 -0
- package/lib/seam/access-codes/use-access-codes.js +2 -2
- package/lib/seam/access-codes/use-access-codes.js.map +1 -1
- package/lib/{ui → seam/components}/AccessCodeDetails/AccessCodeDetails.d.ts +2 -1
- package/lib/{ui → seam/components}/AccessCodeDetails/AccessCodeDetails.js +9 -8
- package/lib/seam/components/AccessCodeDetails/AccessCodeDetails.js.map +1 -0
- package/lib/{ui → seam/components}/AccessCodeDetails/AccessCodeDevice.js +7 -7
- package/lib/seam/components/AccessCodeDetails/AccessCodeDevice.js.map +1 -0
- package/lib/seam/components/AccessCodeTable/AccessCodeTable.d.ts +7 -0
- package/lib/seam/components/AccessCodeTable/AccessCodeTable.js +77 -0
- package/lib/seam/components/AccessCodeTable/AccessCodeTable.js.map +1 -0
- package/lib/{ui → seam/components}/AccessCodeTable/CodeDetails.js +3 -3
- package/lib/seam/components/AccessCodeTable/CodeDetails.js.map +1 -0
- package/lib/seam/components/DeviceDetails/DeviceDetails.d.ts +7 -0
- package/lib/seam/components/DeviceDetails/DeviceDetails.js +80 -0
- package/lib/seam/components/DeviceDetails/DeviceDetails.js.map +1 -0
- package/lib/seam/components/DeviceDetails/DeviceModel.js.map +1 -0
- package/lib/{ui → seam/components}/DeviceTable/DeviceHealthBar.d.ts +3 -2
- package/lib/{ui → seam/components}/DeviceTable/DeviceHealthBar.js +4 -4
- package/lib/seam/components/DeviceTable/DeviceHealthBar.js.map +1 -0
- package/lib/{ui → seam/components}/DeviceTable/DeviceRow.d.ts +1 -1
- package/lib/{ui → seam/components}/DeviceTable/DeviceRow.js +9 -9
- package/lib/seam/components/DeviceTable/DeviceRow.js.map +1 -0
- package/lib/seam/components/DeviceTable/DeviceTable.d.ts +9 -0
- package/lib/seam/components/DeviceTable/DeviceTable.js +66 -0
- package/lib/seam/components/DeviceTable/DeviceTable.js.map +1 -0
- package/lib/seam/components/SupportedDeviceTable/FilterCategoryMenu.d.ts +20 -0
- package/lib/{ui → seam/components}/SupportedDeviceTable/FilterCategoryMenu.js +8 -5
- package/lib/seam/components/SupportedDeviceTable/FilterCategoryMenu.js.map +1 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceContent.d.ts +9 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceContent.js +39 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceContent.js.map +1 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceFilterArea.d.ts +9 -0
- package/lib/{ui → seam/components}/SupportedDeviceTable/SupportedDeviceFilterArea.js +33 -28
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceFilterArea.js.map +1 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceHeader.d.ts +2 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceHeader.js +12 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceHeader.js.map +1 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceRow.d.ts +6 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceRow.js +19 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceRow.js.map +1 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceTable.d.ts +6 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceTable.js +17 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceTable.js.map +1 -0
- package/lib/seam/components/SupportedDeviceTable/use-filtered-device-models.d.ts +7 -0
- package/lib/seam/components/SupportedDeviceTable/use-filtered-device-models.js +18 -0
- package/lib/seam/components/SupportedDeviceTable/use-filtered-device-models.js.map +1 -0
- package/lib/seam/components/index.js.map +1 -0
- package/lib/seam/device-models/use-device-models.d.ts +5 -0
- package/lib/seam/device-models/use-device-models.js +17 -0
- package/lib/seam/device-models/use-device-models.js.map +1 -0
- package/lib/seam/devices/use-devices.js +3 -3
- package/lib/seam/devices/use-devices.js.map +1 -1
- package/lib/seam/devices/use-toggle-lock.js +1 -1
- package/lib/seam/devices/use-toggle-lock.js.map +1 -1
- package/lib/seam/index.d.ts +1 -0
- package/lib/seam/index.js +1 -0
- package/lib/seam/index.js.map +1 -1
- package/lib/seam/use-seam-client.js +1 -1
- package/lib/seam/use-seam-client.js.map +1 -1
- package/lib/seam/use-seam-font.d.ts +1 -1
- package/lib/seam/use-seam-font.js +1 -1
- package/lib/seam/use-seam-font.js.map +1 -1
- package/lib/seam/use-seam-styles.js.map +1 -1
- package/lib/{capitalize.js → strings.js} +1 -1
- package/lib/strings.js.map +1 -0
- package/lib/ui/Menu/Menu.d.ts +1 -1
- package/lib/ui/Menu/Menu.js.map +1 -1
- package/lib/ui/Menu/MenuItem.d.ts +1 -1
- package/lib/ui/Menu/MoreActionsMenu.d.ts +1 -1
- package/lib/ui/Table/TableFilterBar/TableFilterBar.d.ts +2 -1
- package/lib/ui/Table/TableFilterBar/TableFilterItem.d.ts +2 -1
- package/lib/ui/TextField/SearchTextField.js.map +1 -1
- package/lib/{copy-to-clipboard.js → ui/clipboard.js} +1 -1
- package/lib/ui/clipboard.js.map +1 -0
- package/lib/ui/use-interval.js.map +1 -0
- package/lib/{use-is-date-in-past.js → ui/use-is-date-in-past.js} +1 -1
- package/lib/ui/use-is-date-in-past.js.map +1 -0
- package/lib/ui/use-toggle.js.map +1 -0
- package/lib/version.d.ts +2 -2
- package/lib/version.js +3 -1
- package/lib/version.js.map +1 -1
- package/package.json +21 -8
- package/src/elements.ts +27 -0
- package/src/hooks.ts +1 -0
- package/src/lib/{sort-by.ts → dates.ts} +1 -1
- package/src/lib/element.tsx +86 -0
- package/src/lib/index.ts +2 -2
- package/src/lib/{SeamProvider.tsx → seam/SeamProvider.tsx} +53 -46
- package/src/lib/seam/access-codes/use-access-codes.ts +2 -2
- package/src/lib/seam/components/AccessCodeDetails/AccessCodeDetails.element.ts +12 -0
- package/src/lib/{ui → seam/components}/AccessCodeDetails/AccessCodeDetails.tsx +9 -6
- package/src/lib/{ui → seam/components}/AccessCodeDetails/AccessCodeDevice.tsx +2 -2
- package/src/lib/seam/components/AccessCodeTable/AccessCodeTable.element.ts +12 -0
- package/src/lib/{ui → seam/components}/AccessCodeTable/AccessCodeTable.tsx +30 -11
- package/src/lib/{ui → seam/components}/AccessCodeTable/CodeDetails.tsx +2 -3
- package/src/lib/seam/components/DeviceDetails/DeviceDetails.element.ts +12 -0
- package/src/lib/{ui → seam/components}/DeviceDetails/DeviceDetails.tsx +22 -12
- package/src/lib/{ui → seam/components}/DeviceTable/DeviceHealthBar.tsx +1 -1
- package/src/lib/{ui → seam/components}/DeviceTable/DeviceRow.tsx +1 -1
- package/src/lib/seam/components/DeviceTable/DeviceTable.element.ts +11 -0
- package/src/lib/{ui → seam/components}/DeviceTable/DeviceTable.tsx +15 -12
- package/src/lib/{ui → seam/components}/SupportedDeviceTable/FilterCategoryMenu.tsx +26 -13
- package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceContent.tsx +120 -0
- package/src/lib/{ui → seam/components}/SupportedDeviceTable/SupportedDeviceFilterArea.tsx +43 -39
- package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceHeader.tsx +22 -0
- package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceRow.tsx +48 -0
- package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceTable.element.ts +11 -0
- package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceTable.tsx +48 -0
- package/src/lib/seam/components/SupportedDeviceTable/use-filtered-device-models.ts +35 -0
- package/src/lib/seam/components/elements.ts +5 -0
- package/src/lib/seam/device-models/use-device-models.ts +34 -0
- package/src/lib/seam/devices/use-devices.ts +3 -3
- package/src/lib/seam/devices/use-toggle-lock.ts +1 -2
- package/src/lib/seam/index.ts +1 -0
- package/src/lib/seam/use-seam-client.ts +1 -1
- package/src/lib/seam/use-seam-font.ts +5 -1
- package/src/lib/seam/use-seam-styles.ts +1 -1
- package/src/lib/ui/Menu/Menu.tsx +4 -4
- package/src/lib/ui/Menu/MenuItem.tsx +1 -1
- package/src/lib/ui/Menu/MoreActionsMenu.tsx +1 -1
- package/src/lib/ui/Table/TableFilterBar/TableFilterBar.tsx +2 -2
- package/src/lib/ui/Table/TableFilterBar/TableFilterItem.tsx +1 -1
- package/src/lib/ui/TextField/SearchTextField.tsx +3 -3
- package/src/lib/ui/clipboard.ts +3 -0
- package/src/lib/{use-interval.ts → ui/use-interval.ts} +1 -1
- package/src/lib/{use-is-date-in-past.ts → ui/use-is-date-in-past.ts} +1 -1
- package/src/lib/version.ts +3 -1
- package/src/styles/_access-code-table.scss +7 -0
- package/lib/SeamProvider.js.map +0 -1
- package/lib/capitalize.js.map +0 -1
- package/lib/copy-to-clipboard.js.map +0 -1
- package/lib/sort-by.js.map +0 -1
- package/lib/ui/AccessCodeDetails/AccessCodeDetails.js.map +0 -1
- package/lib/ui/AccessCodeDetails/AccessCodeDevice.js.map +0 -1
- package/lib/ui/AccessCodeTable/AccessCodeTable.d.ts +0 -6
- package/lib/ui/AccessCodeTable/AccessCodeTable.js +0 -69
- package/lib/ui/AccessCodeTable/AccessCodeTable.js.map +0 -1
- package/lib/ui/AccessCodeTable/CodeDetails.js.map +0 -1
- package/lib/ui/DeviceDetails/DeviceDetails.d.ts +0 -6
- package/lib/ui/DeviceDetails/DeviceDetails.js +0 -80
- package/lib/ui/DeviceDetails/DeviceDetails.js.map +0 -1
- package/lib/ui/DeviceDetails/DeviceModel.js.map +0 -1
- package/lib/ui/DeviceTable/DeviceHealthBar.js.map +0 -1
- package/lib/ui/DeviceTable/DeviceRow.js.map +0 -1
- package/lib/ui/DeviceTable/DeviceTable.d.ts +0 -8
- package/lib/ui/DeviceTable/DeviceTable.js +0 -65
- package/lib/ui/DeviceTable/DeviceTable.js.map +0 -1
- package/lib/ui/SupportedDeviceTable/FilterCategoryMenu.d.ts +0 -15
- package/lib/ui/SupportedDeviceTable/FilterCategoryMenu.js.map +0 -1
- package/lib/ui/SupportedDeviceTable/SupportedDeviceContent.d.ts +0 -4
- package/lib/ui/SupportedDeviceTable/SupportedDeviceContent.js +0 -46
- package/lib/ui/SupportedDeviceTable/SupportedDeviceContent.js.map +0 -1
- package/lib/ui/SupportedDeviceTable/SupportedDeviceFilterArea.d.ts +0 -11
- package/lib/ui/SupportedDeviceTable/SupportedDeviceFilterArea.js.map +0 -1
- package/lib/ui/SupportedDeviceTable/SupportedDeviceHeader.d.ts +0 -1
- package/lib/ui/SupportedDeviceTable/SupportedDeviceHeader.js +0 -5
- package/lib/ui/SupportedDeviceTable/SupportedDeviceHeader.js.map +0 -1
- package/lib/ui/SupportedDeviceTable/SupportedDeviceRow.d.ts +0 -5
- package/lib/ui/SupportedDeviceTable/SupportedDeviceRow.js +0 -12
- package/lib/ui/SupportedDeviceTable/SupportedDeviceRow.js.map +0 -1
- package/lib/ui/SupportedDeviceTable/SupportedDeviceTable.d.ts +0 -3
- package/lib/ui/SupportedDeviceTable/SupportedDeviceTable.js +0 -8
- package/lib/ui/SupportedDeviceTable/SupportedDeviceTable.js.map +0 -1
- package/lib/ui/SupportedDeviceTable/types.d.ts +0 -15
- package/lib/ui/SupportedDeviceTable/types.js +0 -2
- package/lib/ui/SupportedDeviceTable/types.js.map +0 -1
- package/lib/ui/index.js.map +0 -1
- package/lib/use-interval.js.map +0 -1
- package/lib/use-is-date-in-past.js.map +0 -1
- package/lib/use-toggle.js.map +0 -1
- package/src/lib/copy-to-clipboard.ts +0 -3
- package/src/lib/ui/SupportedDeviceTable/SupportedDeviceContent.tsx +0 -135
- package/src/lib/ui/SupportedDeviceTable/SupportedDeviceHeader.tsx +0 -14
- package/src/lib/ui/SupportedDeviceTable/SupportedDeviceRow.tsx +0 -35
- package/src/lib/ui/SupportedDeviceTable/SupportedDeviceTable.tsx +0 -16
- package/src/lib/ui/SupportedDeviceTable/types.ts +0 -16
- /package/lib/{ui → seam/components}/AccessCodeDetails/AccessCodeDevice.d.ts +0 -0
- /package/lib/{ui → seam/components}/AccessCodeTable/CodeDetails.d.ts +0 -0
- /package/lib/{ui → seam/components}/DeviceDetails/DeviceModel.d.ts +0 -0
- /package/lib/{ui → seam/components}/DeviceDetails/DeviceModel.js +0 -0
- /package/lib/{ui → seam/components}/index.d.ts +0 -0
- /package/lib/{ui → seam/components}/index.js +0 -0
- /package/lib/{capitalize.d.ts → strings.d.ts} +0 -0
- /package/lib/{copy-to-clipboard.d.ts → ui/clipboard.d.ts} +0 -0
- /package/lib/{use-interval.d.ts → ui/use-interval.d.ts} +0 -0
- /package/lib/{use-interval.js → ui/use-interval.js} +0 -0
- /package/lib/{use-is-date-in-past.d.ts → ui/use-is-date-in-past.d.ts} +0 -0
- /package/lib/{use-toggle.d.ts → ui/use-toggle.d.ts} +0 -0
- /package/lib/{use-toggle.js → ui/use-toggle.js} +0 -0
- /package/src/lib/{ui → seam/components}/DeviceDetails/DeviceModel.tsx +0 -0
- /package/src/lib/{ui → seam/components}/index.ts +0 -0
- /package/src/lib/{capitalize.ts → strings.ts} +0 -0
- /package/src/lib/{use-toggle.ts → ui/use-toggle.ts} +0 -0
|
@@ -2,6 +2,24 @@ import { ChevronDownIcon } from 'lib/icons/ChevronDown.js'
|
|
|
2
2
|
import { Menu } from 'lib/ui/Menu/Menu.js'
|
|
3
3
|
import { MenuItem } from 'lib/ui/Menu/MenuItem.js'
|
|
4
4
|
|
|
5
|
+
export type FilterCategoryMenuProps =
|
|
6
|
+
| FilterCategoryMenuPropsWithAllOption
|
|
7
|
+
| FilterCategoryMenuPropsWithoutAllOption
|
|
8
|
+
|
|
9
|
+
interface FilterCategoryMenuPropsWithAllOption
|
|
10
|
+
extends FilterCategoryMenuBaseProps {
|
|
11
|
+
hideAllOption?: false
|
|
12
|
+
allLabel: string
|
|
13
|
+
onAllOptionSelect: () => void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface FilterCategoryMenuPropsWithoutAllOption
|
|
17
|
+
extends FilterCategoryMenuBaseProps {
|
|
18
|
+
hideAllOption: true
|
|
19
|
+
allLabel: never
|
|
20
|
+
onAllOptionSelect?: never
|
|
21
|
+
}
|
|
22
|
+
|
|
5
23
|
interface FilterCategoryMenuBaseProps {
|
|
6
24
|
label: string
|
|
7
25
|
options: string[]
|
|
@@ -9,24 +27,15 @@ interface FilterCategoryMenuBaseProps {
|
|
|
9
27
|
buttonLabel?: string
|
|
10
28
|
}
|
|
11
29
|
|
|
12
|
-
export type FilterCategoryMenuProps =
|
|
13
|
-
| (FilterCategoryMenuBaseProps & {
|
|
14
|
-
hideAllOption?: false
|
|
15
|
-
onAllOptionSelect: () => void
|
|
16
|
-
})
|
|
17
|
-
| (FilterCategoryMenuBaseProps & {
|
|
18
|
-
hideAllOption: true
|
|
19
|
-
onAllOptionSelect?: never
|
|
20
|
-
})
|
|
21
|
-
|
|
22
30
|
export function FilterCategoryMenu({
|
|
23
|
-
label =
|
|
31
|
+
label = t.filter,
|
|
32
|
+
allLabel,
|
|
24
33
|
options,
|
|
25
34
|
hideAllOption = false,
|
|
26
35
|
onSelect,
|
|
27
36
|
onAllOptionSelect,
|
|
28
37
|
buttonLabel,
|
|
29
|
-
}: FilterCategoryMenuProps) {
|
|
38
|
+
}: FilterCategoryMenuProps): JSX.Element {
|
|
30
39
|
const usableOptions = hideAllOption ? options : ['All', ...options]
|
|
31
40
|
|
|
32
41
|
return (
|
|
@@ -44,7 +53,7 @@ export function FilterCategoryMenu({
|
|
|
44
53
|
<MenuItem
|
|
45
54
|
key={`${index}:${option}`}
|
|
46
55
|
onClick={() => {
|
|
47
|
-
if (option ===
|
|
56
|
+
if (option === allLabel) {
|
|
48
57
|
onAllOptionSelect?.()
|
|
49
58
|
} else {
|
|
50
59
|
onSelect(option)
|
|
@@ -58,3 +67,7 @@ export function FilterCategoryMenu({
|
|
|
58
67
|
</div>
|
|
59
68
|
)
|
|
60
69
|
}
|
|
70
|
+
|
|
71
|
+
const t = {
|
|
72
|
+
filter: 'Filter',
|
|
73
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { SupportedDeviceHeader } from 'lib/seam/components/SupportedDeviceTable/SupportedDeviceHeader.js'
|
|
2
|
+
import { SupportedDeviceRow } from 'lib/seam/components/SupportedDeviceTable/SupportedDeviceRow.js'
|
|
3
|
+
import {
|
|
4
|
+
type DeviceModelFilters,
|
|
5
|
+
useFilteredDeviceModels,
|
|
6
|
+
} from 'lib/seam/components/SupportedDeviceTable/use-filtered-device-models.js'
|
|
7
|
+
import { Button } from 'lib/ui/Button.js'
|
|
8
|
+
|
|
9
|
+
interface SupportedDeviceContentProps {
|
|
10
|
+
filterValue: string
|
|
11
|
+
resetFilterValue: () => void
|
|
12
|
+
filters: DeviceModelFilters
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function SupportedDeviceContent({
|
|
16
|
+
resetFilterValue,
|
|
17
|
+
filterValue,
|
|
18
|
+
filters,
|
|
19
|
+
}: SupportedDeviceContentProps): JSX.Element | null {
|
|
20
|
+
const { deviceModels, isLoading, isError, refetch } = useFilteredDeviceModels(
|
|
21
|
+
filterValue,
|
|
22
|
+
filters
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
if (isLoading) {
|
|
26
|
+
return (
|
|
27
|
+
<div className='seam-supported-device-table-content-state-block'>
|
|
28
|
+
<p>{t.loading}</p>
|
|
29
|
+
</div>
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (isError) {
|
|
34
|
+
return (
|
|
35
|
+
<div className='seam-supported-device-table-content-state-block'>
|
|
36
|
+
<p>{t.error}</p>
|
|
37
|
+
<Button
|
|
38
|
+
variant='solid'
|
|
39
|
+
size='small'
|
|
40
|
+
onClick={() => {
|
|
41
|
+
void refetch()
|
|
42
|
+
}}
|
|
43
|
+
>
|
|
44
|
+
{t.retry}
|
|
45
|
+
</Button>
|
|
46
|
+
</div>
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (deviceModels == null) {
|
|
51
|
+
return null
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<table className='seam-supported-device-table-content'>
|
|
56
|
+
<SupportedDeviceHeader />
|
|
57
|
+
<tbody>
|
|
58
|
+
{deviceModels.map((deviceModel, index) => (
|
|
59
|
+
<SupportedDeviceRow
|
|
60
|
+
key={[
|
|
61
|
+
deviceModel.main_category,
|
|
62
|
+
deviceModel.brand,
|
|
63
|
+
deviceModel.model_name,
|
|
64
|
+
deviceModel.manufacturer_model_id,
|
|
65
|
+
index,
|
|
66
|
+
].join(':')}
|
|
67
|
+
deviceModel={deviceModel}
|
|
68
|
+
/>
|
|
69
|
+
))}
|
|
70
|
+
{deviceModels.length === 0 && (
|
|
71
|
+
<EmptyResult
|
|
72
|
+
filterValue={filterValue}
|
|
73
|
+
resetFilterValue={resetFilterValue}
|
|
74
|
+
/>
|
|
75
|
+
)}
|
|
76
|
+
</tbody>
|
|
77
|
+
</table>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function EmptyResult({
|
|
82
|
+
filterValue,
|
|
83
|
+
resetFilterValue,
|
|
84
|
+
}: Pick<
|
|
85
|
+
SupportedDeviceContentProps,
|
|
86
|
+
'filterValue' | 'resetFilterValue'
|
|
87
|
+
>): JSX.Element {
|
|
88
|
+
const noMatchingRows = (
|
|
89
|
+
<>
|
|
90
|
+
<p>{t.noMatch}</p>
|
|
91
|
+
<Button
|
|
92
|
+
variant='outline'
|
|
93
|
+
size='small'
|
|
94
|
+
onClick={resetFilterValue}
|
|
95
|
+
className='seam-supported-device-table-content-message-clear-search'
|
|
96
|
+
>
|
|
97
|
+
{t.clear}
|
|
98
|
+
</Button>
|
|
99
|
+
</>
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<tr className='seam-supported-device-table-content-message-row'>
|
|
104
|
+
<td colSpan={6}>
|
|
105
|
+
<div className='seam-supported-device-table-content-message'>
|
|
106
|
+
{filterValue.length === 0 ? <p>{t.noneFound}</p> : noMatchingRows}
|
|
107
|
+
</div>
|
|
108
|
+
</td>
|
|
109
|
+
</tr>
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const t = {
|
|
114
|
+
loading: 'Loading device models...',
|
|
115
|
+
retry: 'Retry',
|
|
116
|
+
error: 'There was an error fetching device models.',
|
|
117
|
+
noneFound: 'No device models found.',
|
|
118
|
+
noMatch: 'No device models matched your search.',
|
|
119
|
+
clear: 'Clear search terms',
|
|
120
|
+
}
|
|
@@ -1,58 +1,45 @@
|
|
|
1
1
|
import type { Dispatch, SetStateAction } from 'react'
|
|
2
|
+
import type { DeviceModel } from 'seamapi'
|
|
2
3
|
|
|
3
|
-
import {
|
|
4
|
+
import { FilterCategoryMenu } from 'lib/seam/components/SupportedDeviceTable/FilterCategoryMenu.js'
|
|
5
|
+
import type { DeviceModelFilters } from 'lib/seam/components/SupportedDeviceTable/use-filtered-device-models.js'
|
|
6
|
+
import { useDeviceModels } from 'lib/seam/device-models/use-device-models.js'
|
|
7
|
+
import { capitalize } from 'lib/strings.js'
|
|
4
8
|
import { Button } from 'lib/ui/Button.js'
|
|
5
9
|
import { Menu } from 'lib/ui/Menu/Menu.js'
|
|
6
|
-
import { FilterCategoryMenu } from 'lib/ui/SupportedDeviceTable/FilterCategoryMenu.js'
|
|
7
|
-
import type { DeviceModel, Filters } from 'lib/ui/SupportedDeviceTable/types.js'
|
|
8
10
|
import { SearchTextField } from 'lib/ui/TextField/SearchTextField.js'
|
|
9
11
|
|
|
10
|
-
interface SupportedDeviceFilterAreaProps {
|
|
11
|
-
deviceModels: DeviceModel[]
|
|
12
|
+
export interface SupportedDeviceFilterAreaProps {
|
|
12
13
|
filterValue: string
|
|
13
14
|
setFilterValue: (filter: string) => void
|
|
14
|
-
filters:
|
|
15
|
-
setFilters: Dispatch<SetStateAction<
|
|
15
|
+
filters: DeviceModelFilters
|
|
16
|
+
setFilters: Dispatch<SetStateAction<DeviceModelFilters>>
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export function SupportedDeviceFilterArea({
|
|
19
|
-
deviceModels,
|
|
20
20
|
filterValue,
|
|
21
21
|
setFilterValue,
|
|
22
22
|
filters,
|
|
23
23
|
setFilters,
|
|
24
|
-
}: SupportedDeviceFilterAreaProps) {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
filterProperty !== undefined &&
|
|
29
|
-
filterProperty !== null &&
|
|
30
|
-
filterProperty !== false
|
|
31
|
-
)
|
|
32
|
-
})
|
|
33
|
-
const appliedFiltersCount = appliedFilters.length
|
|
24
|
+
}: SupportedDeviceFilterAreaProps): JSX.Element {
|
|
25
|
+
const appliedFiltersCount = Object.values(filters).filter(
|
|
26
|
+
(v) => v != null && v !== false
|
|
27
|
+
).length
|
|
34
28
|
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
) => {
|
|
38
|
-
const properties = new Set<string>()
|
|
39
|
-
deviceModels.forEach((deviceModel) => {
|
|
40
|
-
properties.add(capitalize(deviceModel[property]))
|
|
41
|
-
})
|
|
42
|
-
return Array.from(properties)
|
|
43
|
-
}
|
|
29
|
+
const filterProperty = 'brand'
|
|
30
|
+
const availableProperties = useAvailableProperties(filterProperty)
|
|
44
31
|
|
|
45
|
-
const resetFilter = (filterType: keyof
|
|
32
|
+
const resetFilter = (filterType: keyof DeviceModelFilters): void => {
|
|
46
33
|
setFilters((filters) => ({
|
|
47
34
|
...filters,
|
|
48
35
|
[filterType]: null,
|
|
49
36
|
}))
|
|
50
37
|
}
|
|
51
38
|
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
39
|
+
const filterButtonLabel =
|
|
40
|
+
appliedFiltersCount > 0 ? `${t.filters} (${appliedFiltersCount})` : t.filter
|
|
41
|
+
|
|
42
|
+
const allLabel = t.all
|
|
56
43
|
|
|
57
44
|
return (
|
|
58
45
|
<div className='seam-supported-device-table-filter-area'>
|
|
@@ -77,27 +64,27 @@ export function SupportedDeviceFilterArea({
|
|
|
77
64
|
>
|
|
78
65
|
<div className='seam-filter-menu-row'>
|
|
79
66
|
<FilterCategoryMenu
|
|
80
|
-
label=
|
|
81
|
-
|
|
67
|
+
label={t.brand}
|
|
68
|
+
allLabel={allLabel}
|
|
69
|
+
options={availableProperties}
|
|
82
70
|
onSelect={(brand: string) => {
|
|
83
71
|
setFilters((filters) => ({
|
|
84
72
|
...filters,
|
|
85
73
|
brand,
|
|
86
74
|
}))
|
|
87
75
|
}}
|
|
88
|
-
buttonLabel={filters.brand ??
|
|
76
|
+
buttonLabel={filters.brand ?? allLabel}
|
|
89
77
|
onAllOptionSelect={() => {
|
|
90
|
-
resetFilter(
|
|
78
|
+
resetFilter(filterProperty)
|
|
91
79
|
}}
|
|
92
80
|
/>
|
|
93
81
|
</div>
|
|
94
|
-
|
|
95
82
|
<div className='seam-filter-menu-row'>
|
|
96
83
|
<label
|
|
97
84
|
htmlFor='supportedOnly'
|
|
98
85
|
className='seam-filter-checkbox-label'
|
|
99
86
|
>
|
|
100
|
-
<p>
|
|
87
|
+
<p>{t.supported}</p>
|
|
101
88
|
<input
|
|
102
89
|
id='supportedOnly'
|
|
103
90
|
name='supportedOnly'
|
|
@@ -115,7 +102,6 @@ export function SupportedDeviceFilterArea({
|
|
|
115
102
|
</div>
|
|
116
103
|
</div>
|
|
117
104
|
</Menu>
|
|
118
|
-
|
|
119
105
|
<div className='seam-supported-device-table-filter-area-search-bar-wrap'>
|
|
120
106
|
<SearchTextField
|
|
121
107
|
value={filterValue}
|
|
@@ -129,3 +115,21 @@ export function SupportedDeviceFilterArea({
|
|
|
129
115
|
</div>
|
|
130
116
|
)
|
|
131
117
|
}
|
|
118
|
+
|
|
119
|
+
const useAvailableProperties = (property: keyof DeviceModel): string[] => {
|
|
120
|
+
const { deviceModels } = useDeviceModels()
|
|
121
|
+
if (deviceModels == null) return []
|
|
122
|
+
const properties = new Set<string>()
|
|
123
|
+
for (const deviceModel of deviceModels) {
|
|
124
|
+
properties.add(capitalize(deviceModel[property]))
|
|
125
|
+
}
|
|
126
|
+
return Array.from(properties)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const t = {
|
|
130
|
+
all: 'All',
|
|
131
|
+
brand: 'Brand',
|
|
132
|
+
supported: 'Supported',
|
|
133
|
+
filter: 'Filter',
|
|
134
|
+
filters: 'Filters',
|
|
135
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function SupportedDeviceHeader(): JSX.Element {
|
|
2
|
+
return (
|
|
3
|
+
<thead>
|
|
4
|
+
<tr>
|
|
5
|
+
<th />
|
|
6
|
+
<th>{t.category}</th>
|
|
7
|
+
<th>{t.modelName}</th>
|
|
8
|
+
<th>{t.manufacturerModelId}</th>
|
|
9
|
+
<th>{t.connectionType}</th>
|
|
10
|
+
<th>{t.status}</th>
|
|
11
|
+
</tr>
|
|
12
|
+
</thead>
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const t = {
|
|
17
|
+
category: 'Category',
|
|
18
|
+
modelName: 'Model Name',
|
|
19
|
+
manufacturerModelId: 'Manufacturer Model ID',
|
|
20
|
+
connectionType: 'Connection Type',
|
|
21
|
+
status: 'Status',
|
|
22
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import classNames from 'classnames'
|
|
2
|
+
import type { DeviceModel } from 'seamapi'
|
|
3
|
+
|
|
4
|
+
import { capitalize } from 'lib/strings.js'
|
|
5
|
+
|
|
6
|
+
export interface SupportedDeviceRowProps {
|
|
7
|
+
deviceModel: DeviceModel
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function SupportedDeviceRow({
|
|
11
|
+
deviceModel,
|
|
12
|
+
}: SupportedDeviceRowProps): JSX.Element {
|
|
13
|
+
const statusColor = supportLevelColors[deviceModel.support_level] ?? 'gray'
|
|
14
|
+
return (
|
|
15
|
+
<tr>
|
|
16
|
+
<td>
|
|
17
|
+
<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>
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const supportLevelColors: Record<
|
|
35
|
+
DeviceModel['support_level'],
|
|
36
|
+
'green' | 'blue' | 'orange'
|
|
37
|
+
> = {
|
|
38
|
+
live: 'green',
|
|
39
|
+
beta: 'blue',
|
|
40
|
+
unsupported: 'orange',
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const connectionTypeNames: Record<DeviceModel['connection_type'], string> = {
|
|
44
|
+
wifi: 'Wifi',
|
|
45
|
+
zwave: 'Z-Wave',
|
|
46
|
+
zigbee: 'Zigbee',
|
|
47
|
+
unknown: 'Unknown',
|
|
48
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ElementProps } from 'lib/element.js'
|
|
2
|
+
|
|
3
|
+
import type { SupportedDeviceTableProps } from './SupportedDeviceTable.js'
|
|
4
|
+
|
|
5
|
+
export const name = 'seam-supported-device-table'
|
|
6
|
+
|
|
7
|
+
export const props: ElementProps<SupportedDeviceTableProps> = {
|
|
8
|
+
cannotFilter: 'boolean',
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { SupportedDeviceTable as Component } from './SupportedDeviceTable.js'
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import classNames from 'classnames'
|
|
2
|
+
import { useState } from 'react'
|
|
3
|
+
|
|
4
|
+
import { SupportedDeviceContent } from 'lib/seam/components/SupportedDeviceTable/SupportedDeviceContent.js'
|
|
5
|
+
import { SupportedDeviceFilterArea } from 'lib/seam/components/SupportedDeviceTable/SupportedDeviceFilterArea.js'
|
|
6
|
+
import type { DeviceModelFilters } from 'lib/seam/components/SupportedDeviceTable/use-filtered-device-models.js'
|
|
7
|
+
|
|
8
|
+
export interface SupportedDeviceTableProps {
|
|
9
|
+
cannotFilter?: boolean
|
|
10
|
+
className?: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function SupportedDeviceTable({
|
|
14
|
+
cannotFilter = false,
|
|
15
|
+
className,
|
|
16
|
+
}: SupportedDeviceTableProps): JSX.Element {
|
|
17
|
+
const [filterValue, setFilterValue] = useState('')
|
|
18
|
+
const [filters, setFilters] = useState<DeviceModelFilters>({
|
|
19
|
+
supportedOnly: false,
|
|
20
|
+
category: null,
|
|
21
|
+
brand: null,
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div
|
|
26
|
+
className={classNames(
|
|
27
|
+
'seam-supported-device-table-content-wrap',
|
|
28
|
+
className
|
|
29
|
+
)}
|
|
30
|
+
>
|
|
31
|
+
{!cannotFilter && (
|
|
32
|
+
<SupportedDeviceFilterArea
|
|
33
|
+
filterValue={filterValue}
|
|
34
|
+
setFilterValue={setFilterValue}
|
|
35
|
+
filters={filters}
|
|
36
|
+
setFilters={setFilters}
|
|
37
|
+
/>
|
|
38
|
+
)}
|
|
39
|
+
<SupportedDeviceContent
|
|
40
|
+
resetFilterValue={() => {
|
|
41
|
+
setFilterValue('')
|
|
42
|
+
}}
|
|
43
|
+
filterValue={filterValue}
|
|
44
|
+
filters={filters}
|
|
45
|
+
/>
|
|
46
|
+
</div>
|
|
47
|
+
)
|
|
48
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useDeviceModels,
|
|
3
|
+
type UseDeviceModelsParams,
|
|
4
|
+
} from 'lib/seam/device-models/use-device-models.js'
|
|
5
|
+
|
|
6
|
+
export interface DeviceModelFilters {
|
|
7
|
+
supportedOnly: boolean
|
|
8
|
+
category: string | null
|
|
9
|
+
brand: string | null
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const useFilteredDeviceModels = (
|
|
13
|
+
filterValue: string,
|
|
14
|
+
filters: DeviceModelFilters
|
|
15
|
+
): ReturnType<typeof useDeviceModels> => {
|
|
16
|
+
const params: UseDeviceModelsParams = {}
|
|
17
|
+
|
|
18
|
+
if (filterValue.trim() !== '') {
|
|
19
|
+
params.text_search = filterValue.trim()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (filters.supportedOnly) {
|
|
23
|
+
params.support_level = 'live'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (filters.category !== null) {
|
|
27
|
+
params.main_category = filters.category
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (filters.brand !== null) {
|
|
31
|
+
params.brand = filters.brand
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return useDeviceModels(params)
|
|
35
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export * as AccessCodeDetails from './AccessCodeDetails/AccessCodeDetails.element.js'
|
|
2
|
+
export * as AccessCodeTable from './AccessCodeTable/AccessCodeTable.element.js'
|
|
3
|
+
export * as DeviceDetails from './DeviceDetails/DeviceDetails.element.js'
|
|
4
|
+
export * as DeviceTable from './DeviceTable/DeviceTable.element.js'
|
|
5
|
+
export * as SupportedDeviceTable from './SupportedDeviceTable/SupportedDeviceTable.element.js'
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { useQuery } from '@tanstack/react-query'
|
|
2
|
+
import type {
|
|
3
|
+
DeviceModel,
|
|
4
|
+
DeviceModelsListRequest,
|
|
5
|
+
DeviceModelsListResponse,
|
|
6
|
+
SeamError,
|
|
7
|
+
} from 'seamapi'
|
|
8
|
+
|
|
9
|
+
import { useSeamClient } from 'lib/seam/use-seam-client.js'
|
|
10
|
+
import type { UseSeamQueryResult } from 'lib/seam/use-seam-query-result.js'
|
|
11
|
+
|
|
12
|
+
export type UseDeviceModelsParams = DeviceModelsListRequest
|
|
13
|
+
export type UseDeviceModelsData = DeviceModel[]
|
|
14
|
+
|
|
15
|
+
export function useDeviceModels(
|
|
16
|
+
params?: UseDeviceModelsParams
|
|
17
|
+
): UseSeamQueryResult<'deviceModels', UseDeviceModelsData> {
|
|
18
|
+
const { client } = useSeamClient()
|
|
19
|
+
|
|
20
|
+
const { data, ...rest } = useQuery<
|
|
21
|
+
DeviceModelsListResponse['device_models'],
|
|
22
|
+
SeamError
|
|
23
|
+
>({
|
|
24
|
+
enabled: client != null,
|
|
25
|
+
queryKey: ['device_models', 'list', params],
|
|
26
|
+
queryFn: async () => {
|
|
27
|
+
if (client == null) return []
|
|
28
|
+
const deviceModels = await client?.deviceModels.list(params)
|
|
29
|
+
return deviceModels
|
|
30
|
+
},
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
return { ...rest, deviceModels: data }
|
|
34
|
+
}
|
|
@@ -7,9 +7,9 @@ import type {
|
|
|
7
7
|
SeamError,
|
|
8
8
|
} from 'seamapi'
|
|
9
9
|
|
|
10
|
+
import { compareByCreatedAtDesc } from 'lib/dates.js'
|
|
10
11
|
import { useSeamClient } from 'lib/seam/use-seam-client.js'
|
|
11
12
|
import type { UseSeamQueryResult } from 'lib/seam/use-seam-query-result.js'
|
|
12
|
-
import { byCreatedAt } from 'lib/sort-by.js'
|
|
13
13
|
|
|
14
14
|
export type UseDevicesParams = DevicesListRequest
|
|
15
15
|
export type UseDevicesData = Array<Device<CommonDeviceProperties>>
|
|
@@ -27,9 +27,9 @@ export function useDevices(
|
|
|
27
27
|
queryFn: async () => {
|
|
28
28
|
if (client == null) return []
|
|
29
29
|
const devices = await client?.devices.list(params)
|
|
30
|
-
return devices.sort(
|
|
30
|
+
return devices.sort(compareByCreatedAtDesc)
|
|
31
31
|
},
|
|
32
|
-
onSuccess(devices) {
|
|
32
|
+
onSuccess: (devices) => {
|
|
33
33
|
// Prime cache for each device.
|
|
34
34
|
for (const device of devices) {
|
|
35
35
|
queryClient.setQueryData(
|
|
@@ -11,9 +11,8 @@ import type {
|
|
|
11
11
|
SeamError,
|
|
12
12
|
} from 'seamapi'
|
|
13
13
|
|
|
14
|
-
import { useSeamClient } from 'lib/index.js'
|
|
15
|
-
|
|
16
14
|
import { isLockDevice } from 'lib/seam/devices/types.js'
|
|
15
|
+
import { useSeamClient } from 'lib/seam/use-seam-client.js'
|
|
17
16
|
|
|
18
17
|
export function useToggleLock({
|
|
19
18
|
device_id: deviceId,
|
package/src/lib/seam/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './access-codes/use-access-code.js'
|
|
2
2
|
export * from './access-codes/use-access-codes.js'
|
|
3
|
+
export * from './device-models/use-device-models.js'
|
|
3
4
|
export * from './devices/use-device.js'
|
|
4
5
|
export * from './devices/use-devices.js'
|
|
5
6
|
export * from './use-seam-client.js'
|
|
@@ -3,7 +3,7 @@ import { useEffect } from 'react'
|
|
|
3
3
|
import { Seam } from 'seamapi'
|
|
4
4
|
import { v4 as uuidv4 } from 'uuid'
|
|
5
5
|
|
|
6
|
-
import { useSeamContext } from 'lib/SeamProvider.js'
|
|
6
|
+
import { useSeamContext } from 'lib/seam/SeamProvider.js'
|
|
7
7
|
|
|
8
8
|
export function useSeamClient(): {
|
|
9
9
|
client: Seam | null
|
|
@@ -3,7 +3,11 @@ import { useEffect } from 'react'
|
|
|
3
3
|
const fontUrl =
|
|
4
4
|
'https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600;700&display=swap'
|
|
5
5
|
|
|
6
|
-
export const useSeamFont = ({
|
|
6
|
+
export const useSeamFont = ({
|
|
7
|
+
disabled = false,
|
|
8
|
+
}: {
|
|
9
|
+
disabled?: boolean
|
|
10
|
+
}): void => {
|
|
7
11
|
useEffect(() => {
|
|
8
12
|
if (disabled) return
|
|
9
13
|
if (globalThis.document == null) return
|
package/src/lib/ui/Menu/Menu.tsx
CHANGED
|
@@ -38,7 +38,7 @@ export function Menu({
|
|
|
38
38
|
children,
|
|
39
39
|
renderButton,
|
|
40
40
|
backgroundProps,
|
|
41
|
-
}: PropsWithChildren<MenuProps>) {
|
|
41
|
+
}: PropsWithChildren<MenuProps>): JSX.Element | null {
|
|
42
42
|
const { Provider } = menuContext
|
|
43
43
|
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null)
|
|
44
44
|
const [documentEl, setDocumentEl] = useState<null | Element>(null)
|
|
@@ -56,11 +56,11 @@ export function Menu({
|
|
|
56
56
|
}
|
|
57
57
|
}, [setDocumentEl])
|
|
58
58
|
|
|
59
|
-
const handleClose = () => {
|
|
59
|
+
const handleClose = (): void => {
|
|
60
60
|
setAnchorEl(null)
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
const handleOpen = (event: MouseEvent<HTMLElement>) => {
|
|
63
|
+
const handleOpen = (event: MouseEvent<HTMLElement>): void => {
|
|
64
64
|
setAnchorEl(event.currentTarget)
|
|
65
65
|
}
|
|
66
66
|
|
|
@@ -171,7 +171,7 @@ export function Menu({
|
|
|
171
171
|
)
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
-
export function useMenu() {
|
|
174
|
+
export function useMenu(): MenuContextValue {
|
|
175
175
|
const context = useContext(menuContext)
|
|
176
176
|
if (context == null) {
|
|
177
177
|
throw new Error('useMenu must be used within a Menu.')
|
|
@@ -11,7 +11,7 @@ interface MoreActionsMenuProps {
|
|
|
11
11
|
export function MoreActionsMenu({
|
|
12
12
|
children,
|
|
13
13
|
menuProps,
|
|
14
|
-
}: PropsWithChildren<MoreActionsMenuProps>) {
|
|
14
|
+
}: PropsWithChildren<MoreActionsMenuProps>): JSX.Element {
|
|
15
15
|
return (
|
|
16
16
|
<Menu
|
|
17
17
|
renderButton={({ onOpen }) => (
|