@hubspot/ui-extensions 0.11.0 → 0.11.2
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/__synced__/experimental/types.synced.d.ts +3 -4
- package/dist/__synced__/remoteComponents.synced.d.ts +168 -355
- package/dist/__synced__/remoteComponents.synced.js +186 -83
- package/dist/__synced__/types/components/button.synced.d.ts +6 -0
- package/dist/__synced__/types/components/index.synced.d.ts +38 -38
- package/dist/__synced__/types/index.synced.d.ts +7 -7
- package/dist/__synced__/types/index.synced.js +1 -9
- package/dist/__synced__/types/shared.synced.d.ts +2 -3
- package/dist/__synced__/utils/remote-component-registry.synced.d.ts +80 -0
- package/dist/__synced__/utils/remote-component-registry.synced.js +64 -0
- package/dist/__tests__/crm/hooks/useAssociations.spec.js +33 -29
- package/dist/__tests__/crm/hooks/useCrmProperties.spec.js +19 -18
- package/dist/__tests__/crm/utils/fetchAssociations.spec.js +8 -7
- package/dist/__tests__/crm/utils/fetchCrmProperties.spec.js +34 -33
- package/dist/crm/index.d.ts +1 -1
- package/dist/crm/index.js +1 -1
- package/dist/experimental/index.d.ts +1 -1
- package/dist/experimental/index.js +1 -1
- package/dist/experimental/testing/__tests__/debug.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/debug.spec.js +43 -0
- package/dist/experimental/testing/__tests__/find.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/find.spec.js +33 -0
- package/dist/experimental/testing/__tests__/findAll.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/findAll.spec.js +12 -0
- package/dist/experimental/testing/__tests__/findAllChildren.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/findAllChildren.spec.js +48 -0
- package/dist/experimental/testing/__tests__/findChild.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/findChild.spec.js +29 -0
- package/dist/experimental/testing/__tests__/fragments.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/fragments.spec.js +59 -0
- package/dist/experimental/testing/__tests__/invalid-components.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/invalid-components.spec.js +88 -0
- package/dist/experimental/testing/__tests__/isMatch.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/isMatch.spec.js +60 -0
- package/dist/experimental/testing/__tests__/maybeFind.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/maybeFind.spec.js +58 -0
- package/dist/experimental/testing/__tests__/maybeFindChild.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/maybeFindChild.spec.js +65 -0
- package/dist/experimental/testing/__tests__/trigger.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/trigger.spec.js +40 -0
- package/dist/experimental/testing/__tests__/type-utils.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/type-utils.spec.js +163 -0
- package/dist/experimental/testing/__tests__/waitFor.spec.d.ts +1 -0
- package/dist/experimental/testing/__tests__/waitFor.spec.js +55 -0
- package/dist/experimental/testing/index.d.ts +3 -0
- package/dist/experimental/testing/index.js +3 -0
- package/dist/experimental/testing/internal/constants.d.ts +2 -0
- package/dist/experimental/testing/internal/constants.js +1 -0
- package/dist/experimental/testing/internal/convert.d.ts +10 -0
- package/dist/experimental/testing/internal/convert.js +131 -0
- package/dist/experimental/testing/internal/debug.d.ts +8 -0
- package/dist/experimental/testing/internal/debug.js +19 -0
- package/dist/experimental/testing/internal/document.d.ts +14 -0
- package/dist/experimental/testing/internal/document.js +37 -0
- package/dist/experimental/testing/internal/element.d.ts +11 -0
- package/dist/experimental/testing/internal/element.js +67 -0
- package/dist/experimental/testing/internal/errors.d.ts +56 -0
- package/dist/experimental/testing/internal/errors.js +70 -0
- package/dist/experimental/testing/internal/fragment.d.ts +8 -0
- package/dist/experimental/testing/internal/fragment.js +44 -0
- package/dist/experimental/testing/internal/match.d.ts +19 -0
- package/dist/experimental/testing/internal/match.js +42 -0
- package/dist/experimental/testing/internal/print.d.ts +6 -0
- package/dist/experimental/testing/internal/print.js +114 -0
- package/dist/experimental/testing/internal/query.d.ts +57 -0
- package/dist/experimental/testing/internal/query.js +213 -0
- package/dist/experimental/testing/internal/root.d.ts +8 -0
- package/dist/experimental/testing/internal/root.js +44 -0
- package/dist/experimental/testing/internal/text.d.ts +9 -0
- package/dist/experimental/testing/internal/text.js +16 -0
- package/dist/experimental/testing/internal/utils/promise-utils.d.ts +14 -0
- package/dist/experimental/testing/internal/utils/promise-utils.js +14 -0
- package/dist/experimental/testing/render.d.ts +9 -0
- package/dist/experimental/testing/render.js +155 -0
- package/dist/experimental/testing/types.d.ts +2 -1
- package/dist/hubspot.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/pages/home/index.d.ts +1 -1
- package/dist/pages/home/index.js +1 -1
- package/package.json +19 -16
- package/dist/__synced__/appHomeRemoteComponents.synced.d.ts +0 -28
- package/dist/__synced__/appHomeRemoteComponents.synced.js +0 -21
- package/dist/__synced__/crmRemoteComponents.synced.d.ts +0 -66
- package/dist/__synced__/crmRemoteComponents.synced.js +0 -15
- package/dist/__synced__/experimentalRemoteComponents.synced.d.ts +0 -94
- package/dist/__synced__/experimentalRemoteComponents.synced.js +0 -56
- package/dist/coreComponents.d.ts +0 -848
- package/dist/coreComponents.js +0 -582
- package/dist/experimental/types.d.ts +0 -240
- package/dist/experimental/types.js +0 -5
- package/dist/types.d.ts +0 -3214
- package/dist/types.js +0 -244
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { RenderedDocumentInternal, RenderedRootNodeInternal } from './types-internal';
|
|
2
|
+
export interface CreateDocumentOptions {
|
|
3
|
+
/**
|
|
4
|
+
* A function that can be called to get the latest rendered root node.
|
|
5
|
+
*/
|
|
6
|
+
getLatestRootNode: () => RenderedRootNodeInternal;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Creates a rendered document.
|
|
10
|
+
*
|
|
11
|
+
* @param options Options for creating the document.
|
|
12
|
+
* @returns A rendered document.
|
|
13
|
+
*/
|
|
14
|
+
export declare const createDocument: (options: CreateDocumentOptions) => RenderedDocumentInternal;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { act as reactAct } from 'react';
|
|
2
|
+
import { InvalidComponentsError } from './errors';
|
|
3
|
+
/**
|
|
4
|
+
* Creates a rendered document.
|
|
5
|
+
*
|
|
6
|
+
* @param options Options for creating the document.
|
|
7
|
+
* @returns A rendered document.
|
|
8
|
+
*/
|
|
9
|
+
export const createDocument = (options) => {
|
|
10
|
+
const { getLatestRootNode } = options;
|
|
11
|
+
const invalidComponentNames = new Set();
|
|
12
|
+
const document = {
|
|
13
|
+
rootNode: null,
|
|
14
|
+
batchUpdate: (run) => {
|
|
15
|
+
reactAct(run);
|
|
16
|
+
const latestRootNode = getLatestRootNode();
|
|
17
|
+
if (latestRootNode.document.hasInvalidComponentNames()) {
|
|
18
|
+
throw new InvalidComponentsError(latestRootNode);
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
addInvalidComponentName: (name) => {
|
|
22
|
+
invalidComponentNames.add(name);
|
|
23
|
+
},
|
|
24
|
+
getInvalidComponentNames: () => {
|
|
25
|
+
if (invalidComponentNames.size === 0) {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
const invalidComponentNamesArray = [...invalidComponentNames];
|
|
29
|
+
invalidComponentNamesArray.sort();
|
|
30
|
+
return invalidComponentNamesArray;
|
|
31
|
+
},
|
|
32
|
+
hasInvalidComponentNames: () => {
|
|
33
|
+
return invalidComponentNames.size > 0;
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
return document;
|
|
37
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { UnknownComponentProps } from '../../../__synced__/types/shared.synced';
|
|
2
|
+
import type { RenderedDocumentInternal, RenderedElementNodeInternal } from './types-internal';
|
|
3
|
+
/**
|
|
4
|
+
* Creates a rendered element node.
|
|
5
|
+
*
|
|
6
|
+
* @param document The document that the element belongs to.
|
|
7
|
+
* @param name The name of the element.
|
|
8
|
+
* @param props The props of the element.
|
|
9
|
+
* @returns A rendered element node.
|
|
10
|
+
*/
|
|
11
|
+
export declare const createElementNode: (document: RenderedDocumentInternal, name: string, props: UnknownComponentProps) => RenderedElementNodeInternal;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { RenderedNodeType } from '../types';
|
|
2
|
+
import { EMPTY_CHILDREN } from './constants';
|
|
3
|
+
import { debugLog } from './debug';
|
|
4
|
+
import { InvalidEventFunctionError, MissingEventFunctionError } from './errors';
|
|
5
|
+
import { printNode } from './print';
|
|
6
|
+
import { find, findAll, findAllChildren, findChild, maybeFind, maybeFindChild, } from './query';
|
|
7
|
+
/**
|
|
8
|
+
* Creates a rendered element node.
|
|
9
|
+
*
|
|
10
|
+
* @param document The document that the element belongs to.
|
|
11
|
+
* @param name The name of the element.
|
|
12
|
+
* @param props The props of the element.
|
|
13
|
+
* @returns A rendered element node.
|
|
14
|
+
*/
|
|
15
|
+
export const createElementNode = (document, name, props) => {
|
|
16
|
+
const elementNode = {
|
|
17
|
+
nodeType: RenderedNodeType.Element,
|
|
18
|
+
name,
|
|
19
|
+
props,
|
|
20
|
+
text: null,
|
|
21
|
+
children: EMPTY_CHILDREN,
|
|
22
|
+
document,
|
|
23
|
+
debugLog: (label) => {
|
|
24
|
+
debugLog(elementNode, label);
|
|
25
|
+
},
|
|
26
|
+
find: (targetComponent, matcher) => {
|
|
27
|
+
return find(elementNode, targetComponent, matcher);
|
|
28
|
+
},
|
|
29
|
+
findAll: (targetComponent, matcher) => {
|
|
30
|
+
return findAll(elementNode, targetComponent, matcher);
|
|
31
|
+
},
|
|
32
|
+
findChild: (targetComponent, matcher) => {
|
|
33
|
+
return findChild(elementNode, targetComponent, matcher);
|
|
34
|
+
},
|
|
35
|
+
findAllChildren: (targetComponent, matcher) => {
|
|
36
|
+
return findAllChildren(elementNode, targetComponent, matcher);
|
|
37
|
+
},
|
|
38
|
+
maybeFind: (targetComponent, matcher) => {
|
|
39
|
+
return maybeFind(elementNode, targetComponent, matcher);
|
|
40
|
+
},
|
|
41
|
+
maybeFindChild: (targetComponent, matcher) => {
|
|
42
|
+
return maybeFindChild(elementNode, targetComponent, matcher);
|
|
43
|
+
},
|
|
44
|
+
toString: () => {
|
|
45
|
+
return printNode(elementNode);
|
|
46
|
+
},
|
|
47
|
+
trigger: (eventPropName, eventArg) => {
|
|
48
|
+
const eventFunction = elementNode.props[eventPropName];
|
|
49
|
+
if (!eventFunction) {
|
|
50
|
+
throw new MissingEventFunctionError({
|
|
51
|
+
componentName: name,
|
|
52
|
+
eventPropName,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (typeof eventFunction !== 'function') {
|
|
56
|
+
throw new InvalidEventFunctionError({
|
|
57
|
+
componentName: name,
|
|
58
|
+
eventPropName,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
document.batchUpdate(() => {
|
|
62
|
+
eventFunction(eventArg);
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
return elementNode;
|
|
67
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { RenderedParentNode } from '../types';
|
|
2
|
+
import { RenderedRootNodeInternal } from './types-internal';
|
|
3
|
+
/**
|
|
4
|
+
* Thrown when trying to trigger an event that has a handler prop that is not a function.
|
|
5
|
+
*/
|
|
6
|
+
export declare class InvalidEventFunctionError extends Error {
|
|
7
|
+
constructor({ componentName, eventPropName, }: {
|
|
8
|
+
componentName: string;
|
|
9
|
+
eventPropName: string;
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Thrown when trying to trigger an event that has no corresponding handler function in the props object.
|
|
14
|
+
*/
|
|
15
|
+
export declare class MissingEventFunctionError extends Error {
|
|
16
|
+
constructor({ componentName, eventPropName, }: {
|
|
17
|
+
componentName: string;
|
|
18
|
+
eventPropName: string;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Thrown when a component is not found in the rendered output.
|
|
23
|
+
*/
|
|
24
|
+
export declare class ComponentNotFoundError extends Error {
|
|
25
|
+
constructor({ findMethodName, parentNode, componentName, }: {
|
|
26
|
+
findMethodName: string;
|
|
27
|
+
parentNode: RenderedParentNode;
|
|
28
|
+
componentName: string;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Thrown when invalid components are detected in the rendered output.
|
|
33
|
+
*/
|
|
34
|
+
export declare class InvalidComponentsError extends Error {
|
|
35
|
+
constructor(rootNode: RenderedRootNodeInternal);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Thrown when the target component passed to the find operation is not a valid HubSpot-provided React component.
|
|
39
|
+
*/
|
|
40
|
+
export declare class FindInvalidComponentError extends Error {
|
|
41
|
+
constructor({ findMethodName }: {
|
|
42
|
+
findMethodName: string;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Thrown when a fragment prop array is detected in the rendered output.
|
|
47
|
+
*/
|
|
48
|
+
export declare class InvalidFragmentPropArrayError extends Error {
|
|
49
|
+
constructor(componentName: string, propName: string);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Thrown when a waitFor() check doesn't pass within the timeout period.
|
|
53
|
+
*/
|
|
54
|
+
export declare class WaitForTimeoutError extends Error {
|
|
55
|
+
constructor(timeout: number);
|
|
56
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { printNode } from './print';
|
|
2
|
+
/**
|
|
3
|
+
* Thrown when trying to trigger an event that has a handler prop that is not a function.
|
|
4
|
+
*/
|
|
5
|
+
export class InvalidEventFunctionError extends Error {
|
|
6
|
+
constructor({ componentName, eventPropName, }) {
|
|
7
|
+
super(`trigger("${String(eventPropName)}", ...) failed. Event function for prop "${String(eventPropName)}" in component "${componentName}" props is not a function`);
|
|
8
|
+
this.name = 'InvalidEventFunctionError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Thrown when trying to trigger an event that has no corresponding handler function in the props object.
|
|
13
|
+
*/
|
|
14
|
+
export class MissingEventFunctionError extends Error {
|
|
15
|
+
constructor({ componentName, eventPropName, }) {
|
|
16
|
+
super(`trigger("${String(eventPropName)}", ...) failed. Event function for prop "${String(eventPropName)}" not found in component "${componentName}" props`);
|
|
17
|
+
this.name = 'MissingEventFunctionError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Thrown when a component is not found in the rendered output.
|
|
22
|
+
*/
|
|
23
|
+
export class ComponentNotFoundError extends Error {
|
|
24
|
+
constructor({ findMethodName, parentNode, componentName, }) {
|
|
25
|
+
super(`${findMethodName}() failed. <${componentName}> not found in rendered output: ${parentNode.toString()}`);
|
|
26
|
+
this.name = 'ComponentNotFoundError';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Thrown when invalid components are detected in the rendered output.
|
|
31
|
+
*/
|
|
32
|
+
export class InvalidComponentsError extends Error {
|
|
33
|
+
constructor(rootNode) {
|
|
34
|
+
super(`Invalid rendered output. Found invalid components (${rootNode.document
|
|
35
|
+
.getInvalidComponentNames()
|
|
36
|
+
.map((name) => `"${name}"`)
|
|
37
|
+
.join(', ')}) in rendered output: ${printNode(rootNode, {
|
|
38
|
+
markInvalidComponents: true,
|
|
39
|
+
listInvalidComponents: true,
|
|
40
|
+
})}`);
|
|
41
|
+
this.name = 'InvalidComponentsError';
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Thrown when the target component passed to the find operation is not a valid HubSpot-provided React component.
|
|
46
|
+
*/
|
|
47
|
+
export class FindInvalidComponentError extends Error {
|
|
48
|
+
constructor({ findMethodName }) {
|
|
49
|
+
super(`${findMethodName}() failed. The provided target component is not a HubSpot-provided React component`);
|
|
50
|
+
this.name = 'FindInvalidComponentError';
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Thrown when a fragment prop array is detected in the rendered output.
|
|
55
|
+
*/
|
|
56
|
+
export class InvalidFragmentPropArrayError extends Error {
|
|
57
|
+
constructor(componentName, propName) {
|
|
58
|
+
super(`Invalid rendered output. Invalid fragment prop array ${propName} for component ${componentName}. Arrays are not allowed for fragment props.`);
|
|
59
|
+
this.name = 'InvalidFragmentPropArrayError';
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Thrown when a waitFor() check doesn't pass within the timeout period.
|
|
64
|
+
*/
|
|
65
|
+
export class WaitForTimeoutError extends Error {
|
|
66
|
+
constructor(timeout) {
|
|
67
|
+
super(`waitFor() failed. Timeout of ${timeout}ms exceeded waiting for check to pass`);
|
|
68
|
+
this.name = 'WaitForTimeoutError';
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RenderedDocumentInternal, RenderedFragmentNodeInternal } from './types-internal';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a rendered fragment node.
|
|
4
|
+
*
|
|
5
|
+
* @param document The document that the fragment belongs to.
|
|
6
|
+
* @returns A rendered fragment node.
|
|
7
|
+
*/
|
|
8
|
+
export declare const createFragmentNode: (document: RenderedDocumentInternal) => RenderedFragmentNodeInternal;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { RenderedNodeType } from '../types';
|
|
2
|
+
import { EMPTY_CHILDREN } from './constants';
|
|
3
|
+
import { debugLog } from './debug';
|
|
4
|
+
import { printNode } from './print';
|
|
5
|
+
import { find, findAll, findAllChildren, findChild, maybeFind, maybeFindChild, } from './query';
|
|
6
|
+
/**
|
|
7
|
+
* Creates a rendered fragment node.
|
|
8
|
+
*
|
|
9
|
+
* @param document The document that the fragment belongs to.
|
|
10
|
+
* @returns A rendered fragment node.
|
|
11
|
+
*/
|
|
12
|
+
export const createFragmentNode = (document) => {
|
|
13
|
+
const fragmentNode = {
|
|
14
|
+
nodeType: RenderedNodeType.Fragment,
|
|
15
|
+
text: null,
|
|
16
|
+
children: EMPTY_CHILDREN,
|
|
17
|
+
document,
|
|
18
|
+
debugLog: (label) => {
|
|
19
|
+
debugLog(fragmentNode, label);
|
|
20
|
+
},
|
|
21
|
+
find: (targetComponent, matcher) => {
|
|
22
|
+
return find(fragmentNode, targetComponent, matcher);
|
|
23
|
+
},
|
|
24
|
+
findAll: (targetComponent, matcher) => {
|
|
25
|
+
return findAll(fragmentNode, targetComponent, matcher);
|
|
26
|
+
},
|
|
27
|
+
findChild: (targetComponent, matcher) => {
|
|
28
|
+
return findChild(fragmentNode, targetComponent, matcher);
|
|
29
|
+
},
|
|
30
|
+
findAllChildren: (targetComponent, matcher) => {
|
|
31
|
+
return findAllChildren(fragmentNode, targetComponent, matcher);
|
|
32
|
+
},
|
|
33
|
+
maybeFind: (targetComponent, matcher) => {
|
|
34
|
+
return maybeFind(fragmentNode, targetComponent, matcher);
|
|
35
|
+
},
|
|
36
|
+
maybeFindChild: (targetComponent, matcher) => {
|
|
37
|
+
return maybeFindChild(fragmentNode, targetComponent, matcher);
|
|
38
|
+
},
|
|
39
|
+
toString: () => {
|
|
40
|
+
return printNode(fragmentNode);
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
return fragmentNode;
|
|
44
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { HubSpotReactComponent, UnknownComponentProps } from '../../../__synced__/types/shared.synced';
|
|
2
|
+
import { ElementMatcher, RenderedElementNode, RenderedNode } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Checks if the element matches the matcher.
|
|
5
|
+
*
|
|
6
|
+
* @param element The element to check.
|
|
7
|
+
* @param matcher An optional matcher to filter the elements.
|
|
8
|
+
* @returns `true` if the element matches the matcher, `false` otherwise.
|
|
9
|
+
*/
|
|
10
|
+
export declare const checkElementMatches: <TProps extends UnknownComponentProps>(element: RenderedElementNode<TProps>, matcher?: ElementMatcher<TProps> | undefined) => boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Checks if the node matches the component and matcher.
|
|
13
|
+
*
|
|
14
|
+
* @param node The node to check.
|
|
15
|
+
* @param component The component to check.
|
|
16
|
+
* @param matcher An optional matcher to filter the elements.
|
|
17
|
+
* @returns Whether the node matches the component and matcher.
|
|
18
|
+
*/
|
|
19
|
+
export declare const isMatch: <TComponentProps extends UnknownComponentProps>(node: RenderedNode | null | undefined, component: HubSpotReactComponent<TComponentProps>, matcher?: ElementMatcher<TComponentProps> | undefined) => node is RenderedElementNode<TComponentProps>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { RenderedNodeType, } from '../types';
|
|
2
|
+
import { __hubSpotComponentRegistry } from '../../../__synced__/remoteComponents.synced';
|
|
3
|
+
/**
|
|
4
|
+
* Checks if the element matches the matcher.
|
|
5
|
+
*
|
|
6
|
+
* @param element The element to check.
|
|
7
|
+
* @param matcher An optional matcher to filter the elements.
|
|
8
|
+
* @returns `true` if the element matches the matcher, `false` otherwise.
|
|
9
|
+
*/
|
|
10
|
+
export const checkElementMatches = (element, matcher) => {
|
|
11
|
+
// If no matcher is provided, the element matches
|
|
12
|
+
if (!matcher) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
// Check if the matcher is a predicate function
|
|
16
|
+
if (typeof matcher === 'function') {
|
|
17
|
+
return matcher(element);
|
|
18
|
+
}
|
|
19
|
+
// Check if all the props in the matcher match the props in the element
|
|
20
|
+
return Object.keys(matcher).every((key) => element.props[key] === matcher[key]);
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Checks if the node matches the component and matcher.
|
|
24
|
+
*
|
|
25
|
+
* @param node The node to check.
|
|
26
|
+
* @param component The component to check.
|
|
27
|
+
* @param matcher An optional matcher to filter the elements.
|
|
28
|
+
* @returns Whether the node matches the component and matcher.
|
|
29
|
+
*/
|
|
30
|
+
export const isMatch = (node, component, matcher) => {
|
|
31
|
+
if (node == null) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
if (node.nodeType !== RenderedNodeType.Element) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
const targetComponentName = __hubSpotComponentRegistry.getComponentName(component);
|
|
38
|
+
if (node.name !== targetComponentName) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
return checkElementMatches(node, matcher);
|
|
42
|
+
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { __hubSpotComponentRegistry } from '../../../__synced__/remoteComponents.synced';
|
|
2
|
+
import { isRenderedElementNode, isRenderedFragmentNode, isRenderedRootNode, isRenderedTextNode, } from '../type-utils';
|
|
3
|
+
const INDENT_STRING = ' ';
|
|
4
|
+
const printTextNode = (node, indent, printContext) => {
|
|
5
|
+
printContext.append(`${indent}${JSON.stringify(node.text)}\n`);
|
|
6
|
+
};
|
|
7
|
+
const propValueToString = (value) => {
|
|
8
|
+
if (typeof value === 'function') {
|
|
9
|
+
return '={function}';
|
|
10
|
+
}
|
|
11
|
+
else if (typeof value === 'number') {
|
|
12
|
+
return `={${value}}`;
|
|
13
|
+
}
|
|
14
|
+
else if (typeof value === 'string') {
|
|
15
|
+
return `=${JSON.stringify(value)}`;
|
|
16
|
+
}
|
|
17
|
+
else if (typeof value === 'boolean') {
|
|
18
|
+
return value === true ? '' : '={false}';
|
|
19
|
+
}
|
|
20
|
+
return `={${JSON.stringify(value)}}`;
|
|
21
|
+
};
|
|
22
|
+
const printElementProps = (name, props, indent, printContext) => {
|
|
23
|
+
for (const [propName, propValue] of Object.entries(props)) {
|
|
24
|
+
if (__hubSpotComponentRegistry.isComponentFragmentProp(name, propName)) {
|
|
25
|
+
printContext.append(` ${propName}={`);
|
|
26
|
+
printFragmentNode(propValue, indent, printContext);
|
|
27
|
+
printContext.append(`}`);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
printContext.append(` ${propName}${propValueToString(propValue)}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const printElementStart = (node, indent, printContext) => {
|
|
35
|
+
const { name } = node;
|
|
36
|
+
printContext.append(indent);
|
|
37
|
+
printContext.append(`<${name}`);
|
|
38
|
+
if (!__hubSpotComponentRegistry.isAllowedComponentName(name)) {
|
|
39
|
+
printContext.foundInvalidComponents.add(name);
|
|
40
|
+
if (printContext.options.markInvalidComponents) {
|
|
41
|
+
printContext.append('⚠️');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
const printElementNode = (node, indent, printContext) => {
|
|
46
|
+
const hasChildren = node.children.length > 0;
|
|
47
|
+
const { name, props } = node;
|
|
48
|
+
if (hasChildren) {
|
|
49
|
+
printElementStart(node, indent, printContext);
|
|
50
|
+
printElementProps(name, props, indent + INDENT_STRING, printContext);
|
|
51
|
+
printContext.append(`>\n`);
|
|
52
|
+
printChildren(node, indent + INDENT_STRING, printContext);
|
|
53
|
+
printContext.append(`${indent}</${name}>\n`);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
printElementStart(node, indent, printContext);
|
|
57
|
+
printElementProps(name, props, indent + INDENT_STRING, printContext);
|
|
58
|
+
printContext.append(`/>\n`);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const printChildren = (node, indent, printContext) => {
|
|
62
|
+
const { children } = node;
|
|
63
|
+
for (const child of children) {
|
|
64
|
+
if (isRenderedTextNode(child)) {
|
|
65
|
+
printTextNode(child, indent, printContext);
|
|
66
|
+
}
|
|
67
|
+
else if (isRenderedElementNode(child)) {
|
|
68
|
+
printElementNode(child, indent, printContext);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
throw new Error(`Illegal State. Invalid rendered node type: ${child.nodeType}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const DEFAULT_PRINT_OPTIONS = {
|
|
76
|
+
markInvalidComponents: true,
|
|
77
|
+
listInvalidComponents: false,
|
|
78
|
+
};
|
|
79
|
+
const printFragmentNode = (node, indent, printContext) => {
|
|
80
|
+
printContext.append(`<>\n`);
|
|
81
|
+
printChildren(node, indent + INDENT_STRING, printContext);
|
|
82
|
+
printContext.append(`${indent}</>`);
|
|
83
|
+
};
|
|
84
|
+
export const printNode = (rootNode, options = DEFAULT_PRINT_OPTIONS) => {
|
|
85
|
+
const { listInvalidComponents } = options;
|
|
86
|
+
let output = '';
|
|
87
|
+
const printContext = {
|
|
88
|
+
append: (str) => {
|
|
89
|
+
output += str;
|
|
90
|
+
},
|
|
91
|
+
options,
|
|
92
|
+
foundInvalidComponents: new Set(),
|
|
93
|
+
};
|
|
94
|
+
if (isRenderedRootNode(rootNode)) {
|
|
95
|
+
printContext.append(`<>\n`);
|
|
96
|
+
printChildren(rootNode, INDENT_STRING, printContext);
|
|
97
|
+
printContext.append(`</>`);
|
|
98
|
+
}
|
|
99
|
+
else if (isRenderedFragmentNode(rootNode)) {
|
|
100
|
+
printFragmentNode(rootNode, '', printContext);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
printElementNode(rootNode, '', printContext);
|
|
104
|
+
}
|
|
105
|
+
if (listInvalidComponents && printContext.foundInvalidComponents.size > 0) {
|
|
106
|
+
printContext.append(`\n⚠️ Invalid components:\n`);
|
|
107
|
+
const foundInvalidComponents = [...printContext.foundInvalidComponents];
|
|
108
|
+
foundInvalidComponents.sort();
|
|
109
|
+
for (const invalidComponentName of foundInvalidComponents) {
|
|
110
|
+
printContext.append(`- ${invalidComponentName}\n`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return output.replace(/\n$/, '');
|
|
114
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { HubSpotReactComponent, UnknownComponentProps } from '../../../__synced__/types/shared.synced';
|
|
2
|
+
import type { ElementMatcher, RenderedElementNode } from '../types';
|
|
3
|
+
import type { RenderedParentNodeInternal } from './types-internal';
|
|
4
|
+
/**
|
|
5
|
+
* Finds the first descendant element node that matches the given component.
|
|
6
|
+
*
|
|
7
|
+
* @param parentNode The parent node to search in.
|
|
8
|
+
* @param targetComponent The component to find.
|
|
9
|
+
* @param matcher An optional matcher to filter the elements.
|
|
10
|
+
* @returns The first element node that matches the given component or `null` if no match is found.
|
|
11
|
+
*/
|
|
12
|
+
export declare const maybeFind: <TProps extends UnknownComponentProps>(parentNode: RenderedParentNodeInternal, targetComponent: HubSpotReactComponent<TProps>, matcher?: ElementMatcher<TProps> | undefined) => RenderedElementNode<TProps> | null;
|
|
13
|
+
/**
|
|
14
|
+
* Finds the first descendant element node that matches the given component.
|
|
15
|
+
*
|
|
16
|
+
* @param parentNode The parent node to search in.
|
|
17
|
+
* @param targetComponent The component to find.
|
|
18
|
+
* @param matcher An optional matcher to filter the elements.
|
|
19
|
+
* @returns The first element node that matches the given component.
|
|
20
|
+
*/
|
|
21
|
+
export declare const find: <TProps extends UnknownComponentProps>(parentNode: RenderedParentNodeInternal, targetComponent: HubSpotReactComponent<TProps>, matcher?: ElementMatcher<TProps> | undefined) => RenderedElementNode<TProps>;
|
|
22
|
+
/**
|
|
23
|
+
* Finds all descendant element nodes that match the given component.
|
|
24
|
+
*
|
|
25
|
+
* @param parentNode The parent node to search in.
|
|
26
|
+
* @param targetComponent The component to find.
|
|
27
|
+
* @param matcher An optional matcher to filter the elements.
|
|
28
|
+
* @returns An array of element nodes that match the given component.
|
|
29
|
+
*/
|
|
30
|
+
export declare const findAll: <TProps extends UnknownComponentProps>(parentNode: RenderedParentNodeInternal, targetComponent: HubSpotReactComponent<TProps>, matcher?: ElementMatcher<TProps> | undefined) => RenderedElementNode<TProps>[];
|
|
31
|
+
/**
|
|
32
|
+
* Finds the first direct child element node that matches the given component.
|
|
33
|
+
*
|
|
34
|
+
* @param parentNode The parent node to search in.
|
|
35
|
+
* @param targetComponent The component to find.
|
|
36
|
+
* @param matcher An optional matcher to filter the elements.
|
|
37
|
+
* @returns The first child element node that matches the given component.
|
|
38
|
+
*/
|
|
39
|
+
export declare const findChild: <TProps extends UnknownComponentProps>(parentNode: RenderedParentNodeInternal, targetComponent: HubSpotReactComponent<TProps>, matcher?: ElementMatcher<TProps> | undefined) => RenderedElementNode<TProps>;
|
|
40
|
+
/**
|
|
41
|
+
* Finds the first direct child element node that matches the given component.
|
|
42
|
+
*
|
|
43
|
+
* @param parentNode The parent node to search in.
|
|
44
|
+
* @param targetComponent The component to find.
|
|
45
|
+
* @param matcher An optional matcher to filter the elements.
|
|
46
|
+
* @returns The first child element node that matches the given component.
|
|
47
|
+
*/
|
|
48
|
+
export declare const maybeFindChild: <TProps extends UnknownComponentProps>(parentNode: RenderedParentNodeInternal, targetComponent: HubSpotReactComponent<TProps>, matcher?: ElementMatcher<TProps> | undefined) => RenderedElementNode<TProps> | null;
|
|
49
|
+
/**
|
|
50
|
+
* Finds all direct child element nodes that match the given component.
|
|
51
|
+
*
|
|
52
|
+
* @param parentNode The parent node to search in.
|
|
53
|
+
* @param targetComponent The component to find.
|
|
54
|
+
* @param matcher An optional matcher to filter the elements.
|
|
55
|
+
* @returns An array of child element nodes that match the given component.
|
|
56
|
+
*/
|
|
57
|
+
export declare const findAllChildren: <TProps extends UnknownComponentProps>(parentNode: RenderedParentNodeInternal, targetComponent: HubSpotReactComponent<TProps>, matcher?: ElementMatcher<TProps> | undefined) => RenderedElementNode<TProps>[];
|