@itwin/tree-widget-react 1.1.0 → 1.1.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/CHANGELOG.md +15 -1
- package/lib/cjs/components/trees/VisibilityTreeBase.scss +10 -10
- package/lib/cjs/components/trees/VisibilityTreeRenderer.js +1 -1
- package/lib/cjs/components/trees/VisibilityTreeRenderer.js.map +1 -1
- package/lib/cjs/e2e-tests/TreeWidget.test.d.ts +2 -0
- package/lib/cjs/e2e-tests/TreeWidget.test.js +46 -0
- package/lib/cjs/e2e-tests/TreeWidget.test.js.map +1 -0
- package/lib/cjs/e2e-tests/utils.d.ts +8 -0
- package/lib/cjs/e2e-tests/utils.js +40 -0
- package/lib/cjs/e2e-tests/utils.js.map +1 -0
- package/lib/esm/components/trees/VisibilityTreeBase.scss +10 -10
- package/lib/esm/components/trees/VisibilityTreeRenderer.js +1 -1
- package/lib/esm/components/trees/VisibilityTreeRenderer.js.map +1 -1
- package/lib/esm/e2e-tests/TreeWidget.test.d.ts +2 -0
- package/lib/esm/e2e-tests/TreeWidget.test.js +41 -0
- package/lib/esm/e2e-tests/TreeWidget.test.js.map +1 -0
- package/lib/esm/e2e-tests/utils.d.ts +8 -0
- package/lib/esm/e2e-tests/utils.js +30 -0
- package/lib/esm/e2e-tests/utils.js.map +1 -0
- package/package.json +6 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
# Change Log - @itwin/tree-widget-react
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Tue, 22 Aug 2023 14:39:05 GMT and should not be manually modified.
|
|
4
|
+
|
|
5
|
+
## 1.1.2
|
|
6
|
+
Tue, 22 Aug 2023 14:39:05 GMT
|
|
7
|
+
|
|
8
|
+
### Patches
|
|
9
|
+
|
|
10
|
+
- `Trees`: Do not select node when checkbox is clicked.
|
|
11
|
+
|
|
12
|
+
## 1.1.1
|
|
13
|
+
Thu, 17 Aug 2023 14:42:37 GMT
|
|
14
|
+
|
|
15
|
+
### Patches
|
|
16
|
+
|
|
17
|
+
- Trees: Fix eye checkbox background when node is selected and hovered.
|
|
4
18
|
|
|
5
19
|
## 1.1.0
|
|
6
20
|
Mon, 07 Aug 2023 13:36:23 GMT
|
|
@@ -7,30 +7,30 @@
|
|
|
7
7
|
.tree-widget-tree-nodes-list {
|
|
8
8
|
.core-tree-node {
|
|
9
9
|
&.with-checkbox {
|
|
10
|
-
|
|
10
|
+
> .contents {
|
|
11
11
|
padding-left: calc(var(--iui-size-3xs) / 2);
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
&.disable-expander {
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
> .contents {
|
|
17
|
+
> .core-tree-expansionToggle {
|
|
18
18
|
display: none;
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
&.is-selected {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
background-color: var(--iui-color-background-accent-muted)
|
|
24
|
+
> .contents {
|
|
25
|
+
> .visibility-tree-checkbox-container {
|
|
26
|
+
background-color: var(--iui-color-background-accent-muted);
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
.
|
|
32
|
-
|
|
33
|
-
.visibility-tree-checkbox-container {
|
|
31
|
+
&:not(.is-selected) {
|
|
32
|
+
> .contents:hover {
|
|
33
|
+
> .visibility-tree-checkbox-container {
|
|
34
34
|
background-color: var(--iui-color-background-hover);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
.without-expander {
|
|
76
|
-
.visibility-tree-checkbox-container
|
|
76
|
+
.visibility-tree-checkbox-container + * {
|
|
77
77
|
margin-left: var(--enlarged-node-expander-additional-padding);
|
|
78
78
|
}
|
|
79
79
|
}
|
|
@@ -49,7 +49,7 @@ exports.createVisibilityTreeNodeRenderer = createVisibilityTreeNodeRenderer;
|
|
|
49
49
|
* @public
|
|
50
50
|
*/
|
|
51
51
|
function VisibilityTreeNodeCheckbox(props) {
|
|
52
|
-
return (0, jsx_runtime_1.jsx)(itwinui_react_1.Checkbox, { className: "visibility-tree-checkbox", variant: "eyeball", checked: props.checked, onChange: (e) => props.onChange(e.currentTarget.checked), disabled: props.disabled, title: props.title });
|
|
52
|
+
return (0, jsx_runtime_1.jsx)(itwinui_react_1.Checkbox, { className: "visibility-tree-checkbox", variant: "eyeball", checked: props.checked, onChange: (e) => props.onChange(e.currentTarget.checked), onClick: props.onClick, disabled: props.disabled, title: props.title });
|
|
53
53
|
}
|
|
54
54
|
exports.VisibilityTreeNodeCheckbox = VisibilityTreeNodeCheckbox;
|
|
55
55
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VisibilityTreeRenderer.js","sourceRoot":"","sources":["../../../../src/components/trees/VisibilityTreeRenderer.tsx"],"names":[],"mappings":";;;;;;;AAAA;;;+FAG+F;AAE/F,4DAAoC;AACpC,iCAAkC;AAClC,8DAA4E;AAC5E,wDAAgD;AAChD,4EAAwF;AACxF,wDAAqD;AAQrD;;;;;GAKG;AACH,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAoClC;;;GAGG;AACH,SAAgB,4BAA4B,CAAC,EAAE,iBAAiB,EAAE,GAAG,SAAS,EAA+B;IAC3G,OAAO,SAAS,sBAAsB,CAAC,SAA4B;QACjE,OAAO,uBAAC,2BAAY,OAAK,SAAS,KAAM,SAAS,EAAE,YAAY,EAAE,gCAAgC,CAAC,iBAAiB,CAAC,GAAI,CAAC;IAC3H,CAAC,CAAC;AACJ,CAAC;AAJD,oEAIC;AAED,MAAM,WAAW,GAAG,IAAI,kCAAe,EAAE,CAAC;AAE1C;;;GAGG;AACH,SAAgB,gCAAgC,CAAC,EAAE,WAAW,GAAG,EAAE,EAAE,uBAAuB,GAAG,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAmC;IACvK,OAAO,SAAS,0BAA0B,CAAC,aAAoC;QAC7E,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,GAAG,WAAW,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAChI,OAAO,CACL,uBAAC,mCAAgB,OACX,aAAa,EACjB,IAAI,EAAE,EAAE,GAAG,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,EACzD,gBAAgB,EAAE,CAAC,aAAsC,EAAE,EAAE,CAAC,CAC5D,gCAAK,SAAS,EAAC,oCAAoC,EAAC,KAAK,EAAE,EAAE,WAAW,EAAE,GAAG,UAAU,IAAI,EAAE,YAC3F,uBAAC,0BAA0B,OAAK,aAAa,GAAI,GAC7C,CACP,EACD,kBAAkB,EAAE,kBAAkB,EACtC,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,EACnD,SAAS,EAAE,IAAA,oBAAU,EAAC,eAAe,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,KAAK,CAAC,IAAI,CAAC,uBAAuB,IAAI,aAAa,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,IAAI,kBAAkB,EAAE,aAAa,CAAC,SAAS,CAAC,GACvM,CACH,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAlBD,4EAkBC;AAED;;;GAGG;AACH,SAAgB,0BAA0B,CAAC,KAA8B;IACvE,OAAO,uBAAC,wBAAQ,IACd,SAAS,EAAC,0BAA0B,EACpC,OAAO,EAAC,SAAS,EACjB,OAAO,EAAE,KAAK,CAAC,OAAO,EACtB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,EACxD,QAAQ,EAAE,KAAK,CAAC,QAAQ,EACxB,KAAK,EAAE,KAAK,CAAC,KAAK,GAClB,CAAC;AACL,CAAC;
|
|
1
|
+
{"version":3,"file":"VisibilityTreeRenderer.js","sourceRoot":"","sources":["../../../../src/components/trees/VisibilityTreeRenderer.tsx"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\n\nimport classNames from \"classnames\";\nimport { useEffect } from \"react\";\nimport { TreeImageLoader, TreeNodeRenderer } from \"@itwin/components-react\";\nimport { Checkbox } from \"@itwin/itwinui-react\";\nimport { useControlledPresentationTreeFiltering } from \"@itwin/presentation-components\";\nimport { TreeRenderer } from \"./common/TreeRenderer\";\n\nimport type { TreeRendererBaseProps } from \"./common/TreeRenderer\";\nimport type { AbstractTreeNodeLoaderWithProvider, TreeNodeRendererProps, TreeRendererProps } from \"@itwin/components-react\";\nimport type { NodeCheckboxRenderProps } from \"@itwin/core-react\";\nimport type { IPresentationTreeDataProvider } from \"@itwin/presentation-components\";\nimport type { VisibilityTreeFilterInfo } from \"./common/Types\";\n\n/**\n * This constant is taken from `@itwin/core-react`.\n * Defines the size in pixels of the expansion toggle.\n * It is used to keep same hierarchy nodes with children and nodes without children in the same line.\n * @note This value applies only to the leaf nodes.\n */\nconst EXPANSION_TOGGLE_WIDTH = 24;\n\n/**\n * Props for visibility tree renderer.\n * @public\n */\nexport interface VisibilityTreeRendererProps extends TreeRendererBaseProps {\n /** Props for single node renderer. */\n nodeRendererProps: VisibilityTreeNodeRendererProps;\n}\n\n/**\n * Props for visibility tree node renderer.\n * @public\n */\nexport interface VisibilityTreeNodeRendererProps {\n /**\n * Specifies whether the icon at the left of the node label should be rendered.\n */\n iconsEnabled: boolean;\n /**\n * Specifies whether node description should be enabled.\n */\n descriptionEnabled: boolean;\n /**\n * Defines the offset in pixels of how much each hierarchy level should be offset to the right from the checkbox.\n * Defaults to `20`.\n */\n levelOffset?: number;\n /**\n * Specifies whether the root node be expanded at all times.\n * Defaults to `false`.\n */\n disableRootNodeCollapse?: boolean;\n}\n\n/**\n * Creates Visibility tree renderer which renders nodes with eye checkbox.\n * @public\n */\nexport function createVisibilityTreeRenderer({ nodeRendererProps, ...restProps }: VisibilityTreeRendererProps) {\n return function VisibilityTreeRenderer(treeProps: TreeRendererProps) {\n return <TreeRenderer {...treeProps} {...restProps} nodeRenderer={createVisibilityTreeNodeRenderer(nodeRendererProps)} />;\n };\n}\n\nconst imageLoader = new TreeImageLoader();\n\n/**\n * Creates node renderer which renders node with eye checkbox.\n * @public\n */\nexport function createVisibilityTreeNodeRenderer({ levelOffset = 20, disableRootNodeCollapse = false, descriptionEnabled, iconsEnabled }: VisibilityTreeNodeRendererProps) {\n return function VisibilityTreeNodeRenderer(treeNodeProps: TreeNodeRendererProps) {\n const nodeOffset = treeNodeProps.node.depth * levelOffset + (treeNodeProps.node.numChildren === 0 ? EXPANSION_TOGGLE_WIDTH : 0);\n return (\n <TreeNodeRenderer\n {...treeNodeProps}\n node={{ ...treeNodeProps.node, depth: 0, numChildren: 1 }} // if we want to disable TreeNodeRenderer style calculations for tree nodes, we need to override these values.\n checkboxRenderer={(checkboxProps: NodeCheckboxRenderProps) => (\n <div className=\"visibility-tree-checkbox-container\" style={{ marginRight: `${nodeOffset}px` }}>\n <VisibilityTreeNodeCheckbox {...checkboxProps} />\n </div>\n )}\n descriptionEnabled={descriptionEnabled}\n imageLoader={iconsEnabled ? imageLoader : undefined}\n className={classNames(\"with-checkbox\", (treeNodeProps.node.numChildren === 0 || (disableRootNodeCollapse && treeNodeProps.node.parentId === undefined)) && \"disable-expander\", treeNodeProps.className)}\n />\n );\n };\n}\n\n/**\n * Checkbox renderer that renders an eye.\n * @public\n */\nexport function VisibilityTreeNodeCheckbox(props: NodeCheckboxRenderProps) {\n return <Checkbox\n className=\"visibility-tree-checkbox\"\n variant=\"eyeball\"\n checked={props.checked}\n onChange={(e) => props.onChange(e.currentTarget.checked)}\n onClick={props.onClick}\n disabled={props.disabled}\n title={props.title}\n />;\n}\n\n/**\n * Filters data provider used in supplied node loader and invokes onFilterApplied when filtering is completed.\n * @public\n */\nexport function useVisibilityTreeFiltering(\n nodeLoader: AbstractTreeNodeLoaderWithProvider<IPresentationTreeDataProvider>,\n filterInfo?: VisibilityTreeFilterInfo,\n onFilterApplied?: (filteredDataProvider: IPresentationTreeDataProvider, matchesCount: number) => void,\n) {\n const { filter, activeMatchIndex } = filterInfo ?? { filter: undefined, activeMatchIndex: undefined };\n const {\n filteredNodeLoader,\n isFiltering,\n matchesCount,\n nodeHighlightingProps,\n } = useControlledPresentationTreeFiltering({ nodeLoader, filter, activeMatchIndex });\n\n useEffect(\n () => {\n if (filter && matchesCount !== undefined && filteredNodeLoader !== nodeLoader)\n onFilterApplied && onFilterApplied(filteredNodeLoader.dataProvider, matchesCount);\n },\n [filter, matchesCount, nodeLoader, filteredNodeLoader, onFilterApplied],\n );\n\n return { filteredNodeLoader, isFiltering, nodeHighlightingProps };\n}\n\n/**\n * Properties for [[VisibilityTreeNoFilteredData]] component.\n * @public\n */\nexport interface VisibilityTreeNoFilteredDataProps {\n title: string;\n message: string;\n}\n\n/**\n * Renders message that no nodes was found for filter.\n * @public\n */\nexport function VisibilityTreeNoFilteredData(props: VisibilityTreeNoFilteredDataProps) {\n return (\n <div className=\"components-tree-errormessage\">\n <span className=\"errormessage-header\">{props.title}</span>\n <span className=\"errormessage-body\">{props.message}</span>\n </div>\n );\n}\n"]}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const test_1 = require("@playwright/test");
|
|
7
|
+
const assert_1 = __importDefault(require("assert"));
|
|
8
|
+
const utils_1 = require("./utils");
|
|
9
|
+
let treeWidget;
|
|
10
|
+
test_1.test.beforeEach(async ({ page, baseURL }) => {
|
|
11
|
+
(0, assert_1.default)(baseURL);
|
|
12
|
+
await page.goto(baseURL);
|
|
13
|
+
// expand panel size to ~300px
|
|
14
|
+
await (0, utils_1.expandStagePanel)(page, "right", 100);
|
|
15
|
+
treeWidget = (0, utils_1.locateWidget)(page, "tree");
|
|
16
|
+
await treeWidget.waitFor();
|
|
17
|
+
});
|
|
18
|
+
test_1.test.describe("should match image snapshot", () => {
|
|
19
|
+
(0, test_1.test)("initial tree", async () => {
|
|
20
|
+
// wait for element to be visible in the tree
|
|
21
|
+
await (0, utils_1.locateNode)(treeWidget, "ProcessPhysicalModel").getByRole("checkbox", { name: "Visible", exact: true }).waitFor();
|
|
22
|
+
await (0, test_1.expect)(treeWidget).toHaveScreenshot();
|
|
23
|
+
});
|
|
24
|
+
(0, test_1.test)("expanded tree node", async () => {
|
|
25
|
+
const node = (0, utils_1.locateNode)(treeWidget, "ProcessPhysicalModel");
|
|
26
|
+
await node.getByTestId("tree-node-expansion-toggle").click();
|
|
27
|
+
// wait for node at the bottom to be visible/loaded
|
|
28
|
+
await (0, utils_1.locateNode)(treeWidget, "Tag-Category").waitFor();
|
|
29
|
+
await (0, test_1.expect)(treeWidget).toHaveScreenshot();
|
|
30
|
+
});
|
|
31
|
+
(0, test_1.test)("selected node", async () => {
|
|
32
|
+
const node = (0, utils_1.locateNode)(treeWidget, "BayTown");
|
|
33
|
+
await node.click();
|
|
34
|
+
// wait for node to become selected
|
|
35
|
+
await (0, test_1.expect)(node).toHaveClass(/is-selected/);
|
|
36
|
+
await (0, test_1.expect)(treeWidget).toHaveScreenshot();
|
|
37
|
+
});
|
|
38
|
+
(0, test_1.test)("search", async () => {
|
|
39
|
+
await treeWidget.getByText("BayTown").waitFor();
|
|
40
|
+
await treeWidget.getByTitle("Search for something").click();
|
|
41
|
+
await treeWidget.getByPlaceholder("Search...").fill("Model");
|
|
42
|
+
await treeWidget.locator(".components-activehighlight").waitFor();
|
|
43
|
+
await (0, test_1.expect)(treeWidget).toHaveScreenshot();
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
//# sourceMappingURL=TreeWidget.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TreeWidget.test.js","sourceRoot":"","sources":["../../../src/e2e-tests/TreeWidget.test.ts"],"names":[],"mappings":";;;;;AAKA,2CAAgD;AAChD,oDAA4B;AAC5B,mCAAqE;AAErE,IAAI,UAAmB,CAAC;AACxB,WAAI,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE;IAC1C,IAAA,gBAAM,EAAC,OAAO,CAAC,CAAC;IAChB,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzB,8BAA8B;IAC9B,MAAM,IAAA,wBAAgB,EAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;IAC3C,UAAU,GAAG,IAAA,oBAAY,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACxC,MAAM,UAAU,CAAC,OAAO,EAAE,CAAC;AAC7B,CAAC,CAAC,CAAC;AAEH,WAAI,CAAC,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;IAEhD,IAAA,WAAI,EAAC,cAAc,EAAE,KAAK,IAAI,EAAE;QAC9B,6CAA6C;QAC7C,MAAM,IAAA,kBAAU,EAAC,UAAU,EAAE,sBAAsB,CAAC,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;QACvH,MAAM,IAAA,aAAM,EAAC,UAAU,CAAC,CAAC,gBAAgB,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,IAAA,WAAI,EAAC,oBAAoB,EAAE,KAAK,IAAI,EAAE;QACpC,MAAM,IAAI,GAAG,IAAA,kBAAU,EAAC,UAAU,EAAE,sBAAsB,CAAC,CAAC;QAC5D,MAAM,IAAI,CAAC,WAAW,CAAC,4BAA4B,CAAC,CAAC,KAAK,EAAE,CAAC;QAE7D,mDAAmD;QACnD,MAAM,IAAA,kBAAU,EAAC,UAAU,EAAE,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC;QACvD,MAAM,IAAA,aAAM,EAAC,UAAU,CAAC,CAAC,gBAAgB,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,IAAA,WAAI,EAAC,eAAe,EAAE,KAAK,IAAI,EAAE;QAC/B,MAAM,IAAI,GAAG,IAAA,kBAAU,EAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAC/C,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QAEnB,mCAAmC;QACnC,MAAM,IAAA,aAAM,EAAC,IAAI,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;QAC9C,MAAM,IAAA,aAAM,EAAC,UAAU,CAAC,CAAC,gBAAgB,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,IAAA,WAAI,EAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QACxB,MAAM,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;QAChD,MAAM,UAAU,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAC,KAAK,EAAE,CAAC;QAC5D,MAAM,UAAU,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7D,MAAM,UAAU,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC,OAAO,EAAE,CAAC;QAClE,MAAM,IAAA,aAAM,EAAC,UAAU,CAAC,CAAC,gBAAgB,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;AAEL,CAAC,CAAC,CAAC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\nimport type { Locator } from \"@playwright/test\";\nimport { expect, test } from \"@playwright/test\";\nimport assert from \"assert\";\nimport { expandStagePanel, locateNode, locateWidget } from \"./utils\";\n\nlet treeWidget: Locator;\ntest.beforeEach(async ({ page, baseURL }) => {\n assert(baseURL);\n await page.goto(baseURL);\n // expand panel size to ~300px\n await expandStagePanel(page, \"right\", 100);\n treeWidget = locateWidget(page, \"tree\");\n await treeWidget.waitFor();\n});\n\ntest.describe(\"should match image snapshot\", () => {\n\n test(\"initial tree\", async () => {\n // wait for element to be visible in the tree\n await locateNode(treeWidget, \"ProcessPhysicalModel\").getByRole(\"checkbox\", { name: \"Visible\", exact: true }).waitFor();\n await expect(treeWidget).toHaveScreenshot();\n });\n\n test(\"expanded tree node\", async () => {\n const node = locateNode(treeWidget, \"ProcessPhysicalModel\");\n await node.getByTestId(\"tree-node-expansion-toggle\").click();\n\n // wait for node at the bottom to be visible/loaded\n await locateNode(treeWidget, \"Tag-Category\").waitFor();\n await expect(treeWidget).toHaveScreenshot();\n });\n\n test(\"selected node\", async () => {\n const node = locateNode(treeWidget, \"BayTown\");\n await node.click();\n\n // wait for node to become selected\n await expect(node).toHaveClass(/is-selected/);\n await expect(treeWidget).toHaveScreenshot();\n });\n\n test(\"search\", async () => {\n await treeWidget.getByText(\"BayTown\").waitFor();\n await treeWidget.getByTitle(\"Search for something\").click();\n await treeWidget.getByPlaceholder(\"Search...\").fill(\"Model\");\n await treeWidget.locator(\".components-activehighlight\").waitFor();\n await expect(treeWidget).toHaveScreenshot();\n });\n\n});\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Locator, Page } from "@playwright/test";
|
|
2
|
+
export declare const locateNode: (tree: Page | Locator, name: string) => Locator;
|
|
3
|
+
export declare const locateWidget: (page: Page | Locator, widgetName: string) => Locator;
|
|
4
|
+
type PanelSide = "left" | "right" | "top" | "bottom";
|
|
5
|
+
export declare const locatePanel: (page: Page, side: PanelSide) => Locator;
|
|
6
|
+
export declare const expandStagePanel: (page: Page, side: PanelSide, px: number) => Promise<void>;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.expandStagePanel = exports.locatePanel = exports.locateWidget = exports.locateNode = void 0;
|
|
7
|
+
const assert_1 = __importDefault(require("assert"));
|
|
8
|
+
const locateNode = (tree, name) => tree.getByRole("treeitem", { name });
|
|
9
|
+
exports.locateNode = locateNode;
|
|
10
|
+
const locateWidget = (page, widgetName) => page.locator(`.${widgetName}-widget`);
|
|
11
|
+
exports.locateWidget = locateWidget;
|
|
12
|
+
const locatePanel = (page, side) => page.locator(`.nz-widgetPanels-panel.nz-${side}`);
|
|
13
|
+
exports.locatePanel = locatePanel;
|
|
14
|
+
const expandStagePanel = async (page, side, px) => {
|
|
15
|
+
const widgetPanel = (0, exports.locatePanel)(page, side);
|
|
16
|
+
const handlePos = await widgetPanel
|
|
17
|
+
.locator(".nz-grip-container")
|
|
18
|
+
.locator(".nz-handle")
|
|
19
|
+
.boundingBox();
|
|
20
|
+
(0, assert_1.default)(handlePos);
|
|
21
|
+
await page.mouse.move(handlePos.x, handlePos.y);
|
|
22
|
+
await page.mouse.down();
|
|
23
|
+
switch (side) {
|
|
24
|
+
case "left":
|
|
25
|
+
await page.mouse.move(handlePos.x + px, handlePos.y);
|
|
26
|
+
break;
|
|
27
|
+
case "right":
|
|
28
|
+
await page.mouse.move(handlePos.x - px, handlePos.y);
|
|
29
|
+
break;
|
|
30
|
+
case "top":
|
|
31
|
+
await page.mouse.move(handlePos.x, handlePos.y - px);
|
|
32
|
+
break;
|
|
33
|
+
case "bottom":
|
|
34
|
+
await page.mouse.move(handlePos.x, handlePos.y + px);
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
await page.mouse.up();
|
|
38
|
+
};
|
|
39
|
+
exports.expandStagePanel = expandStagePanel;
|
|
40
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/e2e-tests/utils.ts"],"names":[],"mappings":";;;;;;AAKA,oDAA4B;AAErB,MAAM,UAAU,GAAG,CAAC,IAAoB,EAAE,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;AAA1F,QAAA,UAAU,cAAgF;AAEhG,MAAM,YAAY,GAAG,CAAC,IAAoB,EAAE,UAAkB,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,UAAU,SAAS,CAAC,CAAC;AAAnG,QAAA,YAAY,gBAAuF;AAGzG,MAAM,WAAW,GAAG,CAAC,IAAU,EAAE,IAAe,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,6BAA6B,IAAI,EAAE,CAAC,CAAC;AAAjG,QAAA,WAAW,eAAsF;AAEvG,MAAM,gBAAgB,GAAG,KAAK,EAAE,IAAU,EAAE,IAAe,EAAE,EAAU,EAAE,EAAE;IAChF,MAAM,WAAW,GAAG,IAAA,mBAAW,EAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAG,MAAM,WAAW;SAChC,OAAO,CAAC,oBAAoB,CAAC;SAC7B,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,EAAE,CAAC;IACjB,IAAA,gBAAM,EAAC,SAAS,CAAC,CAAC;IAElB,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IAChD,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAExB,QAAQ,IAAI,EAAE;QACZ,KAAK,MAAM;YACT,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;YACrD,MAAM;QACR,KAAK,OAAO;YACV,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;YACrD,MAAM;QACR,KAAK,KAAK;YACR,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;YACrD,MAAM;QACR,KAAK,QAAQ;YACX,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;YACrD,MAAM;KACT;IACD,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;AACxB,CAAC,CAAC;AA1BW,QAAA,gBAAgB,oBA0B3B","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\nimport type { Locator, Page } from \"@playwright/test\";\nimport assert from \"assert\";\n\nexport const locateNode = (tree: Page | Locator, name: string) => tree.getByRole(\"treeitem\", { name });\n\nexport const locateWidget = (page: Page | Locator, widgetName: string) => page.locator(`.${widgetName}-widget`);\n\ntype PanelSide = \"left\" | \"right\" | \"top\" | \"bottom\";\nexport const locatePanel = (page: Page, side: PanelSide) => page.locator(`.nz-widgetPanels-panel.nz-${side}`);\n\nexport const expandStagePanel = async (page: Page, side: PanelSide, px: number) => {\n const widgetPanel = locatePanel(page, side);\n const handlePos = await widgetPanel\n .locator(\".nz-grip-container\")\n .locator(\".nz-handle\")\n .boundingBox();\n assert(handlePos);\n\n await page.mouse.move(handlePos.x, handlePos.y);\n await page.mouse.down();\n\n switch (side) {\n case \"left\":\n await page.mouse.move(handlePos.x + px, handlePos.y);\n break;\n case \"right\":\n await page.mouse.move(handlePos.x - px, handlePos.y);\n break;\n case \"top\":\n await page.mouse.move(handlePos.x, handlePos.y - px);\n break;\n case \"bottom\":\n await page.mouse.move(handlePos.x, handlePos.y + px);\n break;\n }\n await page.mouse.up();\n};\n"]}
|
|
@@ -7,30 +7,30 @@
|
|
|
7
7
|
.tree-widget-tree-nodes-list {
|
|
8
8
|
.core-tree-node {
|
|
9
9
|
&.with-checkbox {
|
|
10
|
-
|
|
10
|
+
> .contents {
|
|
11
11
|
padding-left: calc(var(--iui-size-3xs) / 2);
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
&.disable-expander {
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
> .contents {
|
|
17
|
+
> .core-tree-expansionToggle {
|
|
18
18
|
display: none;
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
&.is-selected {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
background-color: var(--iui-color-background-accent-muted)
|
|
24
|
+
> .contents {
|
|
25
|
+
> .visibility-tree-checkbox-container {
|
|
26
|
+
background-color: var(--iui-color-background-accent-muted);
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
.
|
|
32
|
-
|
|
33
|
-
.visibility-tree-checkbox-container {
|
|
31
|
+
&:not(.is-selected) {
|
|
32
|
+
> .contents:hover {
|
|
33
|
+
> .visibility-tree-checkbox-container {
|
|
34
34
|
background-color: var(--iui-color-background-hover);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
.without-expander {
|
|
76
|
-
.visibility-tree-checkbox-container
|
|
76
|
+
.visibility-tree-checkbox-container + * {
|
|
77
77
|
margin-left: var(--enlarged-node-expander-additional-padding);
|
|
78
78
|
}
|
|
79
79
|
}
|
|
@@ -41,7 +41,7 @@ export function createVisibilityTreeNodeRenderer({ levelOffset = 20, disableRoot
|
|
|
41
41
|
* @public
|
|
42
42
|
*/
|
|
43
43
|
export function VisibilityTreeNodeCheckbox(props) {
|
|
44
|
-
return _jsx(Checkbox, { className: "visibility-tree-checkbox", variant: "eyeball", checked: props.checked, onChange: (e) => props.onChange(e.currentTarget.checked), disabled: props.disabled, title: props.title });
|
|
44
|
+
return _jsx(Checkbox, { className: "visibility-tree-checkbox", variant: "eyeball", checked: props.checked, onChange: (e) => props.onChange(e.currentTarget.checked), onClick: props.onClick, disabled: props.disabled, title: props.title });
|
|
45
45
|
}
|
|
46
46
|
/**
|
|
47
47
|
* Filters data provider used in supplied node loader and invokes onFilterApplied when filtering is completed.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VisibilityTreeRenderer.js","sourceRoot":"","sources":["../../../../src/components/trees/VisibilityTreeRenderer.tsx"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\n\nimport classNames from \"classnames\";\nimport { useEffect } from \"react\";\nimport { TreeImageLoader, TreeNodeRenderer } from \"@itwin/components-react\";\nimport { Checkbox } from \"@itwin/itwinui-react\";\nimport { useControlledPresentationTreeFiltering } from \"@itwin/presentation-components\";\nimport { TreeRenderer } from \"./common/TreeRenderer\";\n\nimport type { TreeRendererBaseProps } from \"./common/TreeRenderer\";\nimport type { AbstractTreeNodeLoaderWithProvider, TreeNodeRendererProps, TreeRendererProps } from \"@itwin/components-react\";\nimport type { NodeCheckboxRenderProps } from \"@itwin/core-react\";\nimport type { IPresentationTreeDataProvider } from \"@itwin/presentation-components\";\nimport type { VisibilityTreeFilterInfo } from \"./common/Types\";\n\n/**\n * This constant is taken from `@itwin/core-react`.\n * Defines the size in pixels of the expansion toggle.\n * It is used to keep same hierarchy nodes with children and nodes without children in the same line.\n * @note This value applies only to the leaf nodes.\n */\nconst EXPANSION_TOGGLE_WIDTH = 24;\n\n/**\n * Props for visibility tree renderer.\n * @public\n */\nexport interface VisibilityTreeRendererProps extends TreeRendererBaseProps {\n /** Props for single node renderer. */\n nodeRendererProps: VisibilityTreeNodeRendererProps;\n}\n\n/**\n * Props for visibility tree node renderer.\n * @public\n */\nexport interface VisibilityTreeNodeRendererProps {\n /**\n * Specifies whether the icon at the left of the node label should be rendered.\n */\n iconsEnabled: boolean;\n /**\n * Specifies whether node description should be enabled.\n */\n descriptionEnabled: boolean;\n /**\n * Defines the offset in pixels of how much each hierarchy level should be offset to the right from the checkbox.\n * Defaults to `20`.\n */\n levelOffset?: number;\n /**\n * Specifies whether the root node be expanded at all times.\n * Defaults to `false`.\n */\n disableRootNodeCollapse?: boolean;\n}\n\n/**\n * Creates Visibility tree renderer which renders nodes with eye checkbox.\n * @public\n */\nexport function createVisibilityTreeRenderer({ nodeRendererProps, ...restProps }: VisibilityTreeRendererProps) {\n return function VisibilityTreeRenderer(treeProps: TreeRendererProps) {\n return <TreeRenderer {...treeProps} {...restProps} nodeRenderer={createVisibilityTreeNodeRenderer(nodeRendererProps)} />;\n };\n}\n\nconst imageLoader = new TreeImageLoader();\n\n/**\n * Creates node renderer which renders node with eye checkbox.\n * @public\n */\nexport function createVisibilityTreeNodeRenderer({ levelOffset = 20, disableRootNodeCollapse = false, descriptionEnabled, iconsEnabled }: VisibilityTreeNodeRendererProps) {\n return function VisibilityTreeNodeRenderer(treeNodeProps: TreeNodeRendererProps) {\n const nodeOffset = treeNodeProps.node.depth * levelOffset + (treeNodeProps.node.numChildren === 0 ? EXPANSION_TOGGLE_WIDTH : 0);\n return (\n <TreeNodeRenderer\n {...treeNodeProps}\n node={{ ...treeNodeProps.node, depth: 0, numChildren: 1 }} // if we want to disable TreeNodeRenderer style calculations for tree nodes, we need to override these values.\n checkboxRenderer={(checkboxProps: NodeCheckboxRenderProps) => (\n <div className=\"visibility-tree-checkbox-container\" style={{ marginRight: `${nodeOffset}px` }}>\n <VisibilityTreeNodeCheckbox {...checkboxProps} />\n </div>\n )}\n descriptionEnabled={descriptionEnabled}\n imageLoader={iconsEnabled ? imageLoader : undefined}\n className={classNames(\"with-checkbox\", (treeNodeProps.node.numChildren === 0 || (disableRootNodeCollapse && treeNodeProps.node.parentId === undefined)) && \"disable-expander\", treeNodeProps.className)}\n />\n );\n };\n}\n\n/**\n * Checkbox renderer that renders an eye.\n * @public\n */\nexport function VisibilityTreeNodeCheckbox(props: NodeCheckboxRenderProps) {\n return <Checkbox\n className=\"visibility-tree-checkbox\"\n variant=\"eyeball\"\n checked={props.checked}\n onChange={(e) => props.onChange(e.currentTarget.checked)}\n disabled={props.disabled}\n title={props.title}\n />;\n}\n\n/**\n * Filters data provider used in supplied node loader and invokes onFilterApplied when filtering is completed.\n * @public\n */\nexport function useVisibilityTreeFiltering(\n nodeLoader: AbstractTreeNodeLoaderWithProvider<IPresentationTreeDataProvider>,\n filterInfo?: VisibilityTreeFilterInfo,\n onFilterApplied?: (filteredDataProvider: IPresentationTreeDataProvider, matchesCount: number) => void,\n) {\n const { filter, activeMatchIndex } = filterInfo ?? { filter: undefined, activeMatchIndex: undefined };\n const {\n filteredNodeLoader,\n isFiltering,\n matchesCount,\n nodeHighlightingProps,\n } = useControlledPresentationTreeFiltering({ nodeLoader, filter, activeMatchIndex });\n\n useEffect(\n () => {\n if (filter && matchesCount !== undefined && filteredNodeLoader !== nodeLoader)\n onFilterApplied && onFilterApplied(filteredNodeLoader.dataProvider, matchesCount);\n },\n [filter, matchesCount, nodeLoader, filteredNodeLoader, onFilterApplied],\n );\n\n return { filteredNodeLoader, isFiltering, nodeHighlightingProps };\n}\n\n/**\n * Properties for [[VisibilityTreeNoFilteredData]] component.\n * @public\n */\nexport interface VisibilityTreeNoFilteredDataProps {\n title: string;\n message: string;\n}\n\n/**\n * Renders message that no nodes was found for filter.\n * @public\n */\nexport function VisibilityTreeNoFilteredData(props: VisibilityTreeNoFilteredDataProps) {\n return (\n <div className=\"components-tree-errormessage\">\n <span className=\"errormessage-header\">{props.title}</span>\n <span className=\"errormessage-body\">{props.message}</span>\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"VisibilityTreeRenderer.js","sourceRoot":"","sources":["../../../../src/components/trees/VisibilityTreeRenderer.tsx"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\n\nimport classNames from \"classnames\";\nimport { useEffect } from \"react\";\nimport { TreeImageLoader, TreeNodeRenderer } from \"@itwin/components-react\";\nimport { Checkbox } from \"@itwin/itwinui-react\";\nimport { useControlledPresentationTreeFiltering } from \"@itwin/presentation-components\";\nimport { TreeRenderer } from \"./common/TreeRenderer\";\n\nimport type { TreeRendererBaseProps } from \"./common/TreeRenderer\";\nimport type { AbstractTreeNodeLoaderWithProvider, TreeNodeRendererProps, TreeRendererProps } from \"@itwin/components-react\";\nimport type { NodeCheckboxRenderProps } from \"@itwin/core-react\";\nimport type { IPresentationTreeDataProvider } from \"@itwin/presentation-components\";\nimport type { VisibilityTreeFilterInfo } from \"./common/Types\";\n\n/**\n * This constant is taken from `@itwin/core-react`.\n * Defines the size in pixels of the expansion toggle.\n * It is used to keep same hierarchy nodes with children and nodes without children in the same line.\n * @note This value applies only to the leaf nodes.\n */\nconst EXPANSION_TOGGLE_WIDTH = 24;\n\n/**\n * Props for visibility tree renderer.\n * @public\n */\nexport interface VisibilityTreeRendererProps extends TreeRendererBaseProps {\n /** Props for single node renderer. */\n nodeRendererProps: VisibilityTreeNodeRendererProps;\n}\n\n/**\n * Props for visibility tree node renderer.\n * @public\n */\nexport interface VisibilityTreeNodeRendererProps {\n /**\n * Specifies whether the icon at the left of the node label should be rendered.\n */\n iconsEnabled: boolean;\n /**\n * Specifies whether node description should be enabled.\n */\n descriptionEnabled: boolean;\n /**\n * Defines the offset in pixels of how much each hierarchy level should be offset to the right from the checkbox.\n * Defaults to `20`.\n */\n levelOffset?: number;\n /**\n * Specifies whether the root node be expanded at all times.\n * Defaults to `false`.\n */\n disableRootNodeCollapse?: boolean;\n}\n\n/**\n * Creates Visibility tree renderer which renders nodes with eye checkbox.\n * @public\n */\nexport function createVisibilityTreeRenderer({ nodeRendererProps, ...restProps }: VisibilityTreeRendererProps) {\n return function VisibilityTreeRenderer(treeProps: TreeRendererProps) {\n return <TreeRenderer {...treeProps} {...restProps} nodeRenderer={createVisibilityTreeNodeRenderer(nodeRendererProps)} />;\n };\n}\n\nconst imageLoader = new TreeImageLoader();\n\n/**\n * Creates node renderer which renders node with eye checkbox.\n * @public\n */\nexport function createVisibilityTreeNodeRenderer({ levelOffset = 20, disableRootNodeCollapse = false, descriptionEnabled, iconsEnabled }: VisibilityTreeNodeRendererProps) {\n return function VisibilityTreeNodeRenderer(treeNodeProps: TreeNodeRendererProps) {\n const nodeOffset = treeNodeProps.node.depth * levelOffset + (treeNodeProps.node.numChildren === 0 ? EXPANSION_TOGGLE_WIDTH : 0);\n return (\n <TreeNodeRenderer\n {...treeNodeProps}\n node={{ ...treeNodeProps.node, depth: 0, numChildren: 1 }} // if we want to disable TreeNodeRenderer style calculations for tree nodes, we need to override these values.\n checkboxRenderer={(checkboxProps: NodeCheckboxRenderProps) => (\n <div className=\"visibility-tree-checkbox-container\" style={{ marginRight: `${nodeOffset}px` }}>\n <VisibilityTreeNodeCheckbox {...checkboxProps} />\n </div>\n )}\n descriptionEnabled={descriptionEnabled}\n imageLoader={iconsEnabled ? imageLoader : undefined}\n className={classNames(\"with-checkbox\", (treeNodeProps.node.numChildren === 0 || (disableRootNodeCollapse && treeNodeProps.node.parentId === undefined)) && \"disable-expander\", treeNodeProps.className)}\n />\n );\n };\n}\n\n/**\n * Checkbox renderer that renders an eye.\n * @public\n */\nexport function VisibilityTreeNodeCheckbox(props: NodeCheckboxRenderProps) {\n return <Checkbox\n className=\"visibility-tree-checkbox\"\n variant=\"eyeball\"\n checked={props.checked}\n onChange={(e) => props.onChange(e.currentTarget.checked)}\n onClick={props.onClick}\n disabled={props.disabled}\n title={props.title}\n />;\n}\n\n/**\n * Filters data provider used in supplied node loader and invokes onFilterApplied when filtering is completed.\n * @public\n */\nexport function useVisibilityTreeFiltering(\n nodeLoader: AbstractTreeNodeLoaderWithProvider<IPresentationTreeDataProvider>,\n filterInfo?: VisibilityTreeFilterInfo,\n onFilterApplied?: (filteredDataProvider: IPresentationTreeDataProvider, matchesCount: number) => void,\n) {\n const { filter, activeMatchIndex } = filterInfo ?? { filter: undefined, activeMatchIndex: undefined };\n const {\n filteredNodeLoader,\n isFiltering,\n matchesCount,\n nodeHighlightingProps,\n } = useControlledPresentationTreeFiltering({ nodeLoader, filter, activeMatchIndex });\n\n useEffect(\n () => {\n if (filter && matchesCount !== undefined && filteredNodeLoader !== nodeLoader)\n onFilterApplied && onFilterApplied(filteredNodeLoader.dataProvider, matchesCount);\n },\n [filter, matchesCount, nodeLoader, filteredNodeLoader, onFilterApplied],\n );\n\n return { filteredNodeLoader, isFiltering, nodeHighlightingProps };\n}\n\n/**\n * Properties for [[VisibilityTreeNoFilteredData]] component.\n * @public\n */\nexport interface VisibilityTreeNoFilteredDataProps {\n title: string;\n message: string;\n}\n\n/**\n * Renders message that no nodes was found for filter.\n * @public\n */\nexport function VisibilityTreeNoFilteredData(props: VisibilityTreeNoFilteredDataProps) {\n return (\n <div className=\"components-tree-errormessage\">\n <span className=\"errormessage-header\">{props.title}</span>\n <span className=\"errormessage-body\">{props.message}</span>\n </div>\n );\n}\n"]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { expect, test } from "@playwright/test";
|
|
2
|
+
import assert from "assert";
|
|
3
|
+
import { expandStagePanel, locateNode, locateWidget } from "./utils";
|
|
4
|
+
let treeWidget;
|
|
5
|
+
test.beforeEach(async ({ page, baseURL }) => {
|
|
6
|
+
assert(baseURL);
|
|
7
|
+
await page.goto(baseURL);
|
|
8
|
+
// expand panel size to ~300px
|
|
9
|
+
await expandStagePanel(page, "right", 100);
|
|
10
|
+
treeWidget = locateWidget(page, "tree");
|
|
11
|
+
await treeWidget.waitFor();
|
|
12
|
+
});
|
|
13
|
+
test.describe("should match image snapshot", () => {
|
|
14
|
+
test("initial tree", async () => {
|
|
15
|
+
// wait for element to be visible in the tree
|
|
16
|
+
await locateNode(treeWidget, "ProcessPhysicalModel").getByRole("checkbox", { name: "Visible", exact: true }).waitFor();
|
|
17
|
+
await expect(treeWidget).toHaveScreenshot();
|
|
18
|
+
});
|
|
19
|
+
test("expanded tree node", async () => {
|
|
20
|
+
const node = locateNode(treeWidget, "ProcessPhysicalModel");
|
|
21
|
+
await node.getByTestId("tree-node-expansion-toggle").click();
|
|
22
|
+
// wait for node at the bottom to be visible/loaded
|
|
23
|
+
await locateNode(treeWidget, "Tag-Category").waitFor();
|
|
24
|
+
await expect(treeWidget).toHaveScreenshot();
|
|
25
|
+
});
|
|
26
|
+
test("selected node", async () => {
|
|
27
|
+
const node = locateNode(treeWidget, "BayTown");
|
|
28
|
+
await node.click();
|
|
29
|
+
// wait for node to become selected
|
|
30
|
+
await expect(node).toHaveClass(/is-selected/);
|
|
31
|
+
await expect(treeWidget).toHaveScreenshot();
|
|
32
|
+
});
|
|
33
|
+
test("search", async () => {
|
|
34
|
+
await treeWidget.getByText("BayTown").waitFor();
|
|
35
|
+
await treeWidget.getByTitle("Search for something").click();
|
|
36
|
+
await treeWidget.getByPlaceholder("Search...").fill("Model");
|
|
37
|
+
await treeWidget.locator(".components-activehighlight").waitFor();
|
|
38
|
+
await expect(treeWidget).toHaveScreenshot();
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
//# sourceMappingURL=TreeWidget.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TreeWidget.test.js","sourceRoot":"","sources":["../../../src/e2e-tests/TreeWidget.test.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAErE,IAAI,UAAmB,CAAC;AACxB,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE;IAC1C,MAAM,CAAC,OAAO,CAAC,CAAC;IAChB,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzB,8BAA8B;IAC9B,MAAM,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;IAC3C,UAAU,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACxC,MAAM,UAAU,CAAC,OAAO,EAAE,CAAC;AAC7B,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;IAEhD,IAAI,CAAC,cAAc,EAAE,KAAK,IAAI,EAAE;QAC9B,6CAA6C;QAC7C,MAAM,UAAU,CAAC,UAAU,EAAE,sBAAsB,CAAC,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;QACvH,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC,gBAAgB,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,oBAAoB,EAAE,KAAK,IAAI,EAAE;QACpC,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,EAAE,sBAAsB,CAAC,CAAC;QAC5D,MAAM,IAAI,CAAC,WAAW,CAAC,4BAA4B,CAAC,CAAC,KAAK,EAAE,CAAC;QAE7D,mDAAmD;QACnD,MAAM,UAAU,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC;QACvD,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC,gBAAgB,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,eAAe,EAAE,KAAK,IAAI,EAAE;QAC/B,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAC/C,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QAEnB,mCAAmC;QACnC,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;QAC9C,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC,gBAAgB,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QACxB,MAAM,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;QAChD,MAAM,UAAU,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAC,KAAK,EAAE,CAAC;QAC5D,MAAM,UAAU,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7D,MAAM,UAAU,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC,OAAO,EAAE,CAAC;QAClE,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC,gBAAgB,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;AAEL,CAAC,CAAC,CAAC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\nimport type { Locator } from \"@playwright/test\";\nimport { expect, test } from \"@playwright/test\";\nimport assert from \"assert\";\nimport { expandStagePanel, locateNode, locateWidget } from \"./utils\";\n\nlet treeWidget: Locator;\ntest.beforeEach(async ({ page, baseURL }) => {\n assert(baseURL);\n await page.goto(baseURL);\n // expand panel size to ~300px\n await expandStagePanel(page, \"right\", 100);\n treeWidget = locateWidget(page, \"tree\");\n await treeWidget.waitFor();\n});\n\ntest.describe(\"should match image snapshot\", () => {\n\n test(\"initial tree\", async () => {\n // wait for element to be visible in the tree\n await locateNode(treeWidget, \"ProcessPhysicalModel\").getByRole(\"checkbox\", { name: \"Visible\", exact: true }).waitFor();\n await expect(treeWidget).toHaveScreenshot();\n });\n\n test(\"expanded tree node\", async () => {\n const node = locateNode(treeWidget, \"ProcessPhysicalModel\");\n await node.getByTestId(\"tree-node-expansion-toggle\").click();\n\n // wait for node at the bottom to be visible/loaded\n await locateNode(treeWidget, \"Tag-Category\").waitFor();\n await expect(treeWidget).toHaveScreenshot();\n });\n\n test(\"selected node\", async () => {\n const node = locateNode(treeWidget, \"BayTown\");\n await node.click();\n\n // wait for node to become selected\n await expect(node).toHaveClass(/is-selected/);\n await expect(treeWidget).toHaveScreenshot();\n });\n\n test(\"search\", async () => {\n await treeWidget.getByText(\"BayTown\").waitFor();\n await treeWidget.getByTitle(\"Search for something\").click();\n await treeWidget.getByPlaceholder(\"Search...\").fill(\"Model\");\n await treeWidget.locator(\".components-activehighlight\").waitFor();\n await expect(treeWidget).toHaveScreenshot();\n });\n\n});\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Locator, Page } from "@playwright/test";
|
|
2
|
+
export declare const locateNode: (tree: Page | Locator, name: string) => Locator;
|
|
3
|
+
export declare const locateWidget: (page: Page | Locator, widgetName: string) => Locator;
|
|
4
|
+
type PanelSide = "left" | "right" | "top" | "bottom";
|
|
5
|
+
export declare const locatePanel: (page: Page, side: PanelSide) => Locator;
|
|
6
|
+
export declare const expandStagePanel: (page: Page, side: PanelSide, px: number) => Promise<void>;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
export const locateNode = (tree, name) => tree.getByRole("treeitem", { name });
|
|
3
|
+
export const locateWidget = (page, widgetName) => page.locator(`.${widgetName}-widget`);
|
|
4
|
+
export const locatePanel = (page, side) => page.locator(`.nz-widgetPanels-panel.nz-${side}`);
|
|
5
|
+
export const expandStagePanel = async (page, side, px) => {
|
|
6
|
+
const widgetPanel = locatePanel(page, side);
|
|
7
|
+
const handlePos = await widgetPanel
|
|
8
|
+
.locator(".nz-grip-container")
|
|
9
|
+
.locator(".nz-handle")
|
|
10
|
+
.boundingBox();
|
|
11
|
+
assert(handlePos);
|
|
12
|
+
await page.mouse.move(handlePos.x, handlePos.y);
|
|
13
|
+
await page.mouse.down();
|
|
14
|
+
switch (side) {
|
|
15
|
+
case "left":
|
|
16
|
+
await page.mouse.move(handlePos.x + px, handlePos.y);
|
|
17
|
+
break;
|
|
18
|
+
case "right":
|
|
19
|
+
await page.mouse.move(handlePos.x - px, handlePos.y);
|
|
20
|
+
break;
|
|
21
|
+
case "top":
|
|
22
|
+
await page.mouse.move(handlePos.x, handlePos.y - px);
|
|
23
|
+
break;
|
|
24
|
+
case "bottom":
|
|
25
|
+
await page.mouse.move(handlePos.x, handlePos.y + px);
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
await page.mouse.up();
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/e2e-tests/utils.ts"],"names":[],"mappings":"AAKA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAoB,EAAE,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;AAEvG,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,IAAoB,EAAE,UAAkB,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,UAAU,SAAS,CAAC,CAAC;AAGhH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAU,EAAE,IAAe,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,6BAA6B,IAAI,EAAE,CAAC,CAAC;AAE9G,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,EAAE,IAAU,EAAE,IAAe,EAAE,EAAU,EAAE,EAAE;IAChF,MAAM,WAAW,GAAG,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAG,MAAM,WAAW;SAChC,OAAO,CAAC,oBAAoB,CAAC;SAC7B,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,EAAE,CAAC;IACjB,MAAM,CAAC,SAAS,CAAC,CAAC;IAElB,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IAChD,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAExB,QAAQ,IAAI,EAAE;QACZ,KAAK,MAAM;YACT,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;YACrD,MAAM;QACR,KAAK,OAAO;YACV,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;YACrD,MAAM;QACR,KAAK,KAAK;YACR,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;YACrD,MAAM;QACR,KAAK,QAAQ;YACX,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;YACrD,MAAM;KACT;IACD,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;AACxB,CAAC,CAAC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\nimport type { Locator, Page } from \"@playwright/test\";\nimport assert from \"assert\";\n\nexport const locateNode = (tree: Page | Locator, name: string) => tree.getByRole(\"treeitem\", { name });\n\nexport const locateWidget = (page: Page | Locator, widgetName: string) => page.locator(`.${widgetName}-widget`);\n\ntype PanelSide = \"left\" | \"right\" | \"top\" | \"bottom\";\nexport const locatePanel = (page: Page, side: PanelSide) => page.locator(`.nz-widgetPanels-panel.nz-${side}`);\n\nexport const expandStagePanel = async (page: Page, side: PanelSide, px: number) => {\n const widgetPanel = locatePanel(page, side);\n const handlePos = await widgetPanel\n .locator(\".nz-grip-container\")\n .locator(\".nz-handle\")\n .boundingBox();\n assert(handlePos);\n\n await page.mouse.move(handlePos.x, handlePos.y);\n await page.mouse.down();\n\n switch (side) {\n case \"left\":\n await page.mouse.move(handlePos.x + px, handlePos.y);\n break;\n case \"right\":\n await page.mouse.move(handlePos.x - px, handlePos.y);\n break;\n case \"top\":\n await page.mouse.move(handlePos.x, handlePos.y - px);\n break;\n case \"bottom\":\n await page.mouse.move(handlePos.x, handlePos.y + px);\n break;\n }\n await page.mouse.up();\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@itwin/tree-widget-react",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "Tree Widget React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Bentley",
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
"@itwin/presentation-frontend": "^4.0.0",
|
|
57
57
|
"@itwin/presentation-testing": "^4.0.0",
|
|
58
58
|
"@itwin/webgl-compatibility": "^4.0.0",
|
|
59
|
+
"@playwright/test": "^1.36.2",
|
|
59
60
|
"@rushstack/eslint-patch": "1.2.0",
|
|
60
61
|
"@testing-library/dom": "^8.12.0",
|
|
61
62
|
"@testing-library/react": "^12.0.0",
|
|
@@ -78,6 +79,7 @@
|
|
|
78
79
|
"chai-jest-snapshot": "^2.0.0",
|
|
79
80
|
"chai-subset": "1.6.0",
|
|
80
81
|
"cpx2": "^3.0.0",
|
|
82
|
+
"cross-env": "^7.0.3",
|
|
81
83
|
"deep-equal": "^1.0.0",
|
|
82
84
|
"eslint": "^8.41.0",
|
|
83
85
|
"eslint-plugin-unused-imports": "^2.0.0",
|
|
@@ -113,6 +115,7 @@
|
|
|
113
115
|
]
|
|
114
116
|
},
|
|
115
117
|
"scripts": {
|
|
118
|
+
"start:test-viewer": "node ./scripts/start-test-viewer.js",
|
|
116
119
|
"build": "npm run -s dual-build && npm run -s copy:assets",
|
|
117
120
|
"dual-build": "npm run -s build:cjs && npm run -s build:esm",
|
|
118
121
|
"build:cjs": "tsc 1>&2 --outDir lib/cjs",
|
|
@@ -127,6 +130,8 @@
|
|
|
127
130
|
"lint:fix": "npm run lint -- --fix",
|
|
128
131
|
"pseudolocalize": "betools pseudolocalize --englishDir ./public/locales/en --out ./lib/public/locales/en-PSEUDO",
|
|
129
132
|
"test": "mocha \"./lib/cjs/test/**/*.test.js\"",
|
|
133
|
+
"test:e2e": "playwright test",
|
|
134
|
+
"test:e2e:debug": "cross-env PWDEBUG=1 playwright test --ui",
|
|
130
135
|
"clean": "rimraf lib .rush/temp/package-deps*.json",
|
|
131
136
|
"rebuild": "npm run clean && npm run build"
|
|
132
137
|
},
|