@seamapi/react 5.0.0 → 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 -2
- package/dist/ecosystem.js +45 -0
- package/dist/ecosystem.js.map +1 -0
- package/dist/elements.js +12871 -11737
- package/dist/elements.js.map +1 -1
- package/dist/index.css +469 -0
- 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 -0
- package/lib/seam/components/index.js +2 -0
- 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/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/index.ts +2 -0
- 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 -0
- package/src/styles/_supported-devices.scss +153 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
export function StateMessage({ children, actionLabel, onAction, role = 'status', }) {
|
|
3
|
+
return (_jsxs("div", { className: 'seam-ecosystem-message', role: role, children: [_jsx("p", { children: children }), actionLabel != null && onAction != null && (_jsx("button", { type: 'button', className: 'seam-ecosystem-button', onClick: onAction, children: actionLabel }))] }));
|
|
4
|
+
}
|
|
5
|
+
//# sourceMappingURL=StateMessage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StateMessage.js","sourceRoot":"","sources":["../../../src/lib/ui/ecosystem/StateMessage.tsx"],"names":[],"mappings":";AAQA,MAAM,UAAU,YAAY,CAAC,EAC3B,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,IAAI,GAAG,QAAQ,GACG;IAClB,OAAO,CACL,eAAK,SAAS,EAAC,wBAAwB,EAAC,IAAI,EAAE,IAAI,aAChD,sBAAI,QAAQ,GAAK,EAChB,WAAW,IAAI,IAAI,IAAI,QAAQ,IAAI,IAAI,IAAI,CAC1C,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,uBAAuB,EACjC,OAAO,EAAE,QAAQ,YAEhB,WAAW,GACL,CACV,IACG,CACP,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { EcosystemApiError } from '../../../lib/seam/ecosystem/client.js';
|
|
2
|
+
/** A message for an Ecosystem error, and whether retrying could help. */
|
|
3
|
+
export const getEcosystemErrorMessage = (error, fallback) => {
|
|
4
|
+
if (error instanceof EcosystemApiError) {
|
|
5
|
+
if (error.type === 'embed_key_required') {
|
|
6
|
+
return { message: t.embedKeyRequired, canRetry: false };
|
|
7
|
+
}
|
|
8
|
+
if (error.type === 'origin_not_allowed') {
|
|
9
|
+
return { message: t.originNotAllowed, canRetry: false };
|
|
10
|
+
}
|
|
11
|
+
if (error.status === 401) {
|
|
12
|
+
return { message: t.invalidEmbedKey, canRetry: false };
|
|
13
|
+
}
|
|
14
|
+
if (error.status === 403) {
|
|
15
|
+
return { message: t.originNotAllowed, canRetry: false };
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return { message: fallback, canRetry: true };
|
|
19
|
+
};
|
|
20
|
+
const t = {
|
|
21
|
+
embedKeyRequired: 'An embed key is required to show this list on this website.',
|
|
22
|
+
invalidEmbedKey: 'The embed key is invalid or has been revoked.',
|
|
23
|
+
originNotAllowed: 'The embed key is not allowed on this website.',
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/lib/ui/ecosystem/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AAEhE,yEAAyE;AACzE,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,KAAc,EACd,QAAgB,EACwB,EAAE;IAC1C,IAAI,KAAK,YAAY,iBAAiB,EAAE,CAAC;QACvC,IAAI,KAAK,CAAC,IAAI,KAAK,oBAAoB,EAAE,CAAC;YACxC,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,gBAAgB,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAA;QACzD,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,oBAAoB,EAAE,CAAC;YACxC,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,gBAAgB,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAA;QACzD,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACzB,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,eAAe,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAA;QACxD,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACzB,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,gBAAgB,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAA;QACzD,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAA;AAC9C,CAAC,CAAA;AAED,MAAM,CAAC,GAAG;IACR,gBAAgB,EACd,6DAA6D;IAC/D,eAAe,EAAE,+CAA+C;IAChE,gBAAgB,EAAE,+CAA+C;CAClE,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Decorator } from '@storybook/react';
|
|
2
|
+
export declare const storybookEmbedKeys: {
|
|
3
|
+
readonly seam: "eco_live_storybook";
|
|
4
|
+
readonly partner: "eco_live_storybook_partner";
|
|
5
|
+
readonly manufacturer: "eco_live_storybook_schlage";
|
|
6
|
+
readonly wrongOrigin: "eco_live_storybook_wrong_origin";
|
|
7
|
+
readonly invalid: "eco_live_invalid";
|
|
8
|
+
};
|
|
9
|
+
export declare const storybookEcosystemEndpoint = "/api/ecosystem/v1/";
|
|
10
|
+
export interface EcosystemStoryArgs {
|
|
11
|
+
embedKey?: string | undefined;
|
|
12
|
+
}
|
|
13
|
+
/** Wraps a story in an EcosystemProvider pointed at the fake Ecosystem API. */
|
|
14
|
+
export declare const withFakeEcosystem: Decorator<EcosystemStoryArgs>;
|
|
15
|
+
export declare const withDarkBackground: Decorator;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { EcosystemProvider } from '../../../lib/seam/ecosystem/EcosystemProvider.js';
|
|
3
|
+
// Embed keys accepted by the fake Ecosystem API served at /api/ecosystem
|
|
4
|
+
// (.storybook/fake-ecosystem.js). The Storybook never uses a real key or production data.
|
|
5
|
+
export const storybookEmbedKeys = {
|
|
6
|
+
seam: 'eco_live_storybook',
|
|
7
|
+
partner: 'eco_live_storybook_partner',
|
|
8
|
+
manufacturer: 'eco_live_storybook_schlage',
|
|
9
|
+
wrongOrigin: 'eco_live_storybook_wrong_origin',
|
|
10
|
+
invalid: 'eco_live_invalid',
|
|
11
|
+
};
|
|
12
|
+
export const storybookEcosystemEndpoint = '/api/ecosystem/v1/';
|
|
13
|
+
/** Wraps a story in an EcosystemProvider pointed at the fake Ecosystem API. */
|
|
14
|
+
export const withFakeEcosystem = (Story, context) => (_jsx(EcosystemProvider, { embedKey: context.args.embedKey, ecosystemEndpoint: storybookEcosystemEndpoint, disableCssInjection: true, disableFontInjection: true, children: _jsx(Story, {}) }));
|
|
15
|
+
export const withDarkBackground = (Story) => (_jsx("div", { style: { background: '#0b0d10', padding: 24, borderRadius: 12 }, children: _jsx(Story, {}) }));
|
|
16
|
+
//# sourceMappingURL=storybook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storybook.js","sourceRoot":"","sources":["../../../src/lib/ui/ecosystem/storybook.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAA;AAE3E,yEAAyE;AACzE,0FAA0F;AAC1F,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,IAAI,EAAE,oBAAoB;IAC1B,OAAO,EAAE,4BAA4B;IACrC,YAAY,EAAE,4BAA4B;IAC1C,WAAW,EAAE,iCAAiC;IAC9C,OAAO,EAAE,kBAAkB;CACnB,CAAA;AAEV,MAAM,CAAC,MAAM,0BAA0B,GAAG,oBAAoB,CAAA;AAM9D,+EAA+E;AAC/E,MAAM,CAAC,MAAM,iBAAiB,GAAkC,CAC9D,KAAK,EACL,OAAO,EACP,EAAE,CAAC,CACH,KAAC,iBAAiB,IAChB,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,EAC/B,iBAAiB,EAAE,0BAA0B,EAC7C,mBAAmB,QACnB,oBAAoB,kBAEpB,KAAC,KAAK,KAAG,GACS,CACrB,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAc,CAAC,KAAK,EAAE,EAAE,CAAC,CACtD,cAAK,KAAK,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,YAClE,KAAC,KAAK,KAAG,GACL,CACP,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The class name for an Ecosystem component theme.
|
|
3
|
+
* `auto` follows the visitor's `prefers-color-scheme`.
|
|
4
|
+
*/
|
|
5
|
+
export const getEcosystemThemeClassName = (theme) => {
|
|
6
|
+
if (theme === 'dark' || theme === 'auto') {
|
|
7
|
+
return `seam-ecosystem-theme-${theme}`;
|
|
8
|
+
}
|
|
9
|
+
return 'seam-ecosystem-theme-light';
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=theme.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.js","sourceRoot":"","sources":["../../../src/lib/ui/ecosystem/theme.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CACxC,KAAyB,EACjB,EAAE;IACV,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QACzC,OAAO,wBAAwB,KAAK,EAAE,CAAA;IACxC,CAAC;IACD,OAAO,4BAA4B,CAAA;AACrC,CAAC,CAAA"}
|
package/lib/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const seamapiReactVersion = "5.
|
|
1
|
+
declare const seamapiReactVersion = "5.1.0";
|
|
2
2
|
export default seamapiReactVersion;
|
package/lib/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seamapi/react",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"description": "Seam Components.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
"import": "./dist/elements.js",
|
|
19
19
|
"types": "./src/elements.d.ts"
|
|
20
20
|
},
|
|
21
|
+
"./ecosystem.js": {
|
|
22
|
+
"import": "./dist/ecosystem.js",
|
|
23
|
+
"types": "./src/ecosystem.d.ts"
|
|
24
|
+
},
|
|
21
25
|
"./index.css": {
|
|
22
26
|
"import": "./dist/index.css"
|
|
23
27
|
}
|
|
@@ -26,7 +30,8 @@
|
|
|
26
30
|
"sideEffects": [
|
|
27
31
|
"**/*.css",
|
|
28
32
|
"./elements.js",
|
|
29
|
-
"./dist/elements.js"
|
|
33
|
+
"./dist/elements.js",
|
|
34
|
+
"./dist/ecosystem.js"
|
|
30
35
|
],
|
|
31
36
|
"keywords": [
|
|
32
37
|
"node"
|
|
@@ -64,7 +69,10 @@
|
|
|
64
69
|
"postbuild": "concurrently --raw --group 'node ./index.js' 'node ./hooks.js'",
|
|
65
70
|
"build:entrypoints": "npm run build:js",
|
|
66
71
|
"prebuild:entrypoints": "npm run build:css",
|
|
67
|
-
"postbuild:entrypoints": "
|
|
72
|
+
"postbuild:entrypoints": "npm run build:elements && npm run build:ecosystem",
|
|
73
|
+
"build:elements": "vite build",
|
|
74
|
+
"build:ecosystem": "vite build --mode ecosystem",
|
|
75
|
+
"size": "tsx ./size.ts",
|
|
68
76
|
"build:js": "tsc --project tsconfig.build.json",
|
|
69
77
|
"postbuild:js": "tsc-alias --project tsconfig.build.json",
|
|
70
78
|
"build:css": "sass --load-path=node_modules src/index.scss:dist/index.css",
|
package/src/ecosystem.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineEcosystemElements } from 'lib/ecosystem-element.js'
|
|
2
|
+
import * as components from 'lib/seam/components/ecosystem-elements.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The lightweight Seam Ecosystem web components bundle:
|
|
6
|
+
* only <seam-compatible-apps> and <seam-supported-devices>,
|
|
7
|
+
* without the Seam API client used by the other Seam Components.
|
|
8
|
+
* These elements are also defined by elements.js.
|
|
9
|
+
*/
|
|
10
|
+
export const elementNames: string[] = defineEcosystemElements(components)
|
|
11
|
+
|
|
12
|
+
export default elementNames
|
package/src/elements.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { defineEcosystemElements } from 'lib/ecosystem-element.js'
|
|
1
2
|
import { defineCustomElement, type ElementDefinition } from 'lib/element.js'
|
|
3
|
+
import * as ecosystemComponents from 'lib/seam/components/ecosystem-elements.js'
|
|
2
4
|
import * as components from 'lib/seam/components/elements.js'
|
|
3
5
|
|
|
4
6
|
const elementDefinitions = components as unknown as Record<
|
|
@@ -30,3 +32,5 @@ for (const key of Object.keys(elementDefinitions)) {
|
|
|
30
32
|
elementNames.push(name)
|
|
31
33
|
defineCustomElement({ name, Component, props })
|
|
32
34
|
}
|
|
35
|
+
|
|
36
|
+
elementNames.push(...defineEcosystemElements(ecosystemComponents))
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import r2wc from '@rxfork/r2wc-react-to-web-component'
|
|
2
|
+
import type { ComponentType } from 'react'
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
EcosystemProvider,
|
|
6
|
+
type EcosystemProviderProps,
|
|
7
|
+
} from 'lib/seam/ecosystem/EcosystemProvider.js'
|
|
8
|
+
|
|
9
|
+
declare global {
|
|
10
|
+
// eslint-disable-next-line no-var
|
|
11
|
+
var disableSeamCssInjection: boolean | undefined
|
|
12
|
+
// eslint-disable-next-line no-var
|
|
13
|
+
var disableSeamFontInjection: boolean | undefined
|
|
14
|
+
// eslint-disable-next-line no-var
|
|
15
|
+
var unminifiySeamCss: boolean | undefined
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type PropType = 'string' | 'number' | 'boolean' | 'array' | 'object'
|
|
19
|
+
|
|
20
|
+
export type EcosystemElementProps<T> = Record<
|
|
21
|
+
Exclude<keyof T, 'className'>,
|
|
22
|
+
PropType
|
|
23
|
+
>
|
|
24
|
+
|
|
25
|
+
export interface EcosystemElementDefinition {
|
|
26
|
+
name: string
|
|
27
|
+
Component: ComponentType<any>
|
|
28
|
+
props?: Record<string, PropType>
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
type ProviderProps = Omit<EcosystemProviderProps, 'children'>
|
|
32
|
+
|
|
33
|
+
const providerProps: Record<keyof ProviderProps, PropType> = {
|
|
34
|
+
embedKey: 'string',
|
|
35
|
+
ecosystemEndpoint: 'string',
|
|
36
|
+
queryClient: 'object',
|
|
37
|
+
disableCssInjection: 'boolean',
|
|
38
|
+
disableFontInjection: 'boolean',
|
|
39
|
+
unminifiyCss: 'boolean',
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const commonProps: Record<string, PropType> = {
|
|
43
|
+
className: 'string',
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Defines the custom elements for the Seam Ecosystem components.
|
|
48
|
+
* Each element is wrapped in an `<EcosystemProvider />`, not a `<SeamProvider />`,
|
|
49
|
+
* so it needs no publishable key and does not load the Seam API client.
|
|
50
|
+
* Elements that are already defined are skipped,
|
|
51
|
+
* so `elements.js` and `ecosystem.js` may both be loaded on one page.
|
|
52
|
+
*/
|
|
53
|
+
export const defineEcosystemElements = (
|
|
54
|
+
definitions: Record<string, Partial<EcosystemElementDefinition>>
|
|
55
|
+
): string[] => {
|
|
56
|
+
const names: string[] = []
|
|
57
|
+
for (const [key, definition] of Object.entries(definitions)) {
|
|
58
|
+
const { name, Component, props } = definition
|
|
59
|
+
if (name == null) throw new Error(`Missing element name for ${key}`)
|
|
60
|
+
if (Component == null) {
|
|
61
|
+
throw new Error(`Missing element Component for ${key}`)
|
|
62
|
+
}
|
|
63
|
+
names.push(name)
|
|
64
|
+
defineEcosystemElement({ name, Component, props })
|
|
65
|
+
}
|
|
66
|
+
return names
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export const defineEcosystemElement = ({
|
|
70
|
+
name,
|
|
71
|
+
Component,
|
|
72
|
+
props = {},
|
|
73
|
+
}: EcosystemElementDefinition): void => {
|
|
74
|
+
const registry = globalThis.customElements
|
|
75
|
+
if (registry == null || registry.get(name) != null) return
|
|
76
|
+
|
|
77
|
+
const allProps = { ...props, ...providerProps, ...commonProps }
|
|
78
|
+
|
|
79
|
+
// UPSTREAM: r2wc parses boolean attributes as false when present without a value,
|
|
80
|
+
// e.g., <seam-compatible-apps hide-search>, so they are parsed here instead.
|
|
81
|
+
const booleanProps = Object.entries(allProps)
|
|
82
|
+
.filter(([, type]) => type === 'boolean')
|
|
83
|
+
.map(([prop]) => prop)
|
|
84
|
+
|
|
85
|
+
const element = r2wc(withEcosystemProvider(Component, booleanProps), {
|
|
86
|
+
props: Object.fromEntries(
|
|
87
|
+
Object.entries(allProps).map(([prop, type]) => [
|
|
88
|
+
prop,
|
|
89
|
+
type === 'boolean' ? 'string' : type,
|
|
90
|
+
])
|
|
91
|
+
),
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
registry.define(name, element)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Parses a boolean attribute or property:
|
|
99
|
+
* present without a value or `true` is true; absent or `false` is false.
|
|
100
|
+
*/
|
|
101
|
+
export const parseBooleanProp = (value: unknown): boolean | undefined => {
|
|
102
|
+
if (value == null) return undefined
|
|
103
|
+
if (typeof value === 'boolean') return value
|
|
104
|
+
if (typeof value !== 'string') return Boolean(value)
|
|
105
|
+
return !/^(false|0|no|off)$/i.test(value.trim())
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function withEcosystemProvider(
|
|
109
|
+
Component: ComponentType<any>,
|
|
110
|
+
booleanProps: string[]
|
|
111
|
+
): (props: Record<string, unknown>) => JSX.Element {
|
|
112
|
+
const name = Component.displayName ?? Component.name ?? 'Component'
|
|
113
|
+
|
|
114
|
+
function WithEcosystemProvider({
|
|
115
|
+
container: _container,
|
|
116
|
+
...rawProps
|
|
117
|
+
}: Record<string, unknown>): JSX.Element {
|
|
118
|
+
const props: Record<string, unknown> = { ...rawProps }
|
|
119
|
+
for (const prop of booleanProps) {
|
|
120
|
+
props[prop] = parseBooleanProp(props[prop])
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const {
|
|
124
|
+
embedKey,
|
|
125
|
+
ecosystemEndpoint,
|
|
126
|
+
queryClient,
|
|
127
|
+
disableCssInjection,
|
|
128
|
+
disableFontInjection,
|
|
129
|
+
unminifiyCss,
|
|
130
|
+
...componentProps
|
|
131
|
+
} = props as ProviderProps & Record<string, unknown>
|
|
132
|
+
|
|
133
|
+
return (
|
|
134
|
+
<EcosystemProvider
|
|
135
|
+
embedKey={embedKey}
|
|
136
|
+
ecosystemEndpoint={ecosystemEndpoint}
|
|
137
|
+
queryClient={queryClient}
|
|
138
|
+
disableCssInjection={
|
|
139
|
+
disableCssInjection ?? globalThis.disableSeamCssInjection
|
|
140
|
+
}
|
|
141
|
+
disableFontInjection={
|
|
142
|
+
disableFontInjection ?? globalThis.disableSeamFontInjection
|
|
143
|
+
}
|
|
144
|
+
unminifiyCss={unminifiyCss ?? globalThis.unminifiySeamCss}
|
|
145
|
+
>
|
|
146
|
+
<Component {...componentProps} />
|
|
147
|
+
</EcosystemProvider>
|
|
148
|
+
)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
WithEcosystemProvider.displayName = `WithEcosystemProvider(${name})`
|
|
152
|
+
|
|
153
|
+
return WithEcosystemProvider
|
|
154
|
+
}
|
package/src/lib/element.tsx
CHANGED
|
@@ -64,6 +64,8 @@ const providerProps: R2wcProps<ProviderProps> = {
|
|
|
64
64
|
disableFontInjection: 'boolean',
|
|
65
65
|
unminifiyCss: 'boolean',
|
|
66
66
|
onSessionUpdate: 'object',
|
|
67
|
+
embedKey: 'string',
|
|
68
|
+
ecosystemEndpoint: 'string',
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
export const defineCustomElement = ({
|
|
@@ -96,6 +98,8 @@ function withProvider<P extends JSX.IntrinsicAttributes>(
|
|
|
96
98
|
disableFontInjection,
|
|
97
99
|
unminifiyCss,
|
|
98
100
|
onSessionUpdate,
|
|
101
|
+
embedKey,
|
|
102
|
+
ecosystemEndpoint,
|
|
99
103
|
container: _container,
|
|
100
104
|
...props
|
|
101
105
|
}: ProviderProps & { container: Container } & P): JSX.Element | null {
|
|
@@ -114,6 +118,8 @@ function withProvider<P extends JSX.IntrinsicAttributes>(
|
|
|
114
118
|
}
|
|
115
119
|
unminifiyCss={unminifiyCss ?? globalThis.unminifiySeamCss}
|
|
116
120
|
onSessionUpdate={onSessionUpdate}
|
|
121
|
+
embedKey={embedKey}
|
|
122
|
+
ecosystemEndpoint={ecosystemEndpoint}
|
|
117
123
|
>
|
|
118
124
|
<Component {...(props as P)} />
|
|
119
125
|
</SeamProvider>
|
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
import type { QueryClient } from '@tanstack/react-query'
|
|
9
9
|
import { createContext, type PropsWithChildren, useMemo } from 'react'
|
|
10
10
|
|
|
11
|
+
import { EcosystemContextProvider } from 'lib/seam/ecosystem/EcosystemProvider.js'
|
|
12
|
+
import { seamComponentsClassName } from 'lib/seam/seam-components-class-name.js'
|
|
11
13
|
import { useSeamFont } from 'lib/seam/use-seam-font.js'
|
|
12
14
|
import { useSeamStyles } from 'lib/seam/use-seam-styles.js'
|
|
13
15
|
import {
|
|
@@ -58,9 +60,16 @@ interface SeamProviderBaseProps extends PropsWithChildren {
|
|
|
58
60
|
queryClient?: QueryClient | undefined
|
|
59
61
|
telemetryClient?: TelemetryClient | undefined
|
|
60
62
|
onSessionUpdate?: (client: SeamHttp) => void
|
|
63
|
+
/**
|
|
64
|
+
* Seam Ecosystem embed key (`eco_live_…`) used by the Ecosystem components,
|
|
65
|
+
* e.g., `CompatibleApps` and `SupportedDevices`.
|
|
66
|
+
*/
|
|
67
|
+
embedKey?: string | undefined
|
|
68
|
+
/** Seam Ecosystem API endpoint. Defaults to `https://ecosystem.seam.co/v1/`. */
|
|
69
|
+
ecosystemEndpoint?: string | undefined
|
|
61
70
|
}
|
|
62
71
|
|
|
63
|
-
export
|
|
72
|
+
export { seamComponentsClassName }
|
|
64
73
|
|
|
65
74
|
export function SeamProvider({
|
|
66
75
|
children,
|
|
@@ -70,6 +79,8 @@ export function SeamProvider({
|
|
|
70
79
|
unminifiyCss = false,
|
|
71
80
|
telemetryClient,
|
|
72
81
|
queryClient,
|
|
82
|
+
embedKey,
|
|
83
|
+
ecosystemEndpoint,
|
|
73
84
|
...props
|
|
74
85
|
}: SeamProviderProps): JSX.Element {
|
|
75
86
|
useSeamStyles({ disabled: disableCssInjection, unminified: unminifiyCss })
|
|
@@ -95,7 +106,12 @@ export function SeamProvider({
|
|
|
95
106
|
{...props}
|
|
96
107
|
>
|
|
97
108
|
<Provider value={value}>
|
|
98
|
-
<
|
|
109
|
+
<EcosystemContextProvider
|
|
110
|
+
embedKey={embedKey}
|
|
111
|
+
ecosystemEndpoint={ecosystemEndpoint}
|
|
112
|
+
>
|
|
113
|
+
<Telemetry>{children}</Telemetry>
|
|
114
|
+
</EcosystemContextProvider>
|
|
99
115
|
</Provider>
|
|
100
116
|
</SeamQueryProvider>
|
|
101
117
|
</TelemetryProvider>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { EcosystemElementProps } from 'lib/ecosystem-element.js'
|
|
2
|
+
|
|
3
|
+
import type { CompatibleAppsProps } from './CompatibleApps.js'
|
|
4
|
+
|
|
5
|
+
export const name = 'seam-compatible-apps'
|
|
6
|
+
|
|
7
|
+
export const props: EcosystemElementProps<CompatibleAppsProps> = {
|
|
8
|
+
deviceType: 'string',
|
|
9
|
+
manufacturer: 'string',
|
|
10
|
+
provider: 'string',
|
|
11
|
+
capability: 'string',
|
|
12
|
+
industry: 'string',
|
|
13
|
+
maxVisible: 'number',
|
|
14
|
+
hideSearch: 'boolean',
|
|
15
|
+
hideTitle: 'boolean',
|
|
16
|
+
theme: 'string',
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { CompatibleApps as Component } from './CompatibleApps.js'
|