@itwin/tree-widget-react 2.0.0-dev.0 → 2.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/CHANGELOG.md +25 -1
- package/lib/cjs/components/SelectableTree.d.ts +9 -1
- package/lib/cjs/components/SelectableTree.js +6 -6
- package/lib/cjs/components/SelectableTree.js.map +1 -1
- package/lib/cjs/components/SelectableTree.scss +0 -16
- package/lib/cjs/components/TreeSelector.d.ts +28 -0
- package/lib/cjs/components/TreeSelector.js +27 -0
- package/lib/cjs/components/TreeSelector.js.map +1 -0
- package/lib/cjs/components/TreeSelector.scss +27 -0
- package/lib/cjs/components/TreeWidgetUiItemsProvider.d.ts +9 -1
- package/lib/cjs/components/TreeWidgetUiItemsProvider.js +14 -9
- package/lib/cjs/components/TreeWidgetUiItemsProvider.js.map +1 -1
- package/lib/cjs/components/tree-header/TreeHeader.d.ts +3 -0
- package/lib/cjs/components/tree-header/TreeHeader.js +11 -9
- package/lib/cjs/components/tree-header/TreeHeader.js.map +1 -1
- package/lib/cjs/components/tree-header/TreeHeader.scss +28 -0
- package/lib/cjs/components/trees/category-tree/CategoriesTreeComponent.js +13 -8
- package/lib/cjs/components/trees/category-tree/CategoriesTreeComponent.js.map +1 -1
- package/lib/cjs/components/trees/category-tree/CategoryVisibilityHandler.d.ts +2 -2
- package/lib/cjs/components/trees/common/TreeRenderer.scss +32 -0
- package/lib/cjs/components/trees/models-tree/ModelsTreeComponent.js +17 -12
- package/lib/cjs/components/trees/models-tree/ModelsTreeComponent.js.map +1 -1
- package/lib/esm/components/SelectableTree.d.ts +9 -1
- package/lib/esm/components/SelectableTree.js +6 -6
- package/lib/esm/components/SelectableTree.js.map +1 -1
- package/lib/esm/components/SelectableTree.scss +0 -16
- package/lib/esm/components/TreeSelector.d.ts +28 -0
- package/lib/esm/components/TreeSelector.js +23 -0
- package/lib/esm/components/TreeSelector.js.map +1 -0
- package/lib/esm/components/TreeSelector.scss +27 -0
- package/lib/esm/components/TreeWidgetUiItemsProvider.d.ts +9 -1
- package/lib/esm/components/TreeWidgetUiItemsProvider.js +12 -8
- package/lib/esm/components/TreeWidgetUiItemsProvider.js.map +1 -1
- package/lib/esm/components/tree-header/TreeHeader.d.ts +3 -0
- package/lib/esm/components/tree-header/TreeHeader.js +11 -9
- package/lib/esm/components/tree-header/TreeHeader.js.map +1 -1
- package/lib/esm/components/tree-header/TreeHeader.scss +28 -0
- package/lib/esm/components/trees/category-tree/CategoriesTreeComponent.js +10 -8
- package/lib/esm/components/trees/category-tree/CategoriesTreeComponent.js.map +1 -1
- package/lib/esm/components/trees/category-tree/CategoryVisibilityHandler.d.ts +2 -2
- package/lib/esm/components/trees/common/TreeRenderer.scss +32 -0
- package/lib/esm/components/trees/models-tree/ModelsTreeComponent.js +14 -12
- package/lib/esm/components/trees/models-tree/ModelsTreeComponent.js.map +1 -1
- package/lib/public/locales/en/TreeWidget.json +1 -0
- package/package.json +12 -12
- package/lib/cjs/e2e-tests/TreeWidget.test.d.ts +0 -2
- package/lib/cjs/e2e-tests/TreeWidget.test.js +0 -104
- package/lib/cjs/e2e-tests/TreeWidget.test.js.map +0 -1
- package/lib/cjs/e2e-tests/utils.d.ts +0 -10
- package/lib/cjs/e2e-tests/utils.js +0 -50
- package/lib/cjs/e2e-tests/utils.js.map +0 -1
- package/lib/esm/e2e-tests/TreeWidget.test.d.ts +0 -2
- package/lib/esm/e2e-tests/TreeWidget.test.js +0 -99
- package/lib/esm/e2e-tests/TreeWidget.test.js.map +0 -1
- package/lib/esm/e2e-tests/utils.d.ts +0 -10
- package/lib/esm/e2e-tests/utils.js +0 -38
- package/lib/esm/e2e-tests/utils.js.map +0 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
1
2
|
import "./TreeWidgetUiItemsProvider.scss";
|
|
2
3
|
import { StagePanelLocation, StagePanelSection } from "@itwin/appui-react";
|
|
3
4
|
import type { UiItemsProvider, Widget } from "@itwin/appui-react";
|
|
4
|
-
import type { TreeDefinition } from "./SelectableTree";
|
|
5
|
+
import type { SelectableTreeProps, TreeDefinition } from "./SelectableTree";
|
|
5
6
|
/**
|
|
6
7
|
* Parameters for creating a [[TreeWidgetUiItemsProvider]].
|
|
7
8
|
* @public
|
|
@@ -15,6 +16,8 @@ export interface TreeWidgetOptions {
|
|
|
15
16
|
defaultTreeWidgetPriority?: number;
|
|
16
17
|
/** Trees to show in the widget. Defaults to [[ModelsTreeComponent]] and [[CategoriesTreeComponent]]. */
|
|
17
18
|
trees?: TreeDefinition[];
|
|
19
|
+
/** Modifies the density of the tree widget. `enlarged` widget contains larger content */
|
|
20
|
+
density?: "enlarged" | "default";
|
|
18
21
|
}
|
|
19
22
|
/**
|
|
20
23
|
* Id of the tree widget created by [[TreeWidgetUiItemsProvider]].
|
|
@@ -31,4 +34,9 @@ export declare class TreeWidgetUiItemsProvider implements UiItemsProvider {
|
|
|
31
34
|
constructor(_treeWidgetOptions?: TreeWidgetOptions | undefined);
|
|
32
35
|
provideWidgets(_stageId: string, stageUsage: string, location: StagePanelLocation, section?: StagePanelSection): ReadonlyArray<Widget>;
|
|
33
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Tree widget component which allows selecting which tree to render.
|
|
39
|
+
* @public
|
|
40
|
+
*/
|
|
41
|
+
export declare function TreeWidgetComponent(props: SelectableTreeProps): JSX.Element;
|
|
34
42
|
//# sourceMappingURL=TreeWidgetUiItemsProvider.d.ts.map
|
|
@@ -4,16 +4,16 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
4
4
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
5
5
|
*--------------------------------------------------------------------------------------------*/
|
|
6
6
|
import "./TreeWidgetUiItemsProvider.scss";
|
|
7
|
-
import { ErrorBoundary } from "react-error-boundary";
|
|
8
7
|
import { StagePanelLocation, StagePanelSection, StageUsage } from "@itwin/appui-react";
|
|
9
8
|
import { SvgHierarchyTree } from "@itwin/itwinui-icons-react";
|
|
10
|
-
import { SvgError } from "@itwin/itwinui-illustrations-react";
|
|
11
|
-
import { Button, NonIdealState } from "@itwin/itwinui-react";
|
|
12
9
|
import { TreeWidget } from "../TreeWidget";
|
|
13
|
-
import { SelectableTree } from "./SelectableTree";
|
|
14
10
|
import { CategoriesTreeComponent } from "./trees/category-tree/CategoriesTreeComponent";
|
|
15
11
|
import { ModelsTreeComponent } from "./trees/models-tree/ModelsTreeComponent";
|
|
12
|
+
import { ErrorBoundary } from "react-error-boundary";
|
|
13
|
+
import { SelectableTree } from "./SelectableTree";
|
|
16
14
|
import { useTreeTransientState } from "./utils/UseTreeTransientState";
|
|
15
|
+
import { Button, NonIdealState } from "@itwin/itwinui-react";
|
|
16
|
+
import { SvgError } from "@itwin/itwinui-illustrations-react";
|
|
17
17
|
/**
|
|
18
18
|
* Id of the tree widget created by [[TreeWidgetUiItemsProvider]].
|
|
19
19
|
* @public
|
|
@@ -38,26 +38,30 @@ export class TreeWidgetUiItemsProvider {
|
|
|
38
38
|
{
|
|
39
39
|
id: ModelsTreeComponent.id,
|
|
40
40
|
getLabel: ModelsTreeComponent.getLabel,
|
|
41
|
-
render: () => _jsx(ModelsTreeComponent, {}),
|
|
41
|
+
render: (props) => _jsx(ModelsTreeComponent, { density: props.density }),
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
44
|
id: CategoriesTreeComponent.id,
|
|
45
45
|
getLabel: CategoriesTreeComponent.getLabel,
|
|
46
|
-
render: () => _jsx(CategoriesTreeComponent, {}),
|
|
46
|
+
render: (props) => _jsx(CategoriesTreeComponent, { density: props.density }),
|
|
47
47
|
},
|
|
48
48
|
];
|
|
49
49
|
return [
|
|
50
50
|
{
|
|
51
51
|
id: TreeWidgetId,
|
|
52
52
|
label: TreeWidget.translate("treeview"),
|
|
53
|
-
content: _jsx(
|
|
53
|
+
content: _jsx(TreeWidgetComponent, { trees: trees, density: this._treeWidgetOptions?.density }),
|
|
54
54
|
icon: _jsx(SvgHierarchyTree, {}),
|
|
55
55
|
priority: this._treeWidgetOptions?.defaultTreeWidgetPriority,
|
|
56
56
|
},
|
|
57
57
|
];
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Tree widget component which allows selecting which tree to render.
|
|
62
|
+
* @public
|
|
63
|
+
*/
|
|
64
|
+
export function TreeWidgetComponent(props) {
|
|
61
65
|
const ref = useTreeTransientState();
|
|
62
66
|
return (_jsx("div", { ref: ref, className: "tree-widget", children: _jsx(ErrorBoundary, { FallbackComponent: ErrorState, children: _jsx(SelectableTree, { ...props }) }) }));
|
|
63
67
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreeWidgetUiItemsProvider.js","sourceRoot":"","sources":["../../../src/components/TreeWidgetUiItemsProvider.tsx"],"names":[],"mappings":";AAAA;;;gGAGgG;AAEhG,OAAO,kCAAkC,CAAC;AAC1C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"TreeWidgetUiItemsProvider.js","sourceRoot":"","sources":["../../../src/components/TreeWidgetUiItemsProvider.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 \"./TreeWidgetUiItemsProvider.scss\";\nimport { StagePanelLocation, StagePanelSection, StageUsage } from \"@itwin/appui-react\";\nimport { SvgHierarchyTree } from \"@itwin/itwinui-icons-react\";\nimport { TreeWidget } from \"../TreeWidget\";\nimport { CategoriesTreeComponent } from \"./trees/category-tree/CategoriesTreeComponent\";\nimport { ModelsTreeComponent } from \"./trees/models-tree/ModelsTreeComponent\";\n\nimport type { UiItemsProvider, Widget } from \"@itwin/appui-react\";\nimport type { SelectableTreeProps, TreeDefinition } from \"./SelectableTree\";\nimport type { FallbackProps } from \"react-error-boundary\";\nimport { ErrorBoundary } from \"react-error-boundary\";\nimport { SelectableTree } from \"./SelectableTree\";\nimport { useTreeTransientState } from \"./utils/UseTreeTransientState\";\nimport { Button, NonIdealState } from \"@itwin/itwinui-react\";\nimport { SvgError } from \"@itwin/itwinui-illustrations-react\";\n/**\n * Parameters for creating a [[TreeWidgetUiItemsProvider]].\n * @public\n */\nexport interface TreeWidgetOptions {\n /** The stage panel to place the widget in. Defaults to `StagePanelLocation.Right`. */\n defaultPanelLocation?: StagePanelLocation;\n /** The stage panel section to place the widget in. Defaults to `StagePanelSection.Start`. */\n defaultPanelSection?: StagePanelSection;\n /** Widget priority in the stage panel. */\n defaultTreeWidgetPriority?: number;\n /** Trees to show in the widget. Defaults to [[ModelsTreeComponent]] and [[CategoriesTreeComponent]]. */\n trees?: TreeDefinition[];\n /** Modifies the density of the tree widget. `enlarged` widget contains larger content */\n density?: \"enlarged\" | \"default\";\n}\n\n/**\n * Id of the tree widget created by [[TreeWidgetUiItemsProvider]].\n * @public\n */\nexport const TreeWidgetId = \"tree-widget-react:trees\";\n\n/**\n * A [[UiItemsProvider]] implementation that provides a [[SelectableTree]] into a stage panel.\n * @public\n */\nexport class TreeWidgetUiItemsProvider implements UiItemsProvider {\n public readonly id = \"TreeWidgetUiItemsProvider\";\n\n constructor(private _treeWidgetOptions?: TreeWidgetOptions) {}\n\n public provideWidgets(_stageId: string, stageUsage: string, location: StagePanelLocation, section?: StagePanelSection): ReadonlyArray<Widget> {\n const preferredLocation = this._treeWidgetOptions?.defaultPanelLocation ?? StagePanelLocation.Right;\n const preferredPanelSection = this._treeWidgetOptions?.defaultPanelSection ?? StagePanelSection.Start;\n\n if (location !== preferredLocation || section !== preferredPanelSection || stageUsage !== StageUsage.General) {\n return [];\n }\n\n const trees: TreeDefinition[] = this._treeWidgetOptions?.trees ?? [\n {\n id: ModelsTreeComponent.id,\n getLabel: ModelsTreeComponent.getLabel,\n render: (props) => <ModelsTreeComponent density={props.density} />,\n },\n {\n id: CategoriesTreeComponent.id,\n getLabel: CategoriesTreeComponent.getLabel,\n render: (props) => <CategoriesTreeComponent density={props.density} />,\n },\n ];\n\n return [\n {\n id: TreeWidgetId,\n label: TreeWidget.translate(\"treeview\"),\n content: <TreeWidgetComponent trees={trees} density={this._treeWidgetOptions?.density} />,\n icon: <SvgHierarchyTree />,\n priority: this._treeWidgetOptions?.defaultTreeWidgetPriority,\n },\n ];\n }\n}\n\n/**\n * Tree widget component which allows selecting which tree to render.\n * @public\n */\nexport function TreeWidgetComponent(props: SelectableTreeProps) {\n const ref = useTreeTransientState<HTMLDivElement>();\n\n return (\n <div ref={ref} className=\"tree-widget\">\n <ErrorBoundary FallbackComponent={ErrorState}>\n <SelectableTree {...props} />\n </ErrorBoundary>\n </div>\n );\n}\n\nfunction ErrorState({ resetErrorBoundary }: FallbackProps) {\n return (\n <NonIdealState\n svg={<SvgError />}\n heading={TreeWidget.translate(\"error\")}\n description={TreeWidget.translate(\"generic-error-description\")}\n actions={\n <Button styleType={\"high-visibility\"} onClick={resetErrorBoundary}>\n {TreeWidget.translate(\"retry\")}\n </Button>\n }\n />\n );\n}"]}
|
|
@@ -5,6 +5,7 @@ import type { CommonProps } from "@itwin/core-react";
|
|
|
5
5
|
/** @internal */
|
|
6
6
|
export interface TreeHeaderButtonProps {
|
|
7
7
|
viewport: Viewport;
|
|
8
|
+
density?: "default" | "enlarged";
|
|
8
9
|
}
|
|
9
10
|
/** @internal */
|
|
10
11
|
export interface TreeHeaderProps extends CommonProps {
|
|
@@ -20,6 +21,8 @@ export interface TreeHeaderProps extends CommonProps {
|
|
|
20
21
|
onSelectedChanged: (index: number) => void;
|
|
21
22
|
/** Header buttons */
|
|
22
23
|
children?: React.ReactNode;
|
|
24
|
+
/** Modifies the density of tree header. `enlarged` header contains larger content */
|
|
25
|
+
density?: "default" | "enlarged";
|
|
23
26
|
}
|
|
24
27
|
/** @internal */
|
|
25
28
|
export declare function TreeHeader(props: TreeHeaderProps): JSX.Element;
|
|
@@ -11,11 +11,12 @@ import { ButtonGroup, Divider, DropdownMenu, IconButton, SearchBox } from "@itwi
|
|
|
11
11
|
import { TreeWidget } from "../../TreeWidget";
|
|
12
12
|
/** @internal */
|
|
13
13
|
export function TreeHeader(props) {
|
|
14
|
-
const { onFilterStart, onFilterClear, resultCount, selectedIndex, onSelectedChanged, children, className } = props;
|
|
14
|
+
const { onFilterStart, onFilterClear, resultCount, selectedIndex, onSelectedChanged, children, density, className } = props;
|
|
15
15
|
const [isSearchOpen, setIsSearchOpen] = useState(false);
|
|
16
|
-
|
|
16
|
+
const isEnlarged = density === "enlarged";
|
|
17
|
+
return (_jsxs("div", { className: classnames("tree-widget-tree-header", className, isEnlarged && "enlarge"), children: [_jsx(HeaderButtons, { contracted: isSearchOpen, isEnlarged: isEnlarged, children: children }), _jsx(DebouncedSearchBox, { isOpened: isSearchOpen, onOpen: () => setIsSearchOpen(true), onClose: () => setIsSearchOpen(false), onChange: (value) => (value ? onFilterStart(value) : onFilterClear()), delay: 500, selectedResultIndex: selectedIndex, resultCount: resultCount, onSelectedResultChanged: onSelectedChanged, size: isEnlarged ? "large" : "small" })] }));
|
|
17
18
|
}
|
|
18
|
-
function DebouncedSearchBox({ isOpened, selectedResultIndex, resultCount, onSelectedResultChanged, onChange, onOpen, onClose, delay, }) {
|
|
19
|
+
function DebouncedSearchBox({ isOpened, selectedResultIndex, resultCount, onSelectedResultChanged, onChange, onOpen, onClose, delay, size, }) {
|
|
19
20
|
const [inputValue, setInputValue] = useState("");
|
|
20
21
|
const onChangeRef = useRef(onChange);
|
|
21
22
|
// save latest `onChange` reference into `useRef` to avoid restarting timeout when `onChange` reference changes.
|
|
@@ -32,27 +33,28 @@ function DebouncedSearchBox({ isOpened, selectedResultIndex, resultCount, onSele
|
|
|
32
33
|
clearTimeout(timeoutId);
|
|
33
34
|
};
|
|
34
35
|
}, [inputValue, delay]);
|
|
35
|
-
return (_jsxs(SearchBox, { expandable: true, onExpand: onOpen, onCollapse: onClose, size:
|
|
36
|
+
return (_jsxs(SearchBox, { expandable: true, onExpand: onOpen, onCollapse: onClose, size: size, className: classnames("tree-widget-search-box", !isOpened && "contracted"), children: [_jsx(SearchBox.CollapsedState, { children: _jsx(SearchBox.ExpandButton, { title: TreeWidget.translate("searchBox.searchForSomething"), "aria-label": TreeWidget.translate("searchBox.open"), size: size }) }), _jsxs(SearchBox.ExpandedState, { children: [_jsx(SearchBox.Input, { placeholder: TreeWidget.translate("searchBox.search"), onChange: (e) => setInputValue(e.currentTarget.value) }), _jsx(SearchResultStepper, { selectedIndex: selectedResultIndex, total: resultCount, onStep: onSelectedResultChanged, size: size }), _jsx(SearchBox.CollapseButton, { onClick: () => {
|
|
36
37
|
setInputValue("");
|
|
37
38
|
onClose();
|
|
38
|
-
}, size:
|
|
39
|
+
}, size: size, "aria-label": TreeWidget.translate("searchBox.close") })] })] }));
|
|
39
40
|
}
|
|
40
41
|
function HeaderButtons(props) {
|
|
41
42
|
const className = classnames("button-container", props.contracted && "contracted");
|
|
43
|
+
const dropdownClassName = classnames("dropdown-item", props.isEnlarged && "enlarge");
|
|
42
44
|
return (_jsx(ButtonGroup, { className: className, overflowButton: (overflowStart) => (_jsx(DropdownMenu, { menuItems: () => Children.toArray(props.children)
|
|
43
|
-
.slice(overflowStart
|
|
44
|
-
.map((btn, index) => (_jsx("li", { className:
|
|
45
|
+
.slice(overflowStart)
|
|
46
|
+
.map((btn, index) => (_jsx("li", { className: dropdownClassName, role: "menuitem", children: btn }, index))), className: "tree-header-button-dropdown-container", children: _jsx(IconButton, { title: TreeWidget.translate("dropdownMore"), styleType: "borderless", size: props.isEnlarged ? undefined : "small", children: _jsx(SvgMore, {}) }) })), children: props.children }));
|
|
45
47
|
}
|
|
46
48
|
function SearchResultStepper(props) {
|
|
47
49
|
const { selectedIndex = 1, total, onStep } = props;
|
|
48
50
|
if (!total) {
|
|
49
51
|
return null;
|
|
50
52
|
}
|
|
51
|
-
return (_jsxs(_Fragment, { children: [_jsx("span", { className: "searchbox-stepping-count", children: `${selectedIndex}/${total}` }), _jsx(Divider, { orientation: "vertical" }), _jsx(SearchBox.Button, { title: TreeWidget.translate("searchBox.previous"), size:
|
|
53
|
+
return (_jsxs(_Fragment, { children: [_jsx("span", { className: "searchbox-stepping-count", children: `${selectedIndex}/${total}` }), _jsx(Divider, { orientation: "vertical" }), _jsx(SearchBox.Button, { title: TreeWidget.translate("searchBox.previous"), size: props.size, onClick: () => {
|
|
52
54
|
if (selectedIndex > 1) {
|
|
53
55
|
onStep(selectedIndex - 1);
|
|
54
56
|
}
|
|
55
|
-
}, children: _jsx(SvgCaretUpSmall, {}) }), _jsx(SearchBox.Button, { title: TreeWidget.translate("searchBox.next"), size:
|
|
57
|
+
}, children: _jsx(SvgCaretUpSmall, {}) }), _jsx(SearchBox.Button, { title: TreeWidget.translate("searchBox.next"), size: props.size, onClick: () => {
|
|
56
58
|
if (selectedIndex < total) {
|
|
57
59
|
onStep(selectedIndex + 1);
|
|
58
60
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreeHeader.js","sourceRoot":"","sources":["../../../../src/components/tree-header/TreeHeader.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 \"./TreeHeader.scss\";\nimport classnames from \"classnames\";\nimport { Children, useEffect, useRef, useState } from \"react\";\nimport { SvgCaretDownSmall, SvgCaretUpSmall, SvgMore } from \"@itwin/itwinui-icons-react\";\nimport { ButtonGroup, Divider, DropdownMenu, IconButton, SearchBox } from \"@itwin/itwinui-react\";\nimport { TreeWidget } from \"../../TreeWidget\";\n\nimport type { Viewport } from \"@itwin/core-frontend\";\nimport type { CommonProps } from \"@itwin/core-react\";\n\n/** @internal */\nexport interface TreeHeaderButtonProps {\n viewport: Viewport;\n}\n\n/** @internal */\nexport interface TreeHeaderProps extends CommonProps {\n /** Filtering is cleared after everything's loaded */\n onFilterStart: (newFilter: string) => void;\n /** listens for onClick event for Clear (x) icon */\n onFilterClear: () => void;\n /** Total number of results/entries */\n resultCount?: number;\n /** Current selected result index */\n selectedIndex?: number;\n /** Callback to currently selected result/entry change */\n onSelectedChanged: (index: number) => void;\n /** Header buttons */\n children?: React.ReactNode;\n}\n\n/** @internal */\nexport function TreeHeader(props: TreeHeaderProps) {\n const { onFilterStart, onFilterClear, resultCount, selectedIndex, onSelectedChanged, children, className } = props;\n const [isSearchOpen, setIsSearchOpen] = useState<boolean>(false);\n return (\n <div className={classnames(\"tree-widget-tree-header\", className)}>\n <HeaderButtons contracted={isSearchOpen}>{children}</HeaderButtons>\n <DebouncedSearchBox\n isOpened={isSearchOpen}\n onOpen={() => setIsSearchOpen(true)}\n onClose={() => setIsSearchOpen(false)}\n onChange={(value) => (value ? onFilterStart(value) : onFilterClear())}\n delay={500}\n selectedResultIndex={selectedIndex}\n resultCount={resultCount}\n onSelectedResultChanged={onSelectedChanged}\n />\n </div>\n );\n}\n\ninterface DebouncedSearchBoxProps {\n isOpened: boolean;\n onOpen: () => void;\n onClose: () => void;\n onChange: (value: string) => void;\n delay: number;\n selectedResultIndex?: number;\n resultCount?: number;\n onSelectedResultChanged: (index: number) => void;\n}\n\nfunction DebouncedSearchBox({\n isOpened,\n selectedResultIndex,\n resultCount,\n onSelectedResultChanged,\n onChange,\n onOpen,\n onClose,\n delay,\n}: DebouncedSearchBoxProps) {\n const [inputValue, setInputValue] = useState<string>(\"\");\n const onChangeRef = useRef(onChange);\n // save latest `onChange` reference into `useRef` to avoid restarting timeout when `onChange` reference changes.\n onChangeRef.current = onChange;\n\n useEffect(() => {\n if (!inputValue) {\n onChangeRef.current(\"\");\n return;\n }\n\n const timeoutId = setTimeout(() => {\n onChangeRef.current(inputValue);\n }, delay);\n\n return () => {\n clearTimeout(timeoutId);\n };\n }, [inputValue, delay]);\n\n return (\n <SearchBox expandable onExpand={onOpen} onCollapse={onClose} size=\"small\" className={classnames(\"tree-widget-search-box\", !isOpened && \"contracted\")}>\n <SearchBox.CollapsedState>\n <SearchBox.ExpandButton title={TreeWidget.translate(\"searchBox.searchForSomething\")} aria-label={TreeWidget.translate(\"searchBox.open\")} size=\"small\" />\n </SearchBox.CollapsedState>\n <SearchBox.ExpandedState>\n <SearchBox.Input\n placeholder={TreeWidget.translate(\"searchBox.search\")}\n onChange={(e) => setInputValue(e.currentTarget.value)}\n className=\"search-input\"\n />\n <SearchResultStepper selectedIndex={selectedResultIndex} total={resultCount} onStep={onSelectedResultChanged} />\n <SearchBox.CollapseButton\n onClick={() => {\n setInputValue(\"\");\n onClose();\n }}\n size=\"small\"\n aria-label={TreeWidget.translate(\"searchBox.close\")}\n />\n </SearchBox.ExpandedState>\n </SearchBox>\n );\n}\n\ninterface HeaderButtonsProps {\n contracted: boolean;\n children?: React.ReactNode;\n}\n\nfunction HeaderButtons(props: HeaderButtonsProps) {\n const className = classnames(\"button-container\", props.contracted && \"contracted\");\n\n return (\n <ButtonGroup\n className={className}\n overflowButton={(overflowStart) => (\n <DropdownMenu\n menuItems={() =>\n Children.toArray(props.children)\n .slice(overflowStart - 1)\n .map((btn, index) => (\n <li key={index} className=\"dropdown-item\" role=\"menuitem\">\n {btn}\n </li>\n ))\n }\n className=\"tree-header-button-dropdown-container\"\n >\n <IconButton styleType=\"borderless\" size=\"small\">\n <SvgMore />\n </IconButton>\n </DropdownMenu>\n )}\n >\n {props.children}\n </ButtonGroup>\n );\n}\n\ninterface SearchResultStepperProps {\n total?: number;\n onStep: (newIndex: number) => void;\n selectedIndex?: number;\n}\n\nfunction SearchResultStepper(props: SearchResultStepperProps) {\n const { selectedIndex = 1, total, onStep } = props;\n if (!total) {\n return null;\n }\n\n return (\n <>\n <span className=\"searchbox-stepping-count\">{`${selectedIndex}/${total}`}</span>\n <Divider orientation=\"vertical\" />\n <SearchBox.Button\n title={TreeWidget.translate(\"searchBox.previous\")}\n size=\"small\"\n onClick={() => {\n if (selectedIndex > 1) {\n onStep(selectedIndex - 1);\n }\n }}\n >\n <SvgCaretUpSmall />\n </SearchBox.Button>\n <SearchBox.Button\n title={TreeWidget.translate(\"searchBox.next\")}\n size=\"small\"\n onClick={() => {\n if (selectedIndex < total) {\n onStep(selectedIndex + 1);\n }\n }}\n >\n <SvgCaretDownSmall />\n </SearchBox.Button>\n </>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"TreeHeader.js","sourceRoot":"","sources":["../../../../src/components/tree-header/TreeHeader.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 \"./TreeHeader.scss\";\nimport classnames from \"classnames\";\nimport { Children, useEffect, useRef, useState } from \"react\";\nimport { SvgCaretDownSmall, SvgCaretUpSmall, SvgMore } from \"@itwin/itwinui-icons-react\";\nimport { ButtonGroup, Divider, DropdownMenu, IconButton, SearchBox } from \"@itwin/itwinui-react\";\nimport { TreeWidget } from \"../../TreeWidget\";\n\nimport type { Viewport } from \"@itwin/core-frontend\";\nimport type { CommonProps } from \"@itwin/core-react\";\n\n/** @internal */\nexport interface TreeHeaderButtonProps {\n viewport: Viewport;\n density?: \"default\" | \"enlarged\";\n}\n\n/** @internal */\nexport interface TreeHeaderProps extends CommonProps {\n /** Filtering is cleared after everything's loaded */\n onFilterStart: (newFilter: string) => void;\n /** listens for onClick event for Clear (x) icon */\n onFilterClear: () => void;\n /** Total number of results/entries */\n resultCount?: number;\n /** Current selected result index */\n selectedIndex?: number;\n /** Callback to currently selected result/entry change */\n onSelectedChanged: (index: number) => void;\n /** Header buttons */\n children?: React.ReactNode;\n /** Modifies the density of tree header. `enlarged` header contains larger content */\n density?: \"default\" | \"enlarged\";\n}\n\n/** @internal */\nexport function TreeHeader(props: TreeHeaderProps) {\n const { onFilterStart, onFilterClear, resultCount, selectedIndex, onSelectedChanged, children, density, className } = props;\n const [isSearchOpen, setIsSearchOpen] = useState<boolean>(false);\n const isEnlarged = density === \"enlarged\";\n return (\n <div className={classnames(\"tree-widget-tree-header\", className, isEnlarged && \"enlarge\")}>\n <HeaderButtons contracted={isSearchOpen} isEnlarged={isEnlarged}>\n {children}\n </HeaderButtons>\n <DebouncedSearchBox\n isOpened={isSearchOpen}\n onOpen={() => setIsSearchOpen(true)}\n onClose={() => setIsSearchOpen(false)}\n onChange={(value) => (value ? onFilterStart(value) : onFilterClear())}\n delay={500}\n selectedResultIndex={selectedIndex}\n resultCount={resultCount}\n onSelectedResultChanged={onSelectedChanged}\n size={isEnlarged ? \"large\" : \"small\"}\n />\n </div>\n );\n}\n\ninterface DebouncedSearchBoxProps {\n isOpened: boolean;\n onOpen: () => void;\n onClose: () => void;\n onChange: (value: string) => void;\n delay: number;\n selectedResultIndex?: number;\n resultCount?: number;\n onSelectedResultChanged: (index: number) => void;\n size?: \"large\" | \"small\";\n}\n\nfunction DebouncedSearchBox({\n isOpened,\n selectedResultIndex,\n resultCount,\n onSelectedResultChanged,\n onChange,\n onOpen,\n onClose,\n delay,\n size,\n}: DebouncedSearchBoxProps) {\n const [inputValue, setInputValue] = useState<string>(\"\");\n const onChangeRef = useRef(onChange);\n // save latest `onChange` reference into `useRef` to avoid restarting timeout when `onChange` reference changes.\n onChangeRef.current = onChange;\n\n useEffect(() => {\n if (!inputValue) {\n onChangeRef.current(\"\");\n return;\n }\n\n const timeoutId = setTimeout(() => {\n onChangeRef.current(inputValue);\n }, delay);\n\n return () => {\n clearTimeout(timeoutId);\n };\n }, [inputValue, delay]);\n\n return (\n <SearchBox expandable onExpand={onOpen} onCollapse={onClose} size={size} className={classnames(\"tree-widget-search-box\", !isOpened && \"contracted\")}>\n <SearchBox.CollapsedState>\n <SearchBox.ExpandButton\n title={TreeWidget.translate(\"searchBox.searchForSomething\")}\n aria-label={TreeWidget.translate(\"searchBox.open\")}\n size={size}\n />\n </SearchBox.CollapsedState>\n <SearchBox.ExpandedState>\n <SearchBox.Input\n placeholder={TreeWidget.translate(\"searchBox.search\")}\n onChange={(e) => setInputValue(e.currentTarget.value)}\n />\n <SearchResultStepper selectedIndex={selectedResultIndex} total={resultCount} onStep={onSelectedResultChanged} size={size} />\n <SearchBox.CollapseButton\n onClick={() => {\n setInputValue(\"\");\n onClose();\n }}\n size={size}\n aria-label={TreeWidget.translate(\"searchBox.close\")}\n />\n </SearchBox.ExpandedState>\n </SearchBox>\n );\n}\n\ninterface HeaderButtonsProps {\n contracted: boolean;\n children?: React.ReactNode;\n isEnlarged?: boolean;\n}\n\nfunction HeaderButtons(props: HeaderButtonsProps) {\n const className = classnames(\"button-container\", props.contracted && \"contracted\");\n const dropdownClassName = classnames(\"dropdown-item\", props.isEnlarged && \"enlarge\");\n\n return (\n <ButtonGroup\n className={className}\n overflowButton={(overflowStart) => (\n <DropdownMenu\n menuItems={() =>\n Children.toArray(props.children)\n .slice(overflowStart)\n .map((btn, index) => (\n <li key={index} className={dropdownClassName} role=\"menuitem\">\n {btn}\n </li>\n ))\n }\n className=\"tree-header-button-dropdown-container\"\n >\n <IconButton title={TreeWidget.translate(\"dropdownMore\")} styleType=\"borderless\" size={props.isEnlarged ? undefined : \"small\"}>\n <SvgMore />\n </IconButton>\n </DropdownMenu>\n )}\n >\n {props.children}\n </ButtonGroup>\n );\n}\n\ninterface SearchResultStepperProps {\n total?: number;\n onStep: (newIndex: number) => void;\n selectedIndex?: number;\n size?: \"large\" | \"small\";\n}\n\nfunction SearchResultStepper(props: SearchResultStepperProps) {\n const { selectedIndex = 1, total, onStep } = props;\n if (!total) {\n return null;\n }\n\n return (\n <>\n <span className=\"searchbox-stepping-count\">{`${selectedIndex}/${total}`}</span>\n <Divider orientation=\"vertical\" />\n <SearchBox.Button\n title={TreeWidget.translate(\"searchBox.previous\")}\n size={props.size}\n onClick={() => {\n if (selectedIndex > 1) {\n onStep(selectedIndex - 1);\n }\n }}\n >\n <SvgCaretUpSmall />\n </SearchBox.Button>\n <SearchBox.Button\n title={TreeWidget.translate(\"searchBox.next\")}\n size={props.size}\n onClick={() => {\n if (selectedIndex < total) {\n onStep(selectedIndex + 1);\n }\n }}\n >\n <SvgCaretDownSmall />\n </SearchBox.Button>\n </>\n );\n}\n"]}
|
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
width: 100%;
|
|
15
15
|
height: var(--iui-size-xl);
|
|
16
16
|
|
|
17
|
+
&.enlarge {
|
|
18
|
+
height: calc(var(--iui-size-xl) + var(--iui-size-m));
|
|
19
|
+
}
|
|
20
|
+
|
|
17
21
|
> * {
|
|
18
22
|
width: 100%;
|
|
19
23
|
height: 100%;
|
|
@@ -66,4 +70,28 @@
|
|
|
66
70
|
width: var(--iui-size-xl);
|
|
67
71
|
}
|
|
68
72
|
}
|
|
73
|
+
|
|
74
|
+
&.enlarge {
|
|
75
|
+
--enlarged-header-height: calc(var(--iui-size-xl) + var(--iui-size-m));
|
|
76
|
+
|
|
77
|
+
height: var(--enlarged-header-height);
|
|
78
|
+
min-width: calc(100% - var(--enlarged-header-height));
|
|
79
|
+
|
|
80
|
+
.tree-widget-search-box {
|
|
81
|
+
height: var(--enlarged-header-height);
|
|
82
|
+
width: calc(100% - var(--enlarged-header-height));
|
|
83
|
+
|
|
84
|
+
&.contracted {
|
|
85
|
+
width: var(--enlarged-header-height);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.button-container {
|
|
90
|
+
width: calc(100% - var(--enlarged-header-height));
|
|
91
|
+
|
|
92
|
+
&.contracted {
|
|
93
|
+
width: var(--enlarged-header-height);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
69
97
|
}
|
|
@@ -16,6 +16,7 @@ import { useTreeFilteringState } from "../../TreeFilteringState";
|
|
|
16
16
|
import { AutoSizer } from "../../utils/AutoSizer";
|
|
17
17
|
import { CategoryTree } from "./CategoriesTree";
|
|
18
18
|
import { CategoryVisibilityHandler, hideAllCategories, invertAllCategories, showAllCategories, useCategories } from "./CategoryVisibilityHandler";
|
|
19
|
+
import classNames from "classnames";
|
|
19
20
|
/**
|
|
20
21
|
* A component that renders [[CategoriesTree]] and a header with filtering capabilities
|
|
21
22
|
* and header buttons.
|
|
@@ -58,6 +59,7 @@ function CategoriesTreeComponentImpl(props) {
|
|
|
58
59
|
const categories = useCategories(IModelApp.viewManager, props.iModel, props.viewport);
|
|
59
60
|
const [filteredCategories, setFilteredCategories] = useState();
|
|
60
61
|
const { searchOptions, filterString, onFilterApplied, filteredProvider } = useTreeFilteringState();
|
|
62
|
+
const contentClassName = classNames("tree-widget-tree-content", props.density === "enlarged" && "enlarge");
|
|
61
63
|
useEffect(() => {
|
|
62
64
|
void (async () => {
|
|
63
65
|
if (filteredProvider) {
|
|
@@ -68,13 +70,13 @@ function CategoriesTreeComponentImpl(props) {
|
|
|
68
70
|
}
|
|
69
71
|
})();
|
|
70
72
|
}, [filteredProvider]);
|
|
71
|
-
return (_jsxs("div", { className: "tree-widget-tree-with-header", children: [_jsx(TreeHeader, { onFilterClear: searchOptions.onFilterCancel, onFilterStart: searchOptions.onFilterStart, onSelectedChanged: searchOptions.onResultSelectedChanged, resultCount: searchOptions.matchedResultCount, selectedIndex: searchOptions.activeMatchIndex, children: props.headerButtons
|
|
73
|
+
return (_jsxs("div", { className: "tree-widget-tree-with-header", children: [_jsx(TreeHeader, { onFilterClear: searchOptions.onFilterCancel, onFilterStart: searchOptions.onFilterStart, onSelectedChanged: searchOptions.onResultSelectedChanged, resultCount: searchOptions.matchedResultCount, selectedIndex: searchOptions.activeMatchIndex, density: props.density, children: props.headerButtons
|
|
72
74
|
? props.headerButtons.map((btn, index) => _jsx(Fragment, { children: btn({ viewport: props.viewport, categories, filteredCategories }) }, index))
|
|
73
75
|
: [
|
|
74
|
-
_jsx(ShowAllButton, { viewport: props.viewport, categories: categories, filteredCategories: filteredCategories }, "show-all-btn"),
|
|
75
|
-
_jsx(HideAllButton, { viewport: props.viewport, categories: categories, filteredCategories: filteredCategories }, "hide-all-btn"),
|
|
76
|
-
_jsx(InvertAllButton, { viewport: props.viewport, categories: categories, filteredCategories: filteredCategories }, "invert-all-btn"),
|
|
77
|
-
] }), _jsx("div", { className:
|
|
76
|
+
_jsx(ShowAllButton, { viewport: props.viewport, categories: categories, filteredCategories: filteredCategories, density: props.density }, "show-all-btn"),
|
|
77
|
+
_jsx(HideAllButton, { viewport: props.viewport, categories: categories, filteredCategories: filteredCategories, density: props.density }, "hide-all-btn"),
|
|
78
|
+
_jsx(InvertAllButton, { viewport: props.viewport, categories: categories, filteredCategories: filteredCategories, density: props.density }, "invert-all-btn"),
|
|
79
|
+
] }), _jsx("div", { className: contentClassName, children: _jsx(AutoSizer, { children: ({ width, height }) => (_jsx(CategoryTree, { ...props, categories: categories, width: width, height: height, filterInfo: { filter: filterString, activeMatchIndex: searchOptions.activeMatchIndex }, onFilterApplied: onFilterApplied, activeView: props.viewport })) }) })] }));
|
|
78
80
|
}
|
|
79
81
|
async function getFilteredCategories(filteredProvider) {
|
|
80
82
|
const filteredCategories = [];
|
|
@@ -94,12 +96,12 @@ async function getFilteredCategories(filteredProvider) {
|
|
|
94
96
|
return filteredCategories;
|
|
95
97
|
}
|
|
96
98
|
function ShowAllButton(props) {
|
|
97
|
-
return (_jsx(IconButton, { size: "small", styleType: "borderless", title: TreeWidget.translate("showAll"), onClick: () => void showAllCategories((props.filteredCategories ?? props.categories).map((category) => category.categoryId), props.viewport), children: _jsx(SvgVisibilityShow, {}) }));
|
|
99
|
+
return (_jsx(IconButton, { size: props.density === "enlarged" ? "large" : "small", styleType: "borderless", title: TreeWidget.translate("showAll"), onClick: () => void showAllCategories((props.filteredCategories ?? props.categories).map((category) => category.categoryId), props.viewport), children: _jsx(SvgVisibilityShow, {}) }));
|
|
98
100
|
}
|
|
99
101
|
function HideAllButton(props) {
|
|
100
|
-
return (_jsx(IconButton, { size: "small", styleType: "borderless", title: TreeWidget.translate("hideAll"), onClick: () => void hideAllCategories((props.filteredCategories ?? props.categories).map((category) => category.categoryId), props.viewport), children: _jsx(SvgVisibilityHide, {}) }));
|
|
102
|
+
return (_jsx(IconButton, { size: props.density === "enlarged" ? "large" : "small", styleType: "borderless", title: TreeWidget.translate("hideAll"), onClick: () => void hideAllCategories((props.filteredCategories ?? props.categories).map((category) => category.categoryId), props.viewport), children: _jsx(SvgVisibilityHide, {}) }));
|
|
101
103
|
}
|
|
102
104
|
function InvertAllButton(props) {
|
|
103
|
-
return (_jsx(IconButton, { title: TreeWidget.translate("invert"), size: "small", styleType: "borderless", onClick: () => void invertAllCategories(props.filteredCategories ?? props.categories, props.viewport), children: _jsx(SvgVisibilityHalf, {}) }));
|
|
105
|
+
return (_jsx(IconButton, { title: TreeWidget.translate("invert"), size: props.density === "enlarged" ? "large" : "small", styleType: "borderless", onClick: () => void invertAllCategories(props.filteredCategories ?? props.categories, props.viewport), children: _jsx(SvgVisibilityHalf, {}) }));
|
|
104
106
|
}
|
|
105
107
|
//# sourceMappingURL=CategoriesTreeComponent.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CategoriesTreeComponent.js","sourceRoot":"","sources":["../../../../../src/components/trees/category-tree/CategoriesTreeComponent.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 \"../VisibilityTreeBase.scss\";\nimport { Fragment, useEffect, useState } from \"react\";\nimport { useActiveIModelConnection, useActiveViewport } from \"@itwin/appui-react\";\nimport { IModelApp } from \"@itwin/core-frontend\";\nimport { SvgVisibilityHalf, SvgVisibilityHide, SvgVisibilityShow } from \"@itwin/itwinui-icons-react\";\nimport { IconButton } from \"@itwin/itwinui-react\";\nimport { isPresentationTreeNodeItem } from \"@itwin/presentation-components\";\nimport { TreeWidget } from \"../../../TreeWidget\";\nimport { TreeHeader } from \"../../tree-header/TreeHeader\";\nimport { useTreeFilteringState } from \"../../TreeFilteringState\";\nimport { AutoSizer } from \"../../utils/AutoSizer\";\nimport { CategoryTree } from \"./CategoriesTree\";\nimport { CategoryVisibilityHandler, hideAllCategories, invertAllCategories, showAllCategories, useCategories } from \"./CategoryVisibilityHandler\";\n\nimport type { IModelConnection, ScreenViewport } from \"@itwin/core-frontend\";\nimport type { IPresentationTreeDataProvider } from \"@itwin/presentation-components\";\nimport type { TreeHeaderButtonProps } from \"../../tree-header/TreeHeader\";\nimport type { CategoryTreeProps } from \"./CategoriesTree\";\nimport type { CategoryInfo } from \"./CategoryVisibilityHandler\";\n\n/**\n * Props that get passed to [[CategoriesTreeComponent]] header button renderer.\n * @see CategoriesTreeComponentProps.headerButtons\n * @public\n */\nexport interface CategoriesTreeHeaderButtonProps extends TreeHeaderButtonProps {\n /** A list of categories available in the iModel */\n categories: CategoryInfo[];\n /** In case the tree is filtered, a list of filtered categories. */\n filteredCategories?: CategoryInfo[];\n}\n\n/**\n * Props for [[CategoriesTreeComponent]].\n * @public\n */\nexport interface CategoriesTreeComponentProps\n extends Omit<\n CategoryTreeProps,\n \"iModel\" | \"activeView\" | \"width\" | \"height\" | \"filterInfo\" | \"onFilterApplied\" | \"categories\" | \"categoryVisibilityHandler\" | \"viewManager\"\n > {\n /**\n * Renderers of header buttons. Defaults to:\n * ```ts\n * [\n * CategoriesTreeComponent.ShowAllButton,\n * CategoriesTreeComponent.HideAllButton,\n * CategoriesTreeComponent.InvertAllButton,\n * ]\n * ```\n */\n headerButtons?: Array<(props: CategoriesTreeHeaderButtonProps) => React.ReactNode>;\n}\n\n/**\n * A component that renders [[CategoriesTree]] and a header with filtering capabilities\n * and header buttons.\n * @public\n */\nexport const CategoriesTreeComponent = (props: CategoriesTreeComponentProps) => {\n const iModel = useActiveIModelConnection();\n const viewport = useActiveViewport();\n\n if (!iModel || !viewport) {\n return null;\n }\n\n return <CategoriesTreeComponentImpl {...props} iModel={iModel} viewport={viewport} />;\n};\n\n/**\n * Renders a \"Show all\" button that enables display of all categories and their subcategories.\n * @public\n */\nCategoriesTreeComponent.ShowAllButton = ShowAllButton;\n\n/**\n * Renders a \"Hide all\" button that disables display of all categories.\n * @public\n */\nCategoriesTreeComponent.HideAllButton = HideAllButton;\n\n/**\n * Renders an \"Invert all\" button that inverts display of all categories.\n * @public\n */\nCategoriesTreeComponent.InvertAllButton = InvertAllButton;\n\n/**\n * Id of the component. May be used when a creating a [[TreeDefinition]] for [[SelectableTree]].\n * @public\n */\nCategoriesTreeComponent.id = \"categories-tree\";\n\n/**\n * Label of the component. May be used when a creating a [[TreeDefinition]] for [[SelectableTree]].\n * @public\n */\nCategoriesTreeComponent.getLabel = () => TreeWidget.translate(\"categories\");\n\nfunction CategoriesTreeComponentImpl(props: CategoriesTreeComponentProps & { iModel: IModelConnection; viewport: ScreenViewport }) {\n const categories = useCategories(IModelApp.viewManager, props.iModel, props.viewport);\n const [filteredCategories, setFilteredCategories] = useState<CategoryInfo[]>();\n const { searchOptions, filterString, onFilterApplied, filteredProvider } = useTreeFilteringState();\n\n useEffect(() => {\n void (async () => {\n if (filteredProvider) {\n setFilteredCategories(await getFilteredCategories(filteredProvider));\n } else {\n setFilteredCategories(undefined);\n }\n })();\n }, [filteredProvider]);\n\n return (\n <div className=\"tree-widget-tree-with-header\">\n <TreeHeader\n onFilterClear={searchOptions.onFilterCancel}\n onFilterStart={searchOptions.onFilterStart}\n onSelectedChanged={searchOptions.onResultSelectedChanged}\n resultCount={searchOptions.matchedResultCount}\n selectedIndex={searchOptions.activeMatchIndex}\n >\n {props.headerButtons\n ? props.headerButtons.map((btn, index) => <Fragment key={index}>{btn({ viewport: props.viewport, categories, filteredCategories })}</Fragment>)\n : [\n <ShowAllButton viewport={props.viewport} categories={categories} filteredCategories={filteredCategories} key=\"show-all-btn\" />,\n <HideAllButton viewport={props.viewport} categories={categories} filteredCategories={filteredCategories} key=\"hide-all-btn\" />,\n <InvertAllButton viewport={props.viewport} categories={categories} filteredCategories={filteredCategories} key=\"invert-all-btn\" />,\n ]}\n </TreeHeader>\n <div className=\"tree-widget-tree-content\">\n <AutoSizer>\n {({ width, height }) => (\n <CategoryTree\n {...props}\n categories={categories}\n width={width}\n height={height}\n filterInfo={{ filter: filterString, activeMatchIndex: searchOptions.activeMatchIndex }}\n onFilterApplied={onFilterApplied}\n activeView={props.viewport}\n />\n )}\n </AutoSizer>\n </div>\n </div>\n );\n}\n\nasync function getFilteredCategories(filteredProvider: IPresentationTreeDataProvider) {\n const filteredCategories: CategoryInfo[] = [];\n const nodes = await filteredProvider.getNodes();\n for (const node of nodes) {\n if (!isPresentationTreeNodeItem(node)) {\n continue;\n }\n const filteredCategoryId = CategoryVisibilityHandler.getInstanceIdFromTreeNodeKey(node.key);\n const filteredSubCategoriesIds = node.hasChildren\n ? (await filteredProvider.getNodes(node))\n .filter(isPresentationTreeNodeItem)\n .map((child) => CategoryVisibilityHandler.getInstanceIdFromTreeNodeKey(child.key))\n : [];\n filteredCategories.push({ categoryId: filteredCategoryId, subCategoryIds: filteredSubCategoriesIds });\n }\n return filteredCategories;\n}\n\nfunction ShowAllButton(props: CategoriesTreeHeaderButtonProps) {\n return (\n <IconButton\n size=\"small\"\n styleType=\"borderless\"\n title={TreeWidget.translate(\"showAll\")}\n onClick={() =>\n void showAllCategories(\n (props.filteredCategories ?? props.categories).map((category) => category.categoryId),\n props.viewport,\n )\n }\n >\n <SvgVisibilityShow />\n </IconButton>\n );\n}\n\nfunction HideAllButton(props: CategoriesTreeHeaderButtonProps) {\n return (\n <IconButton\n size=\"small\"\n styleType=\"borderless\"\n title={TreeWidget.translate(\"hideAll\")}\n onClick={() =>\n void hideAllCategories(\n (props.filteredCategories ?? props.categories).map((category) => category.categoryId),\n props.viewport,\n )\n }\n >\n <SvgVisibilityHide />\n </IconButton>\n );\n}\n\nfunction InvertAllButton(props: CategoriesTreeHeaderButtonProps) {\n return (\n <IconButton\n title={TreeWidget.translate(\"invert\")}\n size=\"small\"\n styleType=\"borderless\"\n onClick={() => void invertAllCategories(props.filteredCategories ?? props.categories, props.viewport)}\n >\n <SvgVisibilityHalf />\n </IconButton>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"CategoriesTreeComponent.js","sourceRoot":"","sources":["../../../../../src/components/trees/category-tree/CategoriesTreeComponent.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 \"../VisibilityTreeBase.scss\";\nimport { Fragment, useEffect, useState } from \"react\";\nimport { useActiveIModelConnection, useActiveViewport } from \"@itwin/appui-react\";\nimport { IModelApp } from \"@itwin/core-frontend\";\nimport { SvgVisibilityHalf, SvgVisibilityHide, SvgVisibilityShow } from \"@itwin/itwinui-icons-react\";\nimport { IconButton } from \"@itwin/itwinui-react\";\nimport { isPresentationTreeNodeItem } from \"@itwin/presentation-components\";\nimport { TreeWidget } from \"../../../TreeWidget\";\nimport { TreeHeader } from \"../../tree-header/TreeHeader\";\nimport { useTreeFilteringState } from \"../../TreeFilteringState\";\nimport { AutoSizer } from \"../../utils/AutoSizer\";\nimport { CategoryTree } from \"./CategoriesTree\";\nimport { CategoryVisibilityHandler, hideAllCategories, invertAllCategories, showAllCategories, useCategories } from \"./CategoryVisibilityHandler\";\n\nimport type { IModelConnection, ScreenViewport } from \"@itwin/core-frontend\";\nimport type { IPresentationTreeDataProvider } from \"@itwin/presentation-components\";\nimport type { TreeHeaderButtonProps } from \"../../tree-header/TreeHeader\";\nimport type { CategoryTreeProps } from \"./CategoriesTree\";\nimport type { CategoryInfo } from \"./CategoryVisibilityHandler\";\nimport classNames from \"classnames\";\n\n/**\n * Props that get passed to [[CategoriesTreeComponent]] header button renderer.\n * @see CategoriesTreeComponentProps.headerButtons\n * @public\n */\nexport interface CategoriesTreeHeaderButtonProps extends TreeHeaderButtonProps {\n /** A list of categories available in the iModel */\n categories: CategoryInfo[];\n /** In case the tree is filtered, a list of filtered categories. */\n filteredCategories?: CategoryInfo[];\n}\n\n/**\n * Props for [[CategoriesTreeComponent]].\n * @public\n */\nexport interface CategoriesTreeComponentProps\n extends Omit<\n CategoryTreeProps,\n \"iModel\" | \"activeView\" | \"width\" | \"height\" | \"filterInfo\" | \"onFilterApplied\" | \"categories\" | \"categoryVisibilityHandler\" | \"viewManager\"\n > {\n /**\n * Renderers of header buttons. Defaults to:\n * ```ts\n * [\n * CategoriesTreeComponent.ShowAllButton,\n * CategoriesTreeComponent.HideAllButton,\n * CategoriesTreeComponent.InvertAllButton,\n * ]\n * ```\n */\n headerButtons?: Array<(props: CategoriesTreeHeaderButtonProps) => React.ReactNode>;\n}\n\n/**\n * A component that renders [[CategoriesTree]] and a header with filtering capabilities\n * and header buttons.\n * @public\n */\nexport const CategoriesTreeComponent = (props: CategoriesTreeComponentProps) => {\n const iModel = useActiveIModelConnection();\n const viewport = useActiveViewport();\n\n if (!iModel || !viewport) {\n return null;\n }\n\n return <CategoriesTreeComponentImpl {...props} iModel={iModel} viewport={viewport} />;\n};\n\n/**\n * Renders a \"Show all\" button that enables display of all categories and their subcategories.\n * @public\n */\nCategoriesTreeComponent.ShowAllButton = ShowAllButton;\n\n/**\n * Renders a \"Hide all\" button that disables display of all categories.\n * @public\n */\nCategoriesTreeComponent.HideAllButton = HideAllButton;\n\n/**\n * Renders an \"Invert all\" button that inverts display of all categories.\n * @public\n */\nCategoriesTreeComponent.InvertAllButton = InvertAllButton;\n\n/**\n * Id of the component. May be used when a creating a [[TreeDefinition]] for [[SelectableTree]].\n * @public\n */\nCategoriesTreeComponent.id = \"categories-tree\";\n\n/**\n * Label of the component. May be used when a creating a [[TreeDefinition]] for [[SelectableTree]].\n * @public\n */\nCategoriesTreeComponent.getLabel = () => TreeWidget.translate(\"categories\");\n\nfunction CategoriesTreeComponentImpl(props: CategoriesTreeComponentProps & { iModel: IModelConnection; viewport: ScreenViewport }) {\n const categories = useCategories(IModelApp.viewManager, props.iModel, props.viewport);\n const [filteredCategories, setFilteredCategories] = useState<CategoryInfo[]>();\n const { searchOptions, filterString, onFilterApplied, filteredProvider } = useTreeFilteringState();\n const contentClassName = classNames(\"tree-widget-tree-content\", props.density === \"enlarged\" && \"enlarge\");\n\n useEffect(() => {\n void (async () => {\n if (filteredProvider) {\n setFilteredCategories(await getFilteredCategories(filteredProvider));\n } else {\n setFilteredCategories(undefined);\n }\n })();\n }, [filteredProvider]);\n\n return (\n <div className=\"tree-widget-tree-with-header\">\n <TreeHeader\n onFilterClear={searchOptions.onFilterCancel}\n onFilterStart={searchOptions.onFilterStart}\n onSelectedChanged={searchOptions.onResultSelectedChanged}\n resultCount={searchOptions.matchedResultCount}\n selectedIndex={searchOptions.activeMatchIndex}\n density={props.density}\n >\n {props.headerButtons\n ? props.headerButtons.map((btn, index) => <Fragment key={index}>{btn({ viewport: props.viewport, categories, filteredCategories })}</Fragment>)\n : [\n <ShowAllButton\n viewport={props.viewport}\n categories={categories}\n filteredCategories={filteredCategories}\n key=\"show-all-btn\"\n density={props.density}\n />,\n <HideAllButton\n viewport={props.viewport}\n categories={categories}\n filteredCategories={filteredCategories}\n key=\"hide-all-btn\"\n density={props.density}\n />,\n <InvertAllButton\n viewport={props.viewport}\n categories={categories}\n filteredCategories={filteredCategories}\n key=\"invert-all-btn\"\n density={props.density}\n />,\n ]}\n </TreeHeader>\n <div className={contentClassName}>\n <AutoSizer>\n {({ width, height }) => (\n <CategoryTree\n {...props}\n categories={categories}\n width={width}\n height={height}\n filterInfo={{ filter: filterString, activeMatchIndex: searchOptions.activeMatchIndex }}\n onFilterApplied={onFilterApplied}\n activeView={props.viewport}\n />\n )}\n </AutoSizer>\n </div>\n </div>\n );\n}\n\nasync function getFilteredCategories(filteredProvider: IPresentationTreeDataProvider) {\n const filteredCategories: CategoryInfo[] = [];\n const nodes = await filteredProvider.getNodes();\n for (const node of nodes) {\n if (!isPresentationTreeNodeItem(node)) {\n continue;\n }\n const filteredCategoryId = CategoryVisibilityHandler.getInstanceIdFromTreeNodeKey(node.key);\n const filteredSubCategoriesIds = node.hasChildren\n ? (await filteredProvider.getNodes(node))\n .filter(isPresentationTreeNodeItem)\n .map((child) => CategoryVisibilityHandler.getInstanceIdFromTreeNodeKey(child.key))\n : [];\n filteredCategories.push({ categoryId: filteredCategoryId, subCategoryIds: filteredSubCategoriesIds });\n }\n return filteredCategories;\n}\n\nfunction ShowAllButton(props: CategoriesTreeHeaderButtonProps) {\n return (\n <IconButton\n size={props.density === \"enlarged\" ? \"large\" : \"small\"}\n styleType=\"borderless\"\n title={TreeWidget.translate(\"showAll\")}\n onClick={() =>\n void showAllCategories(\n (props.filteredCategories ?? props.categories).map((category) => category.categoryId),\n props.viewport,\n )\n }\n >\n <SvgVisibilityShow />\n </IconButton>\n );\n}\n\nfunction HideAllButton(props: CategoriesTreeHeaderButtonProps) {\n return (\n <IconButton\n size={props.density === \"enlarged\" ? \"large\" : \"small\"}\n styleType=\"borderless\"\n title={TreeWidget.translate(\"hideAll\")}\n onClick={() =>\n void hideAllCategories(\n (props.filteredCategories ?? props.categories).map((category) => category.categoryId),\n props.viewport,\n )\n }\n >\n <SvgVisibilityHide />\n </IconButton>\n );\n}\n\nfunction InvertAllButton(props: CategoriesTreeHeaderButtonProps) {\n return (\n <IconButton\n title={TreeWidget.translate(\"invert\")}\n size={props.density === \"enlarged\" ? \"large\" : \"small\"}\n styleType=\"borderless\"\n onClick={() => void invertAllCategories(props.filteredCategories ?? props.categories, props.viewport)}\n >\n <SvgVisibilityHalf />\n </IconButton>\n );\n}\n"]}
|
|
@@ -44,8 +44,8 @@ export declare class CategoryVisibilityHandler implements IVisibilityHandler {
|
|
|
44
44
|
onVisibilityChange: BeEvent<VisibilityChangeListener>;
|
|
45
45
|
getVisibilityStatus(node: TreeNodeItem): VisibilityStatus;
|
|
46
46
|
changeVisibility(node: TreeNodeItem, shouldDisplay: boolean): Promise<void>;
|
|
47
|
-
getSubCategoryVisibility(id: string): "
|
|
48
|
-
getCategoryVisibility(id: string): "
|
|
47
|
+
getSubCategoryVisibility(id: string): "visible" | "hidden";
|
|
48
|
+
getCategoryVisibility(id: string): "visible" | "hidden";
|
|
49
49
|
getParent(key: string): CategoryInfo | undefined;
|
|
50
50
|
private onDisplayStyleChanged;
|
|
51
51
|
private onViewedCategoriesChanged;
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
.tree-widget-tree-with-header {
|
|
7
7
|
width: 100%;
|
|
8
8
|
height: 100%;
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
9
11
|
|
|
10
12
|
.tree-widget-tree-header {
|
|
11
13
|
height: var(--iui-size-xl);
|
|
@@ -13,6 +15,10 @@
|
|
|
13
15
|
|
|
14
16
|
.tree-widget-tree-content {
|
|
15
17
|
height: calc(100% - var(--iui-size-xl));
|
|
18
|
+
|
|
19
|
+
&.enlarge {
|
|
20
|
+
height: calc(100% - var(--iui-size-xl) - var(--iui-size-m));
|
|
21
|
+
}
|
|
16
22
|
}
|
|
17
23
|
}
|
|
18
24
|
|
|
@@ -28,6 +34,12 @@
|
|
|
28
34
|
}
|
|
29
35
|
|
|
30
36
|
.core-tree-node {
|
|
37
|
+
> .contents {
|
|
38
|
+
.core-tree-node-icon {
|
|
39
|
+
line-height: 0;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
31
43
|
&.without-expander {
|
|
32
44
|
> .contents {
|
|
33
45
|
> .core-tree-node-icon {
|
|
@@ -49,10 +61,30 @@
|
|
|
49
61
|
margin-left: var(--enlarged-node-without-expander-margin);
|
|
50
62
|
}
|
|
51
63
|
|
|
64
|
+
> .presentation-components-node-action-buttons {
|
|
65
|
+
height: var(--enlarged-node-height);
|
|
66
|
+
width: min-content;
|
|
67
|
+
|
|
68
|
+
.presentation-components-node-action-button {
|
|
69
|
+
height: var(--enlarged-node-height);
|
|
70
|
+
width: var(--enlarged-node-height);
|
|
71
|
+
|
|
72
|
+
svg {
|
|
73
|
+
height: var(--enlarged-node-height);
|
|
74
|
+
width: var(--enlarged-node-height);
|
|
75
|
+
padding: var(--iui-size-s);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
52
80
|
> .contents {
|
|
53
81
|
height: var(--enlarged-node-height);
|
|
54
82
|
font-size: var(--iui-font-size-2);
|
|
55
83
|
|
|
84
|
+
.core-progress-indicator {
|
|
85
|
+
margin: calc(var(--enlarged-node-icon-padding) / 2);
|
|
86
|
+
}
|
|
87
|
+
|
|
56
88
|
/* stylelint-disable-next-line selector-class-pattern */
|
|
57
89
|
.core-tree-expansionToggle {
|
|
58
90
|
> .icon {
|
|
@@ -15,6 +15,7 @@ import { AutoSizer } from "../../utils/AutoSizer";
|
|
|
15
15
|
import { ModelsTree } from "./ModelsTree";
|
|
16
16
|
import { areAllModelsVisible, hideAllModels, invertAllModels, showAllModels, toggleModels } from "./ModelsVisibilityHandler";
|
|
17
17
|
import { queryModelsForHeaderActions } from "./Utils";
|
|
18
|
+
import classNames from "classnames";
|
|
18
19
|
/**
|
|
19
20
|
* A component that renders [[ModelsTree]] and a header with filtering capabilities
|
|
20
21
|
* and header buttons.
|
|
@@ -67,6 +68,7 @@ function ModelsTreeComponentImpl(props) {
|
|
|
67
68
|
const [availableModels, setAvailableModels] = useState([]);
|
|
68
69
|
const { viewport, iModel } = props;
|
|
69
70
|
const { searchOptions, filterString, onFilterApplied } = useTreeFilteringState();
|
|
71
|
+
const contentClassName = classNames("tree-widget-tree-content", props.density === "enlarged" && "enlarge");
|
|
70
72
|
useEffect(() => {
|
|
71
73
|
queryModelsForHeaderActions(iModel)
|
|
72
74
|
.then((modelInfos) => {
|
|
@@ -77,24 +79,24 @@ function ModelsTreeComponentImpl(props) {
|
|
|
77
79
|
});
|
|
78
80
|
}, [iModel]);
|
|
79
81
|
const filterInfo = useMemo(() => ({ filter: filterString, activeMatchIndex: searchOptions.activeMatchIndex }), [filterString, searchOptions.activeMatchIndex]);
|
|
80
|
-
return (_jsxs("div", { className: "tree-widget-tree-with-header", children: [_jsx(TreeHeader, { onFilterClear: searchOptions.onFilterCancel, onFilterStart: searchOptions.onFilterStart, onSelectedChanged: searchOptions.onResultSelectedChanged, resultCount: searchOptions.matchedResultCount, selectedIndex: searchOptions.activeMatchIndex, children: props.headerButtons
|
|
82
|
+
return (_jsxs("div", { className: "tree-widget-tree-with-header", children: [_jsx(TreeHeader, { onFilterClear: searchOptions.onFilterCancel, onFilterStart: searchOptions.onFilterStart, onSelectedChanged: searchOptions.onResultSelectedChanged, resultCount: searchOptions.matchedResultCount, selectedIndex: searchOptions.activeMatchIndex, density: props.density, children: props.headerButtons
|
|
81
83
|
? props.headerButtons.map((btn, index) => _jsx(Fragment, { children: btn({ viewport, models: availableModels }) }, index))
|
|
82
84
|
: [
|
|
83
|
-
_jsx(ShowAllButton, { viewport: viewport, models: availableModels }, "show-all-btn"),
|
|
84
|
-
_jsx(HideAllButton, { viewport: viewport, models: availableModels }, "hide-all-btn"),
|
|
85
|
-
_jsx(InvertButton, { viewport: viewport, models: availableModels }, "invert-all-btn"),
|
|
86
|
-
_jsx(View2DButton, { viewport: viewport, models: availableModels }, "view-2d-btn"),
|
|
87
|
-
_jsx(View3DButton, { viewport: viewport, models: availableModels }, "view-3d-btn"),
|
|
88
|
-
] }), _jsx("div", { className:
|
|
85
|
+
_jsx(ShowAllButton, { viewport: viewport, models: availableModels, density: props.density }, "show-all-btn"),
|
|
86
|
+
_jsx(HideAllButton, { viewport: viewport, models: availableModels, density: props.density }, "hide-all-btn"),
|
|
87
|
+
_jsx(InvertButton, { viewport: viewport, models: availableModels, density: props.density }, "invert-all-btn"),
|
|
88
|
+
_jsx(View2DButton, { viewport: viewport, models: availableModels, density: props.density }, "view-2d-btn"),
|
|
89
|
+
_jsx(View3DButton, { viewport: viewport, models: availableModels, density: props.density }, "view-3d-btn"),
|
|
90
|
+
] }), _jsx("div", { className: contentClassName, children: _jsx(AutoSizer, { children: ({ width, height }) => (_jsx(ModelsTree, { ...props, iModel: iModel, activeView: viewport, width: width, height: height, filterInfo: filterInfo, onFilterApplied: onFilterApplied })) }) })] }));
|
|
89
91
|
}
|
|
90
92
|
function ShowAllButton(props) {
|
|
91
|
-
return (_jsx(IconButton, { size: "small", styleType: "borderless", title: TreeWidget.translate("showAll"), onClick: () => void showAllModels(props.models.map((model) => model.id), props.viewport), children: _jsx(SvgVisibilityShow, {}) }));
|
|
93
|
+
return (_jsx(IconButton, { size: props.density === "enlarged" ? "large" : "small", styleType: "borderless", title: TreeWidget.translate("showAll"), onClick: () => void showAllModels(props.models.map((model) => model.id), props.viewport), children: _jsx(SvgVisibilityShow, {}) }));
|
|
92
94
|
}
|
|
93
95
|
function HideAllButton(props) {
|
|
94
|
-
return (_jsx(IconButton, { size: "small", styleType: "borderless", title: TreeWidget.translate("hideAll"), onClick: () => void hideAllModels(props.models.map((model) => model.id), props.viewport), children: _jsx(SvgVisibilityHide, {}) }));
|
|
96
|
+
return (_jsx(IconButton, { size: props.density === "enlarged" ? "large" : "small", styleType: "borderless", title: TreeWidget.translate("hideAll"), onClick: () => void hideAllModels(props.models.map((model) => model.id), props.viewport), children: _jsx(SvgVisibilityHide, {}) }));
|
|
95
97
|
}
|
|
96
98
|
function InvertButton(props) {
|
|
97
|
-
return (_jsx(IconButton, { size: "small", styleType: "borderless", title: TreeWidget.translate("invert"), onClick: () => void invertAllModels(props.models.map((model) => model.id), props.viewport), children: _jsx(SvgVisibilityHalf, {}) }));
|
|
99
|
+
return (_jsx(IconButton, { size: props.density === "enlarged" ? "large" : "small", styleType: "borderless", title: TreeWidget.translate("invert"), onClick: () => void invertAllModels(props.models.map((model) => model.id), props.viewport), children: _jsx(SvgVisibilityHalf, {}) }));
|
|
98
100
|
}
|
|
99
101
|
function View2DButton(props) {
|
|
100
102
|
const models2d = useMemo(() => {
|
|
@@ -105,7 +107,7 @@ function View2DButton(props) {
|
|
|
105
107
|
setIs2dToggleActive(areAllModelsVisible(models2d, props.viewport));
|
|
106
108
|
return props.viewport.onViewedModelsChanged.addListener((vp) => setIs2dToggleActive(areAllModelsVisible(models2d, vp)));
|
|
107
109
|
}, [models2d, props.viewport]);
|
|
108
|
-
return (_jsx(Button, { size: "small", styleType: "borderless", title: TreeWidget.translate("toggle2DViews"), onClick: () => void toggleModels(models2d, is2dToggleActive, props.viewport), disabled: models2d.length === 0, endIcon: is2dToggleActive ? _jsx(SvgVisibilityShow, {}) : _jsx(SvgVisibilityHide, {}), children: TreeWidget.translate("label2D") }));
|
|
110
|
+
return (_jsx(Button, { size: props.density === "enlarged" ? "large" : "small", styleType: "borderless", title: TreeWidget.translate("toggle2DViews"), onClick: () => void toggleModels(models2d, is2dToggleActive, props.viewport), disabled: models2d.length === 0, endIcon: is2dToggleActive ? _jsx(SvgVisibilityShow, {}) : _jsx(SvgVisibilityHide, {}), children: TreeWidget.translate("label2D") }));
|
|
109
111
|
}
|
|
110
112
|
function View3DButton(props) {
|
|
111
113
|
const models3d = useMemo(() => {
|
|
@@ -116,6 +118,6 @@ function View3DButton(props) {
|
|
|
116
118
|
setIs3dToggleActive(areAllModelsVisible(models3d, props.viewport));
|
|
117
119
|
return props.viewport.onViewedModelsChanged.addListener((vp) => setIs3dToggleActive(areAllModelsVisible(models3d, vp)));
|
|
118
120
|
}, [models3d, props.viewport]);
|
|
119
|
-
return (_jsx(Button, { size: "small", styleType: "borderless", title: TreeWidget.translate("toggle3DViews"), onClick: () => void toggleModels(models3d, is3dToggleActive, props.viewport), disabled: models3d.length === 0, endIcon: is3dToggleActive ? _jsx(SvgVisibilityShow, {}) : _jsx(SvgVisibilityHide, {}), children: TreeWidget.translate("label3D") }));
|
|
121
|
+
return (_jsx(Button, { size: props.density === "enlarged" ? "large" : "small", styleType: "borderless", title: TreeWidget.translate("toggle3DViews"), onClick: () => void toggleModels(models3d, is3dToggleActive, props.viewport), disabled: models3d.length === 0, endIcon: is3dToggleActive ? _jsx(SvgVisibilityShow, {}) : _jsx(SvgVisibilityHide, {}), children: TreeWidget.translate("label3D") }));
|
|
120
122
|
}
|
|
121
123
|
//# sourceMappingURL=ModelsTreeComponent.js.map
|