@servicetitan/web-components 30.3.0 → 31.0.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/dist/__mocks__/test-component.d.ts.map +1 -1
- package/dist/common.js +17 -13
- package/dist/common.js.map +1 -1
- package/dist/contexts/index.js +1 -0
- package/dist/contexts/index.js.map +1 -1
- package/dist/contexts/mfe-data-context.js +2 -2
- package/dist/contexts/mfe-data-context.js.map +1 -1
- package/dist/contexts/mfe-metadata-context.js +1 -0
- package/dist/contexts/mfe-metadata-context.js.map +1 -1
- package/dist/delayed.js +8 -5
- package/dist/delayed.js.map +1 -1
- package/dist/event-bus.js +79 -96
- package/dist/event-bus.js.map +1 -1
- package/dist/get-value-for-environment.js +9 -4
- package/dist/get-value-for-environment.js.map +1 -1
- package/dist/globals.js +7 -7
- package/dist/globals.js.map +1 -1
- package/dist/history-manager.js +59 -69
- package/dist/history-manager.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/loader.js +92 -49
- package/dist/loader.js.map +1 -1
- package/dist/register.js +182 -218
- package/dist/register.js.map +1 -1
- package/dist/render.js +11 -12
- package/dist/render.js.map +1 -1
- package/dist/types.js +2 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/get-bundle-info.js +18 -16
- package/dist/utils/get-bundle-info.js.map +1 -1
- package/dist/utils/get-element-name.js +1 -0
- package/dist/utils/get-element-name.js.map +1 -1
- package/dist/utils/get-entry-points.js +11 -4
- package/dist/utils/get-entry-points.js.map +1 -1
- package/dist/utils/get-ld-service-token.js +3 -3
- package/dist/utils/get-ld-service-token.js.map +1 -1
- package/dist/utils/get-mfe-has-compatible-launchdarkly-version.js +4 -4
- package/dist/utils/get-mfe-has-compatible-launchdarkly-version.js.map +1 -1
- package/dist/utils/get-mfe-has-unique-chunk-namespace.js +1 -0
- package/dist/utils/get-mfe-has-unique-chunk-namespace.js.map +1 -1
- package/dist/utils/get-mfe-supports-rerendering.js +4 -4
- package/dist/utils/get-mfe-supports-rerendering.js.map +1 -1
- package/dist/utils/get-version-mismatches.js +18 -11
- package/dist/utils/get-version-mismatches.js.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/is-compatible.js +1 -0
- package/dist/utils/is-compatible.js.map +1 -1
- package/dist/utils/is-versioned-url.js +2 -1
- package/dist/utils/is-versioned-url.js.map +1 -1
- package/dist/utils/load-scripts.js +7 -6
- package/dist/utils/load-scripts.js.map +1 -1
- package/dist/utils/ttl-cache.js +26 -27
- package/dist/utils/ttl-cache.js.map +1 -1
- package/dist/utils/validate-bundle-info.js +13 -10
- package/dist/utils/validate-bundle-info.js.map +1 -1
- package/dist/utils/web-component.js +46 -22
- package/dist/utils/web-component.js.map +1 -1
- package/package.json +11 -11
- package/src/__mocks__/test-component.tsx +2 -0
- package/src/__tests__/event-bus.test.ts +1 -0
- package/src/__tests__/loader.test.tsx +3 -3
- package/src/event-bus.ts +1 -0
- package/dist/__mocks__/expect-styles-in-dom.js +0 -9
- package/dist/__mocks__/expect-styles-in-dom.js.map +0 -1
- package/dist/__mocks__/index.js +0 -4
- package/dist/__mocks__/index.js.map +0 -1
- package/dist/__mocks__/register-component.js +0 -14
- package/dist/__mocks__/register-component.js.map +0 -1
- package/dist/__mocks__/test-component.js +0 -15
- package/dist/__mocks__/test-component.js.map +0 -1
- package/dist/contexts/tests/mfe-data-context.test.js +0 -24
- package/dist/contexts/tests/mfe-data-context.test.js.map +0 -1
- package/dist/contexts/tests/mfe-metadata-context.test.js +0 -26
- package/dist/contexts/tests/mfe-metadata-context.test.js.map +0 -1
|
@@ -1,39 +1,42 @@
|
|
|
1
1
|
export function validateBundleInfo({ mismatch, mfeHasCompatibleLaunchDarklyVersion }, { exposedDependencies = {}, exposedInstanceDependencies, logService, packageUrl }) {
|
|
2
|
-
var _a, _b;
|
|
3
2
|
if (!logService) {
|
|
4
3
|
return;
|
|
5
4
|
}
|
|
6
5
|
if (mismatch) {
|
|
7
|
-
const data = {
|
|
6
|
+
const data = {
|
|
7
|
+
package: packageUrl,
|
|
8
|
+
dependencies: JSON.stringify(mismatch)
|
|
9
|
+
};
|
|
8
10
|
if (Object.keys(exposedDependencies).length === 0) {
|
|
9
11
|
logService.warning({
|
|
10
12
|
category: 'MicroFrontends.NoExposedDependencies',
|
|
11
13
|
message: 'Cannot use light bundle because the host is not exposing dependencies or the list of shared dependencies is empty.',
|
|
12
|
-
data
|
|
14
|
+
data
|
|
13
15
|
});
|
|
14
|
-
}
|
|
15
|
-
else {
|
|
16
|
+
} else {
|
|
16
17
|
logService.warning({
|
|
17
18
|
category: 'MicroFrontends.DependenciesMismatch',
|
|
18
19
|
message: 'Some of the package dependencies have incompatible versions.',
|
|
19
|
-
data
|
|
20
|
+
data
|
|
20
21
|
});
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
/**
|
|
24
25
|
* Note, only checking false here because the value is undefined when the host
|
|
25
26
|
* or the MFE isn't using LaunchDarkly at all.
|
|
26
|
-
*/
|
|
27
|
-
|
|
27
|
+
*/ if (mfeHasCompatibleLaunchDarklyVersion === false) {
|
|
28
|
+
var _exposedInstanceDependencies_launchDarkly;
|
|
29
|
+
var _exposedInstanceDependencies_launchDarkly_version;
|
|
28
30
|
const data = {
|
|
29
31
|
package: packageUrl,
|
|
30
|
-
hostVersion: (
|
|
32
|
+
hostVersion: (_exposedInstanceDependencies_launchDarkly_version = exposedInstanceDependencies === null || exposedInstanceDependencies === void 0 ? void 0 : (_exposedInstanceDependencies_launchDarkly = exposedInstanceDependencies.launchDarkly) === null || _exposedInstanceDependencies_launchDarkly === void 0 ? void 0 : _exposedInstanceDependencies_launchDarkly.version) !== null && _exposedInstanceDependencies_launchDarkly_version !== void 0 ? _exposedInstanceDependencies_launchDarkly_version : ''
|
|
31
33
|
};
|
|
32
34
|
logService.warning({
|
|
33
35
|
category: 'MicroFrontends.LaunchDarklyMismatch',
|
|
34
36
|
message: 'LaunchDarkly versions are incompatible',
|
|
35
|
-
data
|
|
37
|
+
data
|
|
36
38
|
});
|
|
37
39
|
}
|
|
38
40
|
}
|
|
41
|
+
|
|
39
42
|
//# sourceMappingURL=validate-bundle-info.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"sources":["../../src/utils/validate-bundle-info.ts"],"sourcesContent":["import { Log } from '@servicetitan/log-service';\nimport { ExposedDependencies, ExposedInstanceDependencies } from '../common';\nimport { BundleInfo } from './get-bundle-info';\n\ninterface Context {\n exposedDependencies?: ExposedDependencies;\n exposedInstanceDependencies?: ExposedInstanceDependencies;\n logService?: Log;\n packageUrl: string;\n}\nexport function validateBundleInfo(\n { mismatch, mfeHasCompatibleLaunchDarklyVersion }: BundleInfo,\n { exposedDependencies = {}, exposedInstanceDependencies, logService, packageUrl }: Context\n) {\n if (!logService) {\n return;\n }\n\n if (mismatch) {\n const data = { package: packageUrl, dependencies: JSON.stringify(mismatch) };\n if (Object.keys(exposedDependencies).length === 0) {\n logService.warning({\n category: 'MicroFrontends.NoExposedDependencies',\n message:\n 'Cannot use light bundle because the host is not exposing dependencies or the list of shared dependencies is empty.',\n data,\n });\n } else {\n logService.warning({\n category: 'MicroFrontends.DependenciesMismatch',\n message: 'Some of the package dependencies have incompatible versions.',\n data,\n });\n }\n }\n\n /**\n * Note, only checking false here because the value is undefined when the host\n * or the MFE isn't using LaunchDarkly at all.\n */\n\n if (mfeHasCompatibleLaunchDarklyVersion === false) {\n const data = {\n package: packageUrl,\n hostVersion: exposedInstanceDependencies?.launchDarkly?.version ?? '',\n };\n logService.warning({\n category: 'MicroFrontends.LaunchDarklyMismatch',\n message: 'LaunchDarkly versions are incompatible',\n data,\n });\n }\n}\n"],"names":["validateBundleInfo","mismatch","mfeHasCompatibleLaunchDarklyVersion","exposedDependencies","exposedInstanceDependencies","logService","packageUrl","data","package","dependencies","JSON","stringify","Object","keys","length","warning","category","message","hostVersion","launchDarkly","version"],"mappings":"AAUA,OAAO,SAASA,mBACZ,EAAEC,QAAQ,EAAEC,mCAAmC,EAAc,EAC7D,EAAEC,sBAAsB,CAAC,CAAC,EAAEC,2BAA2B,EAAEC,UAAU,EAAEC,UAAU,EAAW;IAE1F,IAAI,CAACD,YAAY;QACb;IACJ;IAEA,IAAIJ,UAAU;QACV,MAAMM,OAAO;YAAEC,SAASF;YAAYG,cAAcC,KAAKC,SAAS,CAACV;QAAU;QAC3E,IAAIW,OAAOC,IAAI,CAACV,qBAAqBW,MAAM,KAAK,GAAG;YAC/CT,WAAWU,OAAO,CAAC;gBACfC,UAAU;gBACVC,SACI;gBACJV;YACJ;QACJ,OAAO;YACHF,WAAWU,OAAO,CAAC;gBACfC,UAAU;gBACVC,SAAS;gBACTV;YACJ;QACJ;IACJ;IAEA;;;KAGC,GAED,IAAIL,wCAAwC,OAAO;YAG9BE;YAAAA;QAFjB,MAAMG,OAAO;YACTC,SAASF;YACTY,aAAad,CAAAA,oDAAAA,wCAAAA,mDAAAA,4CAAAA,4BAA6Be,YAAY,cAAzCf,gEAAAA,0CAA2CgB,OAAO,cAAlDhB,+DAAAA,oDAAsD;QACvE;QACAC,WAAWU,OAAO,CAAC;YACfC,UAAU;YACVC,SAAS;YACTV;QACJ;IACJ;AACJ"}
|
|
@@ -4,15 +4,15 @@ import { useOptionalDependencies } from '@servicetitan/react-ioc';
|
|
|
4
4
|
import { getElementName } from './get-element-name';
|
|
5
5
|
import { HistoryManager } from '../history-manager';
|
|
6
6
|
export function webComponent(props) {
|
|
7
|
-
var
|
|
7
|
+
var _bundleInfo_bundledWith;
|
|
8
8
|
const { basename, bundleInfo, eventBus, exposedDependencies, ldService, logService } = props;
|
|
9
9
|
const { WebComponent, disposer, mfeSupportsRerendering, version } = bundleInfo;
|
|
10
10
|
const elementName = getElementName(bundleInfo);
|
|
11
|
-
const exposedInstanceDependencies = ensureLDVersion(props.exposedInstanceDependencies, (
|
|
12
|
-
return ({ LoadingFallback, ...props })
|
|
11
|
+
const exposedInstanceDependencies = ensureLDVersion(props.exposedInstanceDependencies, (_bundleInfo_bundledWith = bundleInfo.bundledWith) === null || _bundleInfo_bundledWith === void 0 ? void 0 : _bundleInfo_bundledWith['launchdarkly-js-client-sdk']);
|
|
12
|
+
return ({ LoadingFallback, ...props })=>{
|
|
13
13
|
const [isLoading, setIsLoading] = useState(true);
|
|
14
14
|
const [historyManager] = useOptionalDependencies(HistoryManager);
|
|
15
|
-
const handleRef = (webComponent)
|
|
15
|
+
const handleRef = (webComponent)=>{
|
|
16
16
|
webComponent === null || webComponent === void 0 ? void 0 : webComponent.provide({
|
|
17
17
|
ldService,
|
|
18
18
|
logService,
|
|
@@ -21,44 +21,67 @@ export function webComponent(props) {
|
|
|
21
21
|
exposedInstanceDependencies,
|
|
22
22
|
eventBus,
|
|
23
23
|
basename,
|
|
24
|
-
onReady: ()
|
|
24
|
+
onReady: ()=>{
|
|
25
25
|
setIsLoading(false);
|
|
26
26
|
},
|
|
27
|
-
onDispose: ()
|
|
27
|
+
onDispose: ()=>{
|
|
28
28
|
disposer();
|
|
29
|
-
}
|
|
29
|
+
}
|
|
30
30
|
});
|
|
31
31
|
};
|
|
32
32
|
// Stringify data object so that it can be passed as a data-attribute
|
|
33
|
-
const stringifiedData = useMemo(()
|
|
33
|
+
const stringifiedData = useMemo(()=>JSON.stringify(props.data), [
|
|
34
|
+
props.data
|
|
35
|
+
]);
|
|
34
36
|
/*
|
|
35
37
|
* Set key for rendering the web component so that if the data from the Host change,
|
|
36
38
|
* and the MFE's version of startup doesn't support watching for data changes, then
|
|
37
39
|
* the web component will be re-mounted whenever the data changes.
|
|
38
40
|
* This is only used as a fallback when the MFE's version is older.
|
|
39
|
-
*/
|
|
40
|
-
const
|
|
41
|
-
|
|
41
|
+
*/ const key = mfeSupportsRerendering ? undefined : stringifiedData;
|
|
42
|
+
const dataAttrs = useMemo(()=>composeDataAttributes(props.data), [
|
|
43
|
+
props.data
|
|
44
|
+
]);
|
|
42
45
|
const styleUrls = getStyleUrls(bundleInfo);
|
|
43
|
-
return
|
|
46
|
+
return /*#__PURE__*/ _jsxs(Fragment, {
|
|
47
|
+
children: [
|
|
48
|
+
isLoading && /*#__PURE__*/ _jsx(LoadingFallback, {}),
|
|
49
|
+
/*#__PURE__*/ _jsx(WebComponent, {
|
|
44
50
|
// @ts-expect-error because property ref does not exist on IntrinsicAttributes
|
|
45
|
-
ref: handleRef,
|
|
51
|
+
ref: handleRef,
|
|
52
|
+
class: props.className,
|
|
53
|
+
...styleUrls && {
|
|
54
|
+
'style-urls': styleUrls
|
|
55
|
+
},
|
|
56
|
+
...dataAttrs,
|
|
57
|
+
"data-mfe-data": stringifiedData,
|
|
58
|
+
"data-mfe-name": elementName,
|
|
59
|
+
...version && {
|
|
60
|
+
'data-mfe-version': version
|
|
61
|
+
}
|
|
62
|
+
}, key)
|
|
63
|
+
]
|
|
64
|
+
});
|
|
46
65
|
};
|
|
47
66
|
}
|
|
48
67
|
/*
|
|
49
68
|
* Convert camelCase data props to kebab-case data attributes, prepended with data-
|
|
50
69
|
* Ex: fooBar -> data-foo-bar
|
|
51
|
-
*/
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
]));
|
|
70
|
+
*/ function composeDataAttributes(data = {}) {
|
|
71
|
+
return Object.fromEntries(Object.entries(data).map(([key, value])=>[
|
|
72
|
+
'data-' + key.replace(/[A-Z]/g, (letter)=>'-' + letter.toLowerCase()),
|
|
73
|
+
value
|
|
74
|
+
]));
|
|
57
75
|
}
|
|
58
76
|
function ensureLDVersion(exposedInstanceDependencies = {}, version) {
|
|
59
|
-
var
|
|
60
|
-
if (version && !((
|
|
61
|
-
return {
|
|
77
|
+
var _exposedInstanceDependencies_launchDarkly;
|
|
78
|
+
if (version && !((_exposedInstanceDependencies_launchDarkly = exposedInstanceDependencies.launchDarkly) === null || _exposedInstanceDependencies_launchDarkly === void 0 ? void 0 : _exposedInstanceDependencies_launchDarkly.ldService)) {
|
|
79
|
+
return {
|
|
80
|
+
...exposedInstanceDependencies,
|
|
81
|
+
launchDarkly: {
|
|
82
|
+
version
|
|
83
|
+
}
|
|
84
|
+
};
|
|
62
85
|
}
|
|
63
86
|
return exposedInstanceDependencies;
|
|
64
87
|
}
|
|
@@ -67,4 +90,5 @@ function getStyleUrls({ urls }) {
|
|
|
67
90
|
return encodeURIComponent(JSON.stringify(urls.css));
|
|
68
91
|
}
|
|
69
92
|
}
|
|
93
|
+
|
|
70
94
|
//# sourceMappingURL=web-component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"sources":["../../src/utils/web-component.tsx"],"sourcesContent":["import { Fragment, useMemo, useState } from 'react';\nimport { Log } from '@servicetitan/log-service';\nimport { type LDService } from '@servicetitan/launchdarkly-service';\nimport { useOptionalDependencies } from '@servicetitan/react-ioc';\n\nimport { ExposedDependencies, ExposedInstanceDependencies, IWebComponent } from '../common';\nimport { MFEContextData } from '../contexts/mfe-data-context';\nimport { EventBus } from '../event-bus';\nimport { BundleInfo } from './get-bundle-info';\nimport { getElementName } from './get-element-name';\nimport { HistoryManager } from '../history-manager';\nimport { LoaderDataProps } from '../loader';\n\ninterface WebComponentProps {\n basename?: string;\n bundleInfo: BundleInfo;\n eventBus: EventBus;\n exposedDependencies?: ExposedDependencies;\n exposedInstanceDependencies?: ExposedInstanceDependencies;\n ldService?: LDService;\n logService?: Log;\n}\n\nexport function webComponent(props: WebComponentProps) {\n const { basename, bundleInfo, eventBus, exposedDependencies, ldService, logService } = props;\n const { WebComponent, disposer, mfeSupportsRerendering, version } = bundleInfo;\n const elementName = getElementName(bundleInfo);\n\n const exposedInstanceDependencies = ensureLDVersion(\n props.exposedInstanceDependencies,\n bundleInfo.bundledWith?.['launchdarkly-js-client-sdk']\n );\n\n return ({ LoadingFallback, ...props }: LoaderDataProps) => {\n const [isLoading, setIsLoading] = useState(true);\n const [historyManager] = useOptionalDependencies(HistoryManager);\n\n const handleRef = (webComponent: IWebComponent | null) => {\n webComponent?.provide({\n ldService,\n logService,\n historyManager,\n exposedDependencies,\n exposedInstanceDependencies,\n eventBus,\n basename,\n onReady: () => {\n setIsLoading(false);\n },\n onDispose: () => {\n disposer();\n },\n });\n };\n\n // Stringify data object so that it can be passed as a data-attribute\n const stringifiedData = useMemo(() => JSON.stringify(props.data), [props.data]);\n\n /*\n * Set key for rendering the web component so that if the data from the Host change,\n * and the MFE's version of startup doesn't support watching for data changes, then\n * the web component will be re-mounted whenever the data changes.\n * This is only used as a fallback when the MFE's version is older.\n */\n const key = mfeSupportsRerendering ? undefined : stringifiedData;\n const dataAttrs = useMemo(() => composeDataAttributes(props.data), [props.data]);\n const styleUrls = getStyleUrls(bundleInfo);\n\n return (\n <Fragment>\n {isLoading && <LoadingFallback />}\n <WebComponent\n key={key}\n // @ts-expect-error because property ref does not exist on IntrinsicAttributes\n ref={handleRef}\n class={props.className}\n {...(styleUrls && { 'style-urls': styleUrls })}\n /*\n * Continue to spread data as separate data attributes for backwards compatibility,\n * in case the Host has updated web-components, but the MFE has not\n */\n {...dataAttrs}\n data-mfe-data={stringifiedData}\n data-mfe-name={elementName}\n {...(version && { 'data-mfe-version': version })}\n />\n </Fragment>\n );\n };\n}\n\n/*\n * Convert camelCase data props to kebab-case data attributes, prepended with data-\n * Ex: fooBar -> data-foo-bar\n */\nfunction composeDataAttributes(data: MFEContextData<{}> | undefined = {}) {\n return Object.fromEntries(\n Object.entries(data).map(([key, value]) => [\n 'data-' + key.replace(/[A-Z]/g, letter => '-' + letter.toLowerCase()),\n value,\n ])\n );\n}\n\nfunction ensureLDVersion(\n exposedInstanceDependencies: ExposedInstanceDependencies = {},\n version?: string\n) {\n if (version && !exposedInstanceDependencies.launchDarkly?.ldService) {\n return { ...exposedInstanceDependencies, launchDarkly: { version } };\n }\n return exposedInstanceDependencies;\n}\n\nfunction getStyleUrls({ urls }: Pick<BundleInfo, 'urls'>) {\n if (urls.css.length) {\n return encodeURIComponent(JSON.stringify(urls.css));\n }\n}\n"],"names":["Fragment","useMemo","useState","useOptionalDependencies","getElementName","HistoryManager","webComponent","props","bundleInfo","basename","eventBus","exposedDependencies","ldService","logService","WebComponent","disposer","mfeSupportsRerendering","version","elementName","exposedInstanceDependencies","ensureLDVersion","bundledWith","LoadingFallback","isLoading","setIsLoading","historyManager","handleRef","provide","onReady","onDispose","stringifiedData","JSON","stringify","data","key","undefined","dataAttrs","composeDataAttributes","styleUrls","getStyleUrls","ref","class","className","data-mfe-data","data-mfe-name","Object","fromEntries","entries","map","value","replace","letter","toLowerCase","launchDarkly","urls","css","length","encodeURIComponent"],"mappings":";AAAA,SAASA,QAAQ,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,QAAQ;AAGpD,SAASC,uBAAuB,QAAQ,0BAA0B;AAMlE,SAASC,cAAc,QAAQ,qBAAqB;AACpD,SAASC,cAAc,QAAQ,qBAAqB;AAapD,OAAO,SAASC,aAAaC,KAAwB;QAO7CC;IANJ,MAAM,EAAEC,QAAQ,EAAED,UAAU,EAAEE,QAAQ,EAAEC,mBAAmB,EAAEC,SAAS,EAAEC,UAAU,EAAE,GAAGN;IACvF,MAAM,EAAEO,YAAY,EAAEC,QAAQ,EAAEC,sBAAsB,EAAEC,OAAO,EAAE,GAAGT;IACpE,MAAMU,cAAcd,eAAeI;IAEnC,MAAMW,8BAA8BC,gBAChCb,MAAMY,2BAA2B,GACjCX,0BAAAA,WAAWa,WAAW,cAAtBb,8CAAAA,uBAAwB,CAAC,6BAA6B;IAG1D,OAAO,CAAC,EAAEc,eAAe,EAAE,GAAGf,OAAwB;QAClD,MAAM,CAACgB,WAAWC,aAAa,GAAGtB,SAAS;QAC3C,MAAM,CAACuB,eAAe,GAAGtB,wBAAwBE;QAEjD,MAAMqB,YAAY,CAACpB;YACfA,yBAAAA,mCAAAA,aAAcqB,OAAO,CAAC;gBAClBf;gBACAC;gBACAY;gBACAd;gBACAQ;gBACAT;gBACAD;gBACAmB,SAAS;oBACLJ,aAAa;gBACjB;gBACAK,WAAW;oBACPd;gBACJ;YACJ;QACJ;QAEA,qEAAqE;QACrE,MAAMe,kBAAkB7B,QAAQ,IAAM8B,KAAKC,SAAS,CAACzB,MAAM0B,IAAI,GAAG;YAAC1B,MAAM0B,IAAI;SAAC;QAE9E;;;;;SAKC,GACD,MAAMC,MAAMlB,yBAAyBmB,YAAYL;QACjD,MAAMM,YAAYnC,QAAQ,IAAMoC,sBAAsB9B,MAAM0B,IAAI,GAAG;YAAC1B,MAAM0B,IAAI;SAAC;QAC/E,MAAMK,YAAYC,aAAa/B;QAE/B,qBACI,MAACR;;gBACIuB,2BAAa,KAACD;8BACf,KAACR;oBAEG,8EAA8E;oBAC9E0B,KAAKd;oBACLe,OAAOlC,MAAMmC,SAAS;oBACrB,GAAIJ,aAAa;wBAAE,cAAcA;oBAAU,CAAC;oBAK5C,GAAGF,SAAS;oBACbO,iBAAeb;oBACfc,iBAAe1B;oBACd,GAAID,WAAW;wBAAE,oBAAoBA;oBAAQ,CAAC;mBAZ1CiB;;;IAgBrB;AACJ;AAEA;;;CAGC,GACD,SAASG,sBAAsBJ,OAAuC,CAAC,CAAC;IACpE,OAAOY,OAAOC,WAAW,CACrBD,OAAOE,OAAO,CAACd,MAAMe,GAAG,CAAC,CAAC,CAACd,KAAKe,MAAM,GAAK;YACvC,UAAUf,IAAIgB,OAAO,CAAC,UAAUC,CAAAA,SAAU,MAAMA,OAAOC,WAAW;YAClEH;SACH;AAET;AAEA,SAAS7B,gBACLD,8BAA2D,CAAC,CAAC,EAC7DF,OAAgB;QAEAE;IAAhB,IAAIF,WAAW,GAACE,4CAAAA,4BAA4BkC,YAAY,cAAxClC,gEAAAA,0CAA0CP,SAAS,GAAE;QACjE,OAAO;YAAE,GAAGO,2BAA2B;YAAEkC,cAAc;gBAAEpC;YAAQ;QAAE;IACvE;IACA,OAAOE;AACX;AAEA,SAASoB,aAAa,EAAEe,IAAI,EAA4B;IACpD,IAAIA,KAAKC,GAAG,CAACC,MAAM,EAAE;QACjB,OAAOC,mBAAmB1B,KAAKC,SAAS,CAACsB,KAAKC,GAAG;IACrD;AACJ"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@servicetitan/web-components",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "31.0.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -15,17 +15,17 @@
|
|
|
15
15
|
"src"
|
|
16
16
|
],
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@servicetitan/error-boundary": "
|
|
18
|
+
"@servicetitan/error-boundary": "31.0.0",
|
|
19
19
|
"lodash.get": "~4.4.2",
|
|
20
20
|
"mitt": "~3.0.1",
|
|
21
21
|
"semver": "~7.7.2"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@servicetitan/anvil2": "^1.
|
|
24
|
+
"@servicetitan/anvil2": "^1.37.2",
|
|
25
25
|
"@servicetitan/design-system": "~14.5.3",
|
|
26
|
-
"@servicetitan/launchdarkly-service": "
|
|
27
|
-
"@servicetitan/log-service": "
|
|
28
|
-
"@servicetitan/react-ioc": "
|
|
26
|
+
"@servicetitan/launchdarkly-service": "31.0.0",
|
|
27
|
+
"@servicetitan/log-service": "31.0.0",
|
|
28
|
+
"@servicetitan/react-ioc": "31.0.0",
|
|
29
29
|
"@testing-library/dom": "^10.4.0",
|
|
30
30
|
"@testing-library/jest-dom": "^6.6.3",
|
|
31
31
|
"@testing-library/react": "^16.3.0",
|
|
@@ -41,11 +41,11 @@
|
|
|
41
41
|
"shadow-dom-testing-library": "^1.12.0"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
|
-
"@servicetitan/anvil2": ">=1.
|
|
44
|
+
"@servicetitan/anvil2": ">=1.37.2",
|
|
45
45
|
"@servicetitan/design-system": ">=14.5.3",
|
|
46
|
-
"@servicetitan/launchdarkly-service": "
|
|
47
|
-
"@servicetitan/log-service": "
|
|
48
|
-
"@servicetitan/react-ioc": "
|
|
46
|
+
"@servicetitan/launchdarkly-service": "31.0.0",
|
|
47
|
+
"@servicetitan/log-service": "31.0.0",
|
|
48
|
+
"@servicetitan/react-ioc": "31.0.0",
|
|
49
49
|
"history": "~4.10.1",
|
|
50
50
|
"react": ">=17.0.2",
|
|
51
51
|
"react-dom": ">=17.0.2"
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"cli": {
|
|
68
68
|
"webpack": false
|
|
69
69
|
},
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "c52e188a1217df74052774a2eea6a5126089e3d5"
|
|
71
71
|
}
|
|
@@ -2,6 +2,8 @@ import { FC, useContext } from 'react';
|
|
|
2
2
|
import { TablePopupPropsContext } from '@servicetitan/design-system';
|
|
3
3
|
import { useMFEDataContext, useMFEMetadataContext } from '../contexts';
|
|
4
4
|
|
|
5
|
+
jest.mock('@progress/kendo-licensing', () => ({ validatePackage: jest.fn() }));
|
|
6
|
+
|
|
5
7
|
export const MockComponent: FC<Record<string, any>> = props => {
|
|
6
8
|
const data = useMFEDataContext();
|
|
7
9
|
const metadata = useMFEMetadataContext();
|
|
@@ -945,7 +945,7 @@ describe('[web-components] Loader', () => {
|
|
|
945
945
|
test(`reloads metadata after ${description}`, () => {
|
|
946
946
|
act(() => jest.advanceTimersByTime(delay - 1));
|
|
947
947
|
subject();
|
|
948
|
-
expect(common.getJson).
|
|
948
|
+
expect(common.getJson).not.toHaveBeenCalled();
|
|
949
949
|
|
|
950
950
|
act(() => jest.advanceTimersByTime(1));
|
|
951
951
|
subject();
|
|
@@ -958,7 +958,7 @@ describe('[web-components] Loader', () => {
|
|
|
958
958
|
jest.runOnlyPendingTimers();
|
|
959
959
|
subject();
|
|
960
960
|
|
|
961
|
-
expect(common.getJson).
|
|
961
|
+
expect(common.getJson).not.toHaveBeenCalled();
|
|
962
962
|
});
|
|
963
963
|
}
|
|
964
964
|
|
|
@@ -968,7 +968,7 @@ describe('[web-components] Loader', () => {
|
|
|
968
968
|
test('uses cached metadata', () => {
|
|
969
969
|
subject();
|
|
970
970
|
|
|
971
|
-
expect(common.getJson).
|
|
971
|
+
expect(common.getJson).not.toHaveBeenCalled();
|
|
972
972
|
});
|
|
973
973
|
|
|
974
974
|
itReloadsMetadataAfter(1000 * 60 * 15, 'fifteen minutes');
|
package/src/event-bus.ts
CHANGED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import '@testing-library/jest-dom';
|
|
2
|
-
export function expectStylesInDom(styleUrls, shadowRootFn) {
|
|
3
|
-
[styleUrls].flat().forEach(styleUrl => {
|
|
4
|
-
const link = shadowRootFn().querySelector(`link[href='${styleUrl}'][rel='stylesheet'][crossorigin='anonymous']`);
|
|
5
|
-
expect(link).toBeInTheDocument();
|
|
6
|
-
});
|
|
7
|
-
expect(shadowRootFn().querySelectorAll('link').length).toBe([styleUrls].flat().length);
|
|
8
|
-
}
|
|
9
|
-
//# sourceMappingURL=expect-styles-in-dom.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"expect-styles-in-dom.js","sourceRoot":"","sources":["../../src/__mocks__/expect-styles-in-dom.ts"],"names":[],"mappings":"AAAA,OAAO,2BAA2B,CAAC;AAEnC,MAAM,UAAU,iBAAiB,CAAC,SAA4B,EAAE,YAA8B;IAC1F,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;QAClC,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC,aAAa,CACrC,cAAc,QAAQ,+CAA+C,CACxE,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,CAAC,iBAAiB,EAAE,CAAC;IACrC,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,YAAY,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC;AAC3F,CAAC"}
|
package/dist/__mocks__/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/__mocks__/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export function registerComponent(TestComponent, componentName, options) {
|
|
2
|
-
/*
|
|
3
|
-
* This register can only happen once, unfortunately. So the TestComponent needs to
|
|
4
|
-
* work for all tests. If ran more than once, window.customElements.define will throw
|
|
5
|
-
* the error: "NotSupportedError: This name has already been registered in the registry."
|
|
6
|
-
*
|
|
7
|
-
* Also note that there is not way to "unregister" a web component, so an afterAll
|
|
8
|
-
* cannot be used.
|
|
9
|
-
*/
|
|
10
|
-
global.WEB_COMPONENT_NAME = componentName;
|
|
11
|
-
const { register } = require('../register');
|
|
12
|
-
register(TestComponent, true, options);
|
|
13
|
-
}
|
|
14
|
-
//# sourceMappingURL=register-component.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"register-component.js","sourceRoot":"","sources":["../../src/__mocks__/register-component.tsx"],"names":[],"mappings":"AAGA,MAAM,UAAU,iBAAiB,CAC7B,aAAgC,EAChC,aAAiC,EACjC,OAAyB;IAEzB;;;;;;;OAOG;IACF,MAAc,CAAC,kBAAkB,GAAG,aAAa,CAAC;IACnD,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAC5C,QAAQ,CAAC,aAAa,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAC3C,CAAC"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useContext } from 'react';
|
|
3
|
-
import { TablePopupPropsContext } from '@servicetitan/design-system';
|
|
4
|
-
import { useMFEDataContext, useMFEMetadataContext } from '../contexts';
|
|
5
|
-
export const MockComponent = props => {
|
|
6
|
-
const data = useMFEDataContext();
|
|
7
|
-
const metadata = useMFEMetadataContext();
|
|
8
|
-
const popupProps = useContext(TablePopupPropsContext);
|
|
9
|
-
const appendTo = popupProps === null || popupProps === void 0 ? void 0 : popupProps({}).appendTo;
|
|
10
|
-
return (_jsxs("div", { children: [Object.entries(props).map(([name, value]) => (_jsx("span", { children: `Prop: ${name}, Value: ${stringifyValue(value)}` }, name))), Object.entries(data).map(([name, value]) => (_jsx("span", { children: `Data: ${name}, Value: ${stringifyValue(value)}` }, name))), Object.entries(metadata).map(([name, value]) => (_jsx("span", { children: `Metadata: ${name}, Value: ${stringifyValue(value)}` }, name))), _jsxs("span", { children: ["TablePopupPropsContext appendTo: ", String(appendTo)] })] }));
|
|
11
|
-
};
|
|
12
|
-
function stringifyValue(value) {
|
|
13
|
-
return JSON.stringify(value, (_key, value) => value instanceof ShadowRoot ? 'ShadowRoot' : value);
|
|
14
|
-
}
|
|
15
|
-
//# sourceMappingURL=test-component.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"test-component.js","sourceRoot":"","sources":["../../src/__mocks__/test-component.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAM,UAAU,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEvE,MAAM,CAAC,MAAM,aAAa,GAA4B,KAAK,CAAC,EAAE;IAC1D,MAAM,IAAI,GAAG,iBAAiB,EAAE,CAAC;IACjC,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAC;IACzC,MAAM,UAAU,GAAG,UAAU,CAAC,sBAAsB,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAG,EAAE,EAAE,QAAQ,CAAC;IAE3C,OAAO,CACH,0BACK,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAC1C,yBAAkB,SAAS,IAAI,YAAY,cAAc,CAAC,KAAK,CAAC,EAAE,IAAvD,IAAI,CAA2D,CAC7E,CAAC,EACD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CACzC,yBAAkB,SAAS,IAAI,YAAY,cAAc,CAAC,KAAK,CAAC,EAAE,IAAvD,IAAI,CAA2D,CAC7E,CAAC,EACD,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAC7C,yBAAkB,aAAa,IAAI,YAAY,cAAc,CAAC,KAAK,CAAC,EAAE,IAA3D,IAAI,CAA+D,CACjF,CAAC,EAEF,gEAAwC,MAAM,CAAC,QAAQ,CAAC,IAAQ,IAC9D,CACT,CAAC;AACN,CAAC,CAAC;AAEF,SAAS,cAAc,CAAC,KAAU;IAC9B,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACzC,KAAK,YAAY,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CACrD,CAAC;AACN,CAAC"}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { renderHook } from '@testing-library/react';
|
|
3
|
-
import { MFEDataContext, useMFEDataContext } from '../mfe-data-context';
|
|
4
|
-
describe(`[web-components] ${useMFEDataContext.name}`, () => {
|
|
5
|
-
const subject = (wrapper) => renderHook(() => useMFEDataContext(), { wrapper });
|
|
6
|
-
describe('when the MFEDataContext is provided by a parent', () => {
|
|
7
|
-
const data = { foo: 'bar' };
|
|
8
|
-
const Wrapper = ({ children }) => {
|
|
9
|
-
return _jsx(MFEDataContext.Provider, { value: data, children: children });
|
|
10
|
-
};
|
|
11
|
-
test('returns the context', () => {
|
|
12
|
-
expect(subject(Wrapper).result.current).toEqual(data);
|
|
13
|
-
});
|
|
14
|
-
});
|
|
15
|
-
describe('when the MFEDataContext is not provided by a parent', () => {
|
|
16
|
-
const Wrapper = ({ children }) => {
|
|
17
|
-
return _jsx("div", { children: children });
|
|
18
|
-
};
|
|
19
|
-
test('returns an empty object', () => {
|
|
20
|
-
expect(subject(Wrapper).result.current).toEqual({});
|
|
21
|
-
});
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
//# sourceMappingURL=mfe-data-context.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mfe-data-context.test.js","sourceRoot":"","sources":["../../../src/contexts/tests/mfe-data-context.test.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExE,QAAQ,CAAC,oBAAoB,iBAAiB,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE;IACxD,MAAM,OAAO,GAAG,CAAC,OAAY,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,iBAAiB,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IAErF,QAAQ,CAAC,iDAAiD,EAAE,GAAG,EAAE;QAC7D,MAAM,IAAI,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;QAC5B,MAAM,OAAO,GAA0B,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;YACpD,OAAO,KAAC,cAAc,CAAC,QAAQ,IAAC,KAAK,EAAE,IAAI,YAAG,QAAQ,GAA2B,CAAC;QACtF,CAAC,CAAC;QAEF,IAAI,CAAC,qBAAqB,EAAE,GAAG,EAAE;YAC7B,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,qDAAqD,EAAE,GAAG,EAAE;QACjE,MAAM,OAAO,GAA0B,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;YACpD,OAAO,wBAAM,QAAQ,GAAO,CAAC;QACjC,CAAC,CAAC;QAEF,IAAI,CAAC,yBAAyB,EAAE,GAAG,EAAE;YACjC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { renderHook } from '@testing-library/react';
|
|
3
|
-
import { MFEMetadataContext, useMFEMetadataContext } from '../mfe-metadata-context';
|
|
4
|
-
describe(`[web-components] ${useMFEMetadataContext.name}`, () => {
|
|
5
|
-
const subject = (wrapper) => renderHook(() => useMFEMetadataContext(), { wrapper });
|
|
6
|
-
describe('when the MFEMetadataContext is provided by a parent', () => {
|
|
7
|
-
const shadowRoot = document.createElement('div').attachShadow({ mode: 'open' });
|
|
8
|
-
const portalShadowRoot = document.createElement('span').attachShadow({ mode: 'open' });
|
|
9
|
-
const metadata = { shadowRoot, portalShadowRoot };
|
|
10
|
-
const Wrapper = ({ children }) => {
|
|
11
|
-
return (_jsx(MFEMetadataContext.Provider, { value: metadata, children: children }));
|
|
12
|
-
};
|
|
13
|
-
test('returns the context', () => {
|
|
14
|
-
expect(subject(Wrapper).result.current).toEqual(metadata);
|
|
15
|
-
});
|
|
16
|
-
});
|
|
17
|
-
describe('when the MFEMetadataContext is not provided by a parent', () => {
|
|
18
|
-
const Wrapper = ({ children }) => {
|
|
19
|
-
return _jsx("div", { children: children });
|
|
20
|
-
};
|
|
21
|
-
test('returns an empty object', () => {
|
|
22
|
-
expect(subject(Wrapper).result.current).toEqual({});
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
//# sourceMappingURL=mfe-metadata-context.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mfe-metadata-context.test.js","sourceRoot":"","sources":["../../../src/contexts/tests/mfe-metadata-context.test.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEpF,QAAQ,CAAC,oBAAoB,qBAAqB,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE;IAC5D,MAAM,OAAO,GAAG,CAAC,OAAY,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,qBAAqB,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IAEzF,QAAQ,CAAC,qDAAqD,EAAE,GAAG,EAAE;QACjE,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QAChF,MAAM,gBAAgB,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QACvF,MAAM,QAAQ,GAAG,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAAC;QAClD,MAAM,OAAO,GAA0B,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;YACpD,OAAO,CACH,KAAC,kBAAkB,CAAC,QAAQ,IAAC,KAAK,EAAE,QAAQ,YACvC,QAAQ,GACiB,CACjC,CAAC;QACN,CAAC,CAAC;QAEF,IAAI,CAAC,qBAAqB,EAAE,GAAG,EAAE;YAC7B,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACrE,MAAM,OAAO,GAA0B,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;YACpD,OAAO,wBAAM,QAAQ,GAAO,CAAC;QACjC,CAAC,CAAC;QAEF,IAAI,CAAC,yBAAyB,EAAE,GAAG,EAAE;YACjC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
|