@seamapi/react 4.14.2 → 5.1.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 +111 -3
- package/dist/ecosystem.js +45 -0
- package/dist/ecosystem.js.map +1 -0
- package/dist/elements.js +11464 -11007
- package/dist/elements.js.map +1 -1
- package/dist/index.css +469 -345
- package/dist/index.css.map +1 -1
- package/dist/index.min.css +1 -1
- package/dist/index.min.css.map +1 -1
- package/lib/seam/SeamProvider.d.ts +10 -3
- package/lib/seam/SeamProvider.js +5 -3
- package/lib/seam/SeamProvider.js.map +1 -1
- package/lib/seam/components/CompatibleApps/CompatibleApps.d.ts +26 -0
- package/lib/seam/components/CompatibleApps/CompatibleApps.js +126 -0
- package/lib/seam/components/CompatibleApps/CompatibleApps.js.map +1 -0
- package/lib/seam/components/SupportedDevices/DeviceModelRow.d.ts +8 -0
- package/lib/seam/components/SupportedDevices/DeviceModelRow.js +31 -0
- package/lib/seam/components/SupportedDevices/DeviceModelRow.js.map +1 -0
- package/lib/seam/components/SupportedDevices/FilterSelect.d.ts +12 -0
- package/lib/seam/components/SupportedDevices/FilterSelect.js +9 -0
- package/lib/seam/components/SupportedDevices/FilterSelect.js.map +1 -0
- package/lib/seam/components/SupportedDevices/ManufacturerSection.d.ts +10 -0
- package/lib/seam/components/SupportedDevices/ManufacturerSection.js +35 -0
- package/lib/seam/components/SupportedDevices/ManufacturerSection.js.map +1 -0
- package/lib/seam/components/SupportedDevices/SupportedDevices.d.ts +24 -0
- package/lib/seam/components/SupportedDevices/SupportedDevices.js +151 -0
- package/lib/seam/components/SupportedDevices/SupportedDevices.js.map +1 -0
- package/lib/seam/components/SupportedDevices/device-models.d.ts +47 -0
- package/lib/seam/components/SupportedDevices/device-models.js +217 -0
- package/lib/seam/components/SupportedDevices/device-models.js.map +1 -0
- package/lib/seam/components/index.d.ts +2 -2
- package/lib/seam/components/index.js +2 -2
- package/lib/seam/components/index.js.map +1 -1
- package/lib/seam/ecosystem/EcosystemProvider.d.ts +37 -0
- package/lib/seam/ecosystem/EcosystemProvider.js +56 -0
- package/lib/seam/ecosystem/EcosystemProvider.js.map +1 -0
- package/lib/seam/ecosystem/client.d.ts +28 -0
- package/lib/seam/ecosystem/client.js +74 -0
- package/lib/seam/ecosystem/client.js.map +1 -0
- package/lib/seam/ecosystem/index.d.ts +9 -0
- package/lib/seam/ecosystem/index.js +8 -0
- package/lib/seam/ecosystem/index.js.map +1 -0
- package/lib/seam/ecosystem/types.d.ts +253 -0
- package/lib/seam/ecosystem/types.js +10 -0
- package/lib/seam/ecosystem/types.js.map +1 -0
- package/lib/seam/ecosystem/use-compatible-partners.d.ts +21 -0
- package/lib/seam/ecosystem/use-compatible-partners.js +36 -0
- package/lib/seam/ecosystem/use-compatible-partners.js.map +1 -0
- package/lib/seam/ecosystem/use-ecosystem-device-models.d.ts +20 -0
- package/lib/seam/ecosystem/use-ecosystem-device-models.js +51 -0
- package/lib/seam/ecosystem/use-ecosystem-device-models.js.map +1 -0
- package/lib/seam/ecosystem/use-ecosystem-manufacturers.d.ts +11 -0
- package/lib/seam/ecosystem/use-ecosystem-manufacturers.js +49 -0
- package/lib/seam/ecosystem/use-ecosystem-manufacturers.js.map +1 -0
- package/lib/seam/ecosystem/use-ecosystem-query-result.d.ts +7 -0
- package/lib/seam/ecosystem/use-ecosystem-query-result.js +7 -0
- package/lib/seam/ecosystem/use-ecosystem-query-result.js.map +1 -0
- package/lib/seam/ecosystem/use-embed-key-resolution.d.ts +20 -0
- package/lib/seam/ecosystem/use-embed-key-resolution.js +51 -0
- package/lib/seam/ecosystem/use-embed-key-resolution.js.map +1 -0
- 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/seam-components-class-name.d.ts +1 -0
- package/lib/seam/seam-components-class-name.js +2 -0
- package/lib/seam/seam-components-class-name.js.map +1 -0
- package/lib/ui/ecosystem/SearchField.d.ts +9 -0
- package/lib/ui/ecosystem/SearchField.js +8 -0
- package/lib/ui/ecosystem/SearchField.js.map +1 -0
- package/lib/ui/ecosystem/StateMessage.d.ts +8 -0
- package/lib/ui/ecosystem/StateMessage.js +5 -0
- package/lib/ui/ecosystem/StateMessage.js.map +1 -0
- package/lib/ui/ecosystem/errors.d.ts +5 -0
- package/lib/ui/ecosystem/errors.js +25 -0
- package/lib/ui/ecosystem/errors.js.map +1 -0
- package/lib/ui/ecosystem/storybook.d.ts +15 -0
- package/lib/ui/ecosystem/storybook.js +16 -0
- package/lib/ui/ecosystem/storybook.js.map +1 -0
- package/lib/ui/ecosystem/theme.d.ts +6 -0
- package/lib/ui/ecosystem/theme.js +11 -0
- package/lib/ui/ecosystem/theme.js.map +1 -0
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/lib/version.js.map +1 -1
- package/package.json +11 -3
- package/src/ecosystem.d.ts +2 -0
- package/src/ecosystem.ts +12 -0
- package/src/elements.ts +4 -0
- package/src/lib/ecosystem-element.tsx +154 -0
- package/src/lib/element.tsx +6 -0
- package/src/lib/seam/SeamProvider.tsx +18 -2
- package/src/lib/seam/components/CompatibleApps/CompatibleApps.element.ts +19 -0
- package/src/lib/seam/components/CompatibleApps/CompatibleApps.tsx +344 -0
- package/src/lib/seam/components/SupportedDevices/DeviceModelRow.tsx +105 -0
- package/src/lib/seam/components/SupportedDevices/FilterSelect.tsx +43 -0
- package/src/lib/seam/components/SupportedDevices/ManufacturerSection.tsx +114 -0
- package/src/lib/seam/components/SupportedDevices/SupportedDevices.element.ts +17 -0
- package/src/lib/seam/components/SupportedDevices/SupportedDevices.tsx +382 -0
- package/src/lib/seam/components/SupportedDevices/device-models.ts +326 -0
- package/src/lib/seam/components/ecosystem-elements.ts +2 -0
- package/src/lib/seam/components/elements.ts +0 -2
- package/src/lib/seam/components/index.ts +2 -2
- package/src/lib/seam/ecosystem/EcosystemProvider.tsx +133 -0
- package/src/lib/seam/ecosystem/client.ts +116 -0
- package/src/lib/seam/ecosystem/index.ts +19 -0
- package/src/lib/seam/ecosystem/types.ts +334 -0
- package/src/lib/seam/ecosystem/use-compatible-partners.ts +80 -0
- package/src/lib/seam/ecosystem/use-ecosystem-device-models.ts +96 -0
- package/src/lib/seam/ecosystem/use-ecosystem-manufacturers.ts +86 -0
- package/src/lib/seam/ecosystem/use-ecosystem-query-result.ts +19 -0
- package/src/lib/seam/ecosystem/use-embed-key-resolution.ts +80 -0
- package/src/lib/seam/index.ts +1 -0
- package/src/lib/seam/seam-components-class-name.ts +1 -0
- package/src/lib/ui/ecosystem/SearchField.tsx +32 -0
- package/src/lib/ui/ecosystem/StateMessage.tsx +29 -0
- package/src/lib/ui/ecosystem/errors.ts +30 -0
- package/src/lib/ui/ecosystem/storybook.tsx +40 -0
- package/src/lib/ui/ecosystem/theme.ts +14 -0
- package/src/lib/version.ts +1 -1
- package/src/styles/_compatible-apps.scss +102 -0
- package/src/styles/_ecosystem.scss +295 -0
- package/src/styles/_main.scss +6 -4
- package/src/styles/_supported-devices.scss +153 -0
- package/lib/seam/components/SupportedDeviceTable/FilterCategoryMenu.d.ts +0 -20
- package/lib/seam/components/SupportedDeviceTable/FilterCategoryMenu.js +0 -22
- package/lib/seam/components/SupportedDeviceTable/FilterCategoryMenu.js.map +0 -1
- package/lib/seam/components/SupportedDeviceTable/HiddenDevicesOverlay.d.ts +0 -6
- package/lib/seam/components/SupportedDeviceTable/HiddenDevicesOverlay.js +0 -8
- package/lib/seam/components/SupportedDeviceTable/HiddenDevicesOverlay.js.map +0 -1
- package/lib/seam/components/SupportedDeviceTable/ShowAllDevicesButton.d.ts +0 -9
- package/lib/seam/components/SupportedDeviceTable/ShowAllDevicesButton.js +0 -14
- package/lib/seam/components/SupportedDeviceTable/ShowAllDevicesButton.js.map +0 -1
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceContent.d.ts +0 -13
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceContent.js +0 -58
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceContent.js.map +0 -1
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceContentRows.d.ts +0 -7
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceContentRows.js +0 -6
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceContentRows.js.map +0 -1
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceFilterArea.d.ts +0 -12
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceFilterArea.js +0 -58
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceFilterArea.js.map +0 -1
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceManufacturerSection.d.ts +0 -8
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceManufacturerSection.js +0 -39
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceManufacturerSection.js.map +0 -1
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceRow.d.ts +0 -10
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceRow.js +0 -35
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceRow.js.map +0 -1
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceTable.d.ts +0 -11
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceTable.js +0 -20
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceTable.js.map +0 -1
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceTableManufacturerKeys.d.ts +0 -6
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceTableManufacturerKeys.js +0 -21
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceTableManufacturerKeys.js.map +0 -1
- package/lib/seam/components/SupportedDeviceTable/use-device-model.d.ts +0 -7
- package/lib/seam/components/SupportedDeviceTable/use-device-model.js +0 -21
- package/lib/seam/components/SupportedDeviceTable/use-device-model.js.map +0 -1
- package/lib/seam/components/SupportedDeviceTable/use-device-models.d.ts +0 -7
- package/lib/seam/components/SupportedDeviceTable/use-device-models.js +0 -30
- package/lib/seam/components/SupportedDeviceTable/use-device-models.js.map +0 -1
- package/lib/seam/components/SupportedDeviceTable/use-filtered-device-models.d.ts +0 -15
- package/lib/seam/components/SupportedDeviceTable/use-filtered-device-models.js +0 -45
- package/lib/seam/components/SupportedDeviceTable/use-filtered-device-models.js.map +0 -1
- package/lib/seam/components/SupportedDeviceTable/use-filtered-manufacturers.d.ts +0 -10
- package/lib/seam/components/SupportedDeviceTable/use-filtered-manufacturers.js +0 -42
- package/lib/seam/components/SupportedDeviceTable/use-filtered-manufacturers.js.map +0 -1
- package/lib/seam/components/SupportedDeviceTable/use-manufacturer.d.ts +0 -7
- package/lib/seam/components/SupportedDeviceTable/use-manufacturer.js +0 -17
- package/lib/seam/components/SupportedDeviceTable/use-manufacturer.js.map +0 -1
- package/lib/seam/components/SupportedDeviceTable/use-manufacturers.d.ts +0 -7
- package/lib/seam/components/SupportedDeviceTable/use-manufacturers.js +0 -26
- package/lib/seam/components/SupportedDeviceTable/use-manufacturers.js.map +0 -1
- package/src/lib/seam/components/SupportedDeviceTable/FilterCategoryMenu.tsx +0 -78
- package/src/lib/seam/components/SupportedDeviceTable/HiddenDevicesOverlay.tsx +0 -13
- package/src/lib/seam/components/SupportedDeviceTable/ShowAllDevicesButton.tsx +0 -32
- package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceContent.tsx +0 -161
- package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceContentRows.tsx +0 -22
- package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceFilterArea.tsx +0 -145
- package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceManufacturerSection.tsx +0 -109
- package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceRow.tsx +0 -93
- package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceTable.element.ts +0 -15
- package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceTable.tsx +0 -70
- package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceTableManufacturerKeys.element.ts +0 -9
- package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceTableManufacturerKeys.tsx +0 -64
- package/src/lib/seam/components/SupportedDeviceTable/use-device-model.ts +0 -44
- package/src/lib/seam/components/SupportedDeviceTable/use-device-models.ts +0 -57
- package/src/lib/seam/components/SupportedDeviceTable/use-filtered-device-models.ts +0 -88
- package/src/lib/seam/components/SupportedDeviceTable/use-filtered-manufacturers.ts +0 -69
- package/src/lib/seam/components/SupportedDeviceTable/use-manufacturer.ts +0 -40
- package/src/lib/seam/components/SupportedDeviceTable/use-manufacturers.ts +0 -53
- package/src/styles/_supported-device-table-manufacturer-keys.scss +0 -20
- package/src/styles/_supported-device-table.scss +0 -412
|
@@ -5,5 +5,3 @@ export * as CreateAccessCodeForm from './CreateAccessCodeForm/CreateAccessCodeFo
|
|
|
5
5
|
export * as DeviceDetails from './DeviceDetails/DeviceDetails.element.js'
|
|
6
6
|
export * as DeviceTable from './DeviceTable/DeviceTable.element.js'
|
|
7
7
|
export * as EditAccessCodeForm from './EditAccessCodeForm/EditAccessCodeForm.element.js'
|
|
8
|
-
export * as SupportedDeviceTable from './SupportedDeviceTable/SupportedDeviceTable.element.js'
|
|
9
|
-
export * as SupportedDeviceTableManufacturerKeys from './SupportedDeviceTable/SupportedDeviceTableManufacturerKeys.element.js'
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export * from './AccessCodeDetails/AccessCodeDetails.js'
|
|
2
2
|
export * from './AccessCodeTable/AccessCodeTable.js'
|
|
3
3
|
export * from './common-props.js'
|
|
4
|
+
export * from './CompatibleApps/CompatibleApps.js'
|
|
4
5
|
export * from './ConnectAccountButton/ConnectAccountButton.js'
|
|
5
6
|
export * from './CreateAccessCodeForm/CreateAccessCodeForm.js'
|
|
6
7
|
export * from './DeviceDetails/DeviceDetails.js'
|
|
7
8
|
export * from './DeviceTable/DeviceTable.js'
|
|
8
9
|
export * from './EditAccessCodeForm/EditAccessCodeForm.js'
|
|
9
|
-
export * from './
|
|
10
|
-
export * from './SupportedDeviceTable/SupportedDeviceTableManufacturerKeys.js'
|
|
10
|
+
export * from './SupportedDevices/SupportedDevices.js'
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import {
|
|
2
|
+
QueryClient,
|
|
3
|
+
QueryClientContext,
|
|
4
|
+
QueryClientProvider,
|
|
5
|
+
} from '@tanstack/react-query'
|
|
6
|
+
import {
|
|
7
|
+
createContext,
|
|
8
|
+
type PropsWithChildren,
|
|
9
|
+
useContext,
|
|
10
|
+
useMemo,
|
|
11
|
+
} from 'react'
|
|
12
|
+
|
|
13
|
+
import { defaultEcosystemEndpoint } from 'lib/seam/ecosystem/client.js'
|
|
14
|
+
import { seamComponentsClassName } from 'lib/seam/seam-components-class-name.js'
|
|
15
|
+
import { useSeamFont } from 'lib/seam/use-seam-font.js'
|
|
16
|
+
import { useSeamStyles } from 'lib/seam/use-seam-styles.js'
|
|
17
|
+
|
|
18
|
+
export interface EcosystemContext {
|
|
19
|
+
/** The embed key sent as `X-Embed-Key`, if any. */
|
|
20
|
+
embedKey: string | undefined
|
|
21
|
+
/** The Ecosystem API endpoint, ending in `/`. */
|
|
22
|
+
endpoint: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface EcosystemOptions {
|
|
26
|
+
/**
|
|
27
|
+
* Seam Ecosystem embed key (`eco_live_…`).
|
|
28
|
+
* Required outside seam.co: the key's allowed origins must include the page origin.
|
|
29
|
+
*/
|
|
30
|
+
embedKey?: string | undefined
|
|
31
|
+
/** Seam Ecosystem API endpoint. Defaults to `https://ecosystem.seam.co/v1/`. */
|
|
32
|
+
ecosystemEndpoint?: string | undefined
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface EcosystemProviderProps
|
|
36
|
+
extends EcosystemOptions,
|
|
37
|
+
PropsWithChildren {
|
|
38
|
+
queryClient?: QueryClient | undefined
|
|
39
|
+
disableCssInjection?: boolean | undefined
|
|
40
|
+
disableFontInjection?: boolean | undefined
|
|
41
|
+
unminifiyCss?: boolean | undefined
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const defaultQueryClient = new QueryClient()
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Provides the Seam Ecosystem context for `CompatibleApps` and `SupportedDevices`.
|
|
48
|
+
*
|
|
49
|
+
* Unlike `SeamProvider`, this does not need a Seam publishable key
|
|
50
|
+
* and does not load the Seam API client, so it stays lightweight.
|
|
51
|
+
* Inside a `SeamProvider`, pass `embedKey` to the `SeamProvider` instead.
|
|
52
|
+
*/
|
|
53
|
+
export function EcosystemProvider({
|
|
54
|
+
children,
|
|
55
|
+
queryClient,
|
|
56
|
+
disableCssInjection = false,
|
|
57
|
+
disableFontInjection = false,
|
|
58
|
+
unminifiyCss = false,
|
|
59
|
+
...options
|
|
60
|
+
}: EcosystemProviderProps): JSX.Element {
|
|
61
|
+
useSeamStyles({ disabled: disableCssInjection, unminified: unminifiyCss })
|
|
62
|
+
useSeamFont({ disabled: disableFontInjection })
|
|
63
|
+
|
|
64
|
+
const queryClientFromContext = useContext(QueryClientContext)
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<div className={seamComponentsClassName}>
|
|
68
|
+
<QueryClientProvider
|
|
69
|
+
client={
|
|
70
|
+
queryClient ??
|
|
71
|
+
queryClientFromContext ??
|
|
72
|
+
globalThis.seamQueryClient ??
|
|
73
|
+
defaultQueryClient
|
|
74
|
+
}
|
|
75
|
+
>
|
|
76
|
+
<EcosystemContextProvider {...options}>
|
|
77
|
+
{children}
|
|
78
|
+
</EcosystemContextProvider>
|
|
79
|
+
</QueryClientProvider>
|
|
80
|
+
</div>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Provides only the Ecosystem context; used by `SeamProvider`.
|
|
86
|
+
* Unset options inherit from an enclosing provider.
|
|
87
|
+
*/
|
|
88
|
+
export function EcosystemContextProvider({
|
|
89
|
+
children,
|
|
90
|
+
embedKey,
|
|
91
|
+
ecosystemEndpoint,
|
|
92
|
+
}: EcosystemOptions & PropsWithChildren): JSX.Element {
|
|
93
|
+
const parent = useContext(ecosystemContext)
|
|
94
|
+
|
|
95
|
+
const value = useMemo(
|
|
96
|
+
() => ({
|
|
97
|
+
embedKey: normalizeEmbedKey(embedKey) ?? parent.embedKey,
|
|
98
|
+
endpoint: normalizeEndpoint(ecosystemEndpoint) ?? parent.endpoint,
|
|
99
|
+
}),
|
|
100
|
+
[embedKey, ecosystemEndpoint, parent]
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<ecosystemContext.Provider value={value}>
|
|
105
|
+
{children}
|
|
106
|
+
</ecosystemContext.Provider>
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function useEcosystemContext(): EcosystemContext {
|
|
111
|
+
return useContext(ecosystemContext)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const normalizeEmbedKey = (
|
|
115
|
+
embedKey: string | undefined
|
|
116
|
+
): string | undefined => {
|
|
117
|
+
const key = embedKey?.trim()
|
|
118
|
+
if (key == null || key.length === 0) return undefined
|
|
119
|
+
return key
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const normalizeEndpoint = (
|
|
123
|
+
endpoint: string | undefined
|
|
124
|
+
): string | undefined => {
|
|
125
|
+
const value = endpoint?.trim()
|
|
126
|
+
if (value == null || value.length === 0) return undefined
|
|
127
|
+
return value.endsWith('/') ? value : `${value}/`
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const ecosystemContext = createContext<EcosystemContext>({
|
|
131
|
+
embedKey: undefined,
|
|
132
|
+
endpoint: defaultEcosystemEndpoint,
|
|
133
|
+
})
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { EcosystemErrorResponse } from './types.js'
|
|
2
|
+
|
|
3
|
+
export const defaultEcosystemEndpoint = 'https://ecosystem.seam.co/v1/'
|
|
4
|
+
|
|
5
|
+
export type EcosystemQueryParams = Record<
|
|
6
|
+
string,
|
|
7
|
+
string | number | boolean | string[] | null | undefined
|
|
8
|
+
>
|
|
9
|
+
|
|
10
|
+
export interface EcosystemRequestOptions {
|
|
11
|
+
endpoint: string
|
|
12
|
+
embedKey?: string | undefined
|
|
13
|
+
params?: EcosystemQueryParams
|
|
14
|
+
signal?: AbortSignal
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* An error response from the Ecosystem API.
|
|
19
|
+
* The `type` is the API error type, e.g., `embed_key_required`,
|
|
20
|
+
* `invalid_embed_key` or `origin_not_allowed`.
|
|
21
|
+
*/
|
|
22
|
+
export class EcosystemApiError extends Error {
|
|
23
|
+
readonly status: number
|
|
24
|
+
readonly type: string
|
|
25
|
+
readonly requestId: string | null
|
|
26
|
+
|
|
27
|
+
constructor({
|
|
28
|
+
status,
|
|
29
|
+
type,
|
|
30
|
+
message,
|
|
31
|
+
requestId = null,
|
|
32
|
+
}: {
|
|
33
|
+
status: number
|
|
34
|
+
type: string
|
|
35
|
+
message: string
|
|
36
|
+
requestId?: string | null
|
|
37
|
+
}) {
|
|
38
|
+
super(message)
|
|
39
|
+
this.name = 'EcosystemApiError'
|
|
40
|
+
this.status = status
|
|
41
|
+
this.type = type
|
|
42
|
+
this.requestId = requestId
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** True when the error means the embed key is missing, invalid or not allowed here. */
|
|
47
|
+
export const isEmbedKeyError = (error: unknown): boolean =>
|
|
48
|
+
error instanceof EcosystemApiError &&
|
|
49
|
+
(error.status === 401 || error.status === 403)
|
|
50
|
+
|
|
51
|
+
export const getEcosystemUrl = (
|
|
52
|
+
endpoint: string,
|
|
53
|
+
path: string,
|
|
54
|
+
params: EcosystemQueryParams = {}
|
|
55
|
+
): URL => {
|
|
56
|
+
const base = endpoint.endsWith('/') ? endpoint : `${endpoint}/`
|
|
57
|
+
const url = new URL(path, new URL(base, globalThis.location?.href))
|
|
58
|
+
for (const [key, value] of Object.entries(params)) {
|
|
59
|
+
if (value == null) continue
|
|
60
|
+
if (Array.isArray(value)) {
|
|
61
|
+
if (value.length === 0) continue
|
|
62
|
+
url.searchParams.set(key, value.join(','))
|
|
63
|
+
continue
|
|
64
|
+
}
|
|
65
|
+
if (typeof value === 'string' && value.length === 0) continue
|
|
66
|
+
url.searchParams.set(key, String(value))
|
|
67
|
+
}
|
|
68
|
+
return url
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const fetchEcosystem = async <T>(
|
|
72
|
+
path: string,
|
|
73
|
+
{ endpoint, embedKey, params, signal }: EcosystemRequestOptions
|
|
74
|
+
): Promise<T> => {
|
|
75
|
+
const url = getEcosystemUrl(endpoint, path, params)
|
|
76
|
+
|
|
77
|
+
const headers: Record<string, string> = { Accept: 'application/json' }
|
|
78
|
+
if (embedKey != null && embedKey.length > 0) {
|
|
79
|
+
headers['X-Embed-Key'] = embedKey
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const res = await globalThis.fetch(url, {
|
|
83
|
+
headers,
|
|
84
|
+
...(signal == null ? {} : { signal }),
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
const body = (await res.json().catch(() => null)) as unknown
|
|
88
|
+
|
|
89
|
+
if (!res.ok) {
|
|
90
|
+
const error = isErrorResponse(body) ? body.error : null
|
|
91
|
+
throw new EcosystemApiError({
|
|
92
|
+
status: res.status,
|
|
93
|
+
type: error?.type ?? 'unknown_error',
|
|
94
|
+
message:
|
|
95
|
+
error?.message ?? `Ecosystem request failed with status ${res.status}`,
|
|
96
|
+
requestId: error?.request_id ?? null,
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (body == null || typeof body !== 'object') {
|
|
101
|
+
throw new EcosystemApiError({
|
|
102
|
+
status: res.status,
|
|
103
|
+
type: 'invalid_response',
|
|
104
|
+
message: 'Ecosystem returned an invalid response',
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return body as T
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const isErrorResponse = (body: unknown): body is EcosystemErrorResponse =>
|
|
112
|
+
body != null &&
|
|
113
|
+
typeof body === 'object' &&
|
|
114
|
+
'error' in body &&
|
|
115
|
+
body.error != null &&
|
|
116
|
+
typeof body.error === 'object'
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export {
|
|
2
|
+
defaultEcosystemEndpoint,
|
|
3
|
+
EcosystemApiError,
|
|
4
|
+
isEmbedKeyError,
|
|
5
|
+
} from './client.js'
|
|
6
|
+
export {
|
|
7
|
+
type EcosystemContext,
|
|
8
|
+
type EcosystemOptions,
|
|
9
|
+
EcosystemProvider,
|
|
10
|
+
type EcosystemProviderProps,
|
|
11
|
+
useEcosystemContext,
|
|
12
|
+
} from './EcosystemProvider.js'
|
|
13
|
+
export * from './types.js'
|
|
14
|
+
export * from './use-compatible-partners.js'
|
|
15
|
+
export * from './use-ecosystem-device-models.js'
|
|
16
|
+
export * from './use-ecosystem-manufacturers.js'
|
|
17
|
+
export type { UseEcosystemQueryResult } from './use-ecosystem-query-result.js'
|
|
18
|
+
export * from './use-embed-key-resolution.js'
|
|
19
|
+
export type { EcosystemTheme } from 'lib/ui/ecosystem/theme.js'
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response types for the public Seam Ecosystem API (PartnerDB and DeviceDB).
|
|
3
|
+
*
|
|
4
|
+
* Hand-copied from the zod schemas in `seamapi/ecosystem` `public-types/`
|
|
5
|
+
* (origin/main 733edf3, 2026-10-16) to avoid a zod runtime dependency.
|
|
6
|
+
* Fields stored verbatim from the source as JSON are typed as `unknown`.
|
|
7
|
+
* Keep in sync with Ecosystem until it publishes its types as a package.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// Partners (PartnerDB)
|
|
11
|
+
|
|
12
|
+
export interface EcosystemIndustry {
|
|
13
|
+
industry_id: string
|
|
14
|
+
slug: string
|
|
15
|
+
display_name: string
|
|
16
|
+
short_name: string | null
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface EcosystemSolution {
|
|
20
|
+
solution_id: string
|
|
21
|
+
slug: string
|
|
22
|
+
display_name: string
|
|
23
|
+
short_name: string | null
|
|
24
|
+
type: 'software' | 'service'
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type PartnerAssetKind =
|
|
28
|
+
| 'square_logo'
|
|
29
|
+
| 'square_logo_mono'
|
|
30
|
+
| 'horizontal_logo'
|
|
31
|
+
| 'horizontal_logo_mono'
|
|
32
|
+
| 'product_image'
|
|
33
|
+
|
|
34
|
+
export interface PartnerAsset {
|
|
35
|
+
partner_asset_id: string
|
|
36
|
+
kind: PartnerAssetKind
|
|
37
|
+
url: string
|
|
38
|
+
mime: string
|
|
39
|
+
width: number | null
|
|
40
|
+
height: number | null
|
|
41
|
+
sort_order: number
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface Partner {
|
|
45
|
+
partner_id: string
|
|
46
|
+
slug: string
|
|
47
|
+
display_name: string
|
|
48
|
+
website: string | null
|
|
49
|
+
description_md: string | null
|
|
50
|
+
is_live: boolean
|
|
51
|
+
is_featured: boolean
|
|
52
|
+
legacy_industry_featured: boolean
|
|
53
|
+
industries: EcosystemIndustry[]
|
|
54
|
+
solutions: EcosystemSolution[]
|
|
55
|
+
assets: PartnerAsset[]
|
|
56
|
+
created_at: string
|
|
57
|
+
updated_at: string
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type SupportLevel =
|
|
61
|
+
| 'device_category'
|
|
62
|
+
| 'manufacturer'
|
|
63
|
+
| 'provider'
|
|
64
|
+
| 'capability'
|
|
65
|
+
|
|
66
|
+
export type ObservedStatus = 'active' | 'trace' | 'none' | 'unknown'
|
|
67
|
+
|
|
68
|
+
export type DeclaredStatus = 'enabled' | 'disabled' | 'not_via_seam'
|
|
69
|
+
|
|
70
|
+
export interface SupportResolution {
|
|
71
|
+
supported: boolean
|
|
72
|
+
resolved_level: SupportLevel | null
|
|
73
|
+
declared_status: DeclaredStatus | null
|
|
74
|
+
observed_status: ObservedStatus | null
|
|
75
|
+
note: string | null
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface CompatiblePartner extends Partner {
|
|
79
|
+
support: SupportResolution
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Embed keys
|
|
83
|
+
|
|
84
|
+
export type EmbedKeyOwnerKind = 'partner' | 'manufacturer' | 'seam'
|
|
85
|
+
|
|
86
|
+
/** The public record of an embed key, as returned by `embed/resolve`. */
|
|
87
|
+
export interface EmbedKey {
|
|
88
|
+
embed_key_id: string
|
|
89
|
+
display_name: string
|
|
90
|
+
owner_kind: EmbedKeyOwnerKind
|
|
91
|
+
partner_id: string | null
|
|
92
|
+
manufacturer_slug: string | null
|
|
93
|
+
allowed_origins: string[]
|
|
94
|
+
config: Record<string, unknown>
|
|
95
|
+
revoked_at: string | null
|
|
96
|
+
created_at: string
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface EmbedCapabilityExclusion {
|
|
100
|
+
device_category: string
|
|
101
|
+
/** Empty means every manufacturer in the category. */
|
|
102
|
+
manufacturer_slug: string
|
|
103
|
+
/** Empty means every provider in the category. */
|
|
104
|
+
provider_slug: string
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface EmbedExclusions {
|
|
108
|
+
excluded_manufacturers: string[]
|
|
109
|
+
excluded_device_types: string[]
|
|
110
|
+
unsupported_providers: string[]
|
|
111
|
+
capability: string
|
|
112
|
+
capability_exclusions: EmbedCapabilityExclusion[]
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Manufacturer context for manufacturer-owned keys.
|
|
117
|
+
* Not returned by Ecosystem yet (DEVDB-439); read when present.
|
|
118
|
+
*/
|
|
119
|
+
export interface EmbedManufacturerContext {
|
|
120
|
+
manufacturer_slug: string
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface EmbedResolution {
|
|
124
|
+
embed_key: EmbedKey
|
|
125
|
+
exclusions: EmbedExclusions
|
|
126
|
+
manufacturer_context?: EmbedManufacturerContext | null
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Devices (DeviceDB)
|
|
130
|
+
|
|
131
|
+
export interface MediaFormat {
|
|
132
|
+
object_key: string
|
|
133
|
+
url: string
|
|
134
|
+
mime: string | null
|
|
135
|
+
width: number | null
|
|
136
|
+
height: number | null
|
|
137
|
+
bytes: number | null
|
|
138
|
+
sha256: string | null
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export type MediaFormatName = 'thumbnail' | 'small' | 'medium' | 'large'
|
|
142
|
+
|
|
143
|
+
export type DeviceAssetKind =
|
|
144
|
+
| 'square_logo'
|
|
145
|
+
| 'square_logo_mono'
|
|
146
|
+
| 'horizontal_logo'
|
|
147
|
+
| 'horizontal_logo_mono'
|
|
148
|
+
| 'default_device_image'
|
|
149
|
+
| 'featured'
|
|
150
|
+
| 'variant_image'
|
|
151
|
+
|
|
152
|
+
export interface DeviceAsset {
|
|
153
|
+
asset_id: string
|
|
154
|
+
kind: DeviceAssetKind
|
|
155
|
+
object_key: string
|
|
156
|
+
url: string
|
|
157
|
+
mime: string | null
|
|
158
|
+
width: number | null
|
|
159
|
+
height: number | null
|
|
160
|
+
bytes: number | null
|
|
161
|
+
sha256: string | null
|
|
162
|
+
sort_order: number
|
|
163
|
+
formats: Partial<Record<MediaFormatName, MediaFormat>>
|
|
164
|
+
created_at: string
|
|
165
|
+
updated_at: string
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export interface DeviceTypeRef {
|
|
169
|
+
device_type_id: string
|
|
170
|
+
slug: string
|
|
171
|
+
display_name: string
|
|
172
|
+
is_accessory: boolean
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export interface ManufacturerRef {
|
|
176
|
+
manufacturer_id: string
|
|
177
|
+
slug: string
|
|
178
|
+
display_name: string | null
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export interface ProviderRef {
|
|
182
|
+
provider_id: string
|
|
183
|
+
slug: string
|
|
184
|
+
display_name: string | null
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export type CapabilityName =
|
|
188
|
+
| 'device_connectivity'
|
|
189
|
+
| 'can_program_online_access_codes'
|
|
190
|
+
| 'can_program_offline_access_codes'
|
|
191
|
+
| 'can_remotely_unlock'
|
|
192
|
+
| 'can_remotely_lock'
|
|
193
|
+
| 'can_encode_plastic_cards'
|
|
194
|
+
| 'can_provision_mobile_keys'
|
|
195
|
+
| 'can_provision_wallet_keys'
|
|
196
|
+
| 'can_hvac_cool'
|
|
197
|
+
| 'can_hvac_heat'
|
|
198
|
+
| 'can_hvac_auto'
|
|
199
|
+
| 'can_hvac_fan'
|
|
200
|
+
| 'can_program_thermostat_weekly_programs'
|
|
201
|
+
| 'can_monitor'
|
|
202
|
+
|
|
203
|
+
export type CapabilitySupported = 'yes' | 'no' | 'conditionally'
|
|
204
|
+
|
|
205
|
+
export type IntegrationSupportLevel =
|
|
206
|
+
| 'inquire'
|
|
207
|
+
| 'unavailable'
|
|
208
|
+
| 'planned'
|
|
209
|
+
| 'in-progress'
|
|
210
|
+
| 'beta'
|
|
211
|
+
| 'stable'
|
|
212
|
+
|
|
213
|
+
export interface CapabilityReport {
|
|
214
|
+
details: string
|
|
215
|
+
requirements?: Record<
|
|
216
|
+
string,
|
|
217
|
+
{ message: string; device_slugs?: string[]; [key: string]: unknown }
|
|
218
|
+
>
|
|
219
|
+
dependencies?: string[]
|
|
220
|
+
[key: string]: unknown
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export interface CapabilityDetail {
|
|
224
|
+
capability_id: string
|
|
225
|
+
name: CapabilityName
|
|
226
|
+
supported: CapabilitySupported
|
|
227
|
+
integration_support_level: IntegrationSupportLevel | null
|
|
228
|
+
report: CapabilityReport | null
|
|
229
|
+
report_raw: CapabilityReport | null
|
|
230
|
+
locale: string
|
|
231
|
+
computed_at: string
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export interface ProviderCapabilities {
|
|
235
|
+
provider: ProviderRef
|
|
236
|
+
capabilities: CapabilityDetail[]
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export interface DeviceModelVariant {
|
|
240
|
+
device_model_variant_id: string
|
|
241
|
+
color_name: string | null
|
|
242
|
+
style_name: string | null
|
|
243
|
+
primary_color_hex: string | null
|
|
244
|
+
manufacturer_model_id: string | null
|
|
245
|
+
asin: string | null
|
|
246
|
+
gtins: unknown
|
|
247
|
+
marketplace_listings: unknown
|
|
248
|
+
sort_order: number
|
|
249
|
+
images: DeviceAsset[]
|
|
250
|
+
created_at: string
|
|
251
|
+
updated_at: string
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export interface DeviceModel {
|
|
255
|
+
device_model_id: string
|
|
256
|
+
slug: string
|
|
257
|
+
display_name: string | null
|
|
258
|
+
description_md: string | null
|
|
259
|
+
product_url: string | null
|
|
260
|
+
is_forbidden_to_3dparty: boolean | null
|
|
261
|
+
no_longer_sold: boolean | null
|
|
262
|
+
shop_listings: unknown
|
|
263
|
+
last_commerce_search_at: string | null
|
|
264
|
+
manufacturer: ManufacturerRef | null
|
|
265
|
+
device_type: DeviceTypeRef | null
|
|
266
|
+
device_type_properties: unknown
|
|
267
|
+
variants: DeviceModelVariant[]
|
|
268
|
+
featured_image: DeviceAsset | null
|
|
269
|
+
providers: ProviderRef[]
|
|
270
|
+
capabilities_by_provider: ProviderCapabilities[]
|
|
271
|
+
capabilities_stale: boolean
|
|
272
|
+
created_at: string
|
|
273
|
+
updated_at: string
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export interface ManufacturerDefaultDeviceImage {
|
|
277
|
+
device_type: DeviceTypeRef
|
|
278
|
+
asset: DeviceAsset
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export interface Manufacturer {
|
|
282
|
+
manufacturer_id: string
|
|
283
|
+
slug: string
|
|
284
|
+
display_name: string | null
|
|
285
|
+
website: string | null
|
|
286
|
+
headquarters: string | null
|
|
287
|
+
country_of_origin: string | null
|
|
288
|
+
parent_org: string | null
|
|
289
|
+
inc_date: string | null
|
|
290
|
+
customer_support_phone: string | null
|
|
291
|
+
customer_support_email: string | null
|
|
292
|
+
customer_support_url: string | null
|
|
293
|
+
description_md: string | null
|
|
294
|
+
seam_api_guide: string | null
|
|
295
|
+
commerce_footprint: unknown
|
|
296
|
+
last_commerce_search_at: string | null
|
|
297
|
+
logos: DeviceAsset[]
|
|
298
|
+
default_device_images: ManufacturerDefaultDeviceImage[]
|
|
299
|
+
providers: ProviderRef[]
|
|
300
|
+
device_model_count: number
|
|
301
|
+
created_at: string
|
|
302
|
+
updated_at: string
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export interface Pagination {
|
|
306
|
+
has_next_page: boolean
|
|
307
|
+
next_page_cursor: string | null
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Responses
|
|
311
|
+
|
|
312
|
+
export interface CompatibilityResponse {
|
|
313
|
+
partners: CompatiblePartner[]
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export interface DeviceModelsListResponse {
|
|
317
|
+
device_models: DeviceModel[]
|
|
318
|
+
pagination: Pagination
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export interface ManufacturersListResponse {
|
|
322
|
+
manufacturers: Manufacturer[]
|
|
323
|
+
pagination: Pagination
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export interface EcosystemErrorResponse {
|
|
327
|
+
ok: false
|
|
328
|
+
error: {
|
|
329
|
+
type: string
|
|
330
|
+
message: string
|
|
331
|
+
data?: Record<string, unknown>
|
|
332
|
+
request_id?: string
|
|
333
|
+
}
|
|
334
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { useQuery } from '@tanstack/react-query'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
type EcosystemApiError,
|
|
5
|
+
fetchEcosystem,
|
|
6
|
+
} from 'lib/seam/ecosystem/client.js'
|
|
7
|
+
import { useEcosystemContext } from 'lib/seam/ecosystem/EcosystemProvider.js'
|
|
8
|
+
import type {
|
|
9
|
+
CompatibilityResponse,
|
|
10
|
+
CompatiblePartner,
|
|
11
|
+
} from 'lib/seam/ecosystem/types.js'
|
|
12
|
+
import {
|
|
13
|
+
retryEcosystemQuery,
|
|
14
|
+
type UseEcosystemQueryResult,
|
|
15
|
+
} from 'lib/seam/ecosystem/use-ecosystem-query-result.js'
|
|
16
|
+
|
|
17
|
+
export interface UseCompatiblePartnersParams {
|
|
18
|
+
/** Device category, e.g., `smartlock`, `thermostat`, `sensor`, `intercom`. */
|
|
19
|
+
deviceType: string
|
|
20
|
+
/** DeviceDB manufacturer slug, e.g., `schlage`. */
|
|
21
|
+
manufacturer?: string | undefined
|
|
22
|
+
/** DeviceDB provider slug, e.g., `salto-ks`. */
|
|
23
|
+
provider?: string | undefined
|
|
24
|
+
/** DeviceDB capability, e.g., `can_provision_mobile_keys`. */
|
|
25
|
+
capability?: string | undefined
|
|
26
|
+
/** Industry slug, e.g., `short-term-rental`. */
|
|
27
|
+
industry?: string | undefined
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type UseCompatiblePartnersData = CompatiblePartner[]
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The live partners that support a device category, manufacturer, provider
|
|
34
|
+
* or capability through Seam, from Ecosystem `GET /v1/compatibility`.
|
|
35
|
+
* Declared-first: a partner is listed only where Seam or the partner declared support.
|
|
36
|
+
*/
|
|
37
|
+
export function useCompatiblePartners({
|
|
38
|
+
deviceType,
|
|
39
|
+
manufacturer = '',
|
|
40
|
+
provider = '',
|
|
41
|
+
capability = '',
|
|
42
|
+
industry = '',
|
|
43
|
+
}: UseCompatiblePartnersParams): UseEcosystemQueryResult<
|
|
44
|
+
'partners',
|
|
45
|
+
UseCompatiblePartnersData
|
|
46
|
+
> {
|
|
47
|
+
const { embedKey, endpoint } = useEcosystemContext()
|
|
48
|
+
|
|
49
|
+
const params = {
|
|
50
|
+
device_category: deviceType.trim(),
|
|
51
|
+
manufacturer_slug: manufacturer.trim(),
|
|
52
|
+
provider_slug: provider.trim(),
|
|
53
|
+
capability: capability.trim(),
|
|
54
|
+
industry: industry.trim(),
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const { data, ...rest } = useQuery<
|
|
58
|
+
UseCompatiblePartnersData,
|
|
59
|
+
EcosystemApiError
|
|
60
|
+
>({
|
|
61
|
+
enabled: params.device_category.length > 0,
|
|
62
|
+
queryKey: [
|
|
63
|
+
'ecosystem',
|
|
64
|
+
endpoint,
|
|
65
|
+
embedKey ?? null,
|
|
66
|
+
'compatibility',
|
|
67
|
+
params,
|
|
68
|
+
],
|
|
69
|
+
queryFn: async ({ signal }) => {
|
|
70
|
+
const { partners } = await fetchEcosystem<CompatibilityResponse>(
|
|
71
|
+
'compatibility',
|
|
72
|
+
{ endpoint, embedKey, params, signal }
|
|
73
|
+
)
|
|
74
|
+
return partners
|
|
75
|
+
},
|
|
76
|
+
retry: retryEcosystemQuery,
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
return { ...rest, partners: data }
|
|
80
|
+
}
|